export type SearchStageTimingStatus = "running" | "completed" | "failed" | "paused" | "stopped";

export type SearchStageTimingInput = {
  task_id?: string | null;
  taskId?: string | null;
  material_id?: string | null;
  materialId?: string | null;
  material_name?: string | null;
  materialName?: string | null;
  stage_order?: number | null;
  stageOrder?: number | null;
  stage_label?: string | null;
  stageLabel?: string | null;
  stage_kind?: string | null;
  stageKind?: string | null;
  started_at?: string | null;
  startedAt?: string | null;
  ended_at?: string | null;
  endedAt?: string | null;
  duration_ms?: number | null;
  durationMs?: number | null;
  status?: string | null;
};

export type SearchStageTiming = {
  taskId: string;
  materialId: string;
  materialName: string;
  stageOrder: number | null;
  stageLabel: string;
  stageKind: string;
  startedAt: string;
  endedAt: string | null;
  durationMs: number | null;
  elapsedMs: number;
  status: SearchStageTimingStatus;
};

export type SearchStageTimingSnapshot = {
  currentStage: SearchStageTiming | null;
  completedStages: SearchStageTiming[];
  totalElapsedMs: number | null;
};

function normalizeText(value: unknown) {
  return String(value ?? "").trim();
}

function normalizeDate(value: unknown) {
  const text = normalizeText(value);
  if (!text) return null;
  const parsed = Date.parse(text);
  return Number.isFinite(parsed) ? new Date(parsed).toISOString() : null;
}

function normalizeNonNegativeNumber(value: unknown) {
  if (value == null || value === "") return null;
  const numeric = Number(value);
  return Number.isFinite(numeric) && numeric >= 0 ? Math.round(numeric) : null;
}

function normalizeStageStatus(value: unknown, endedAt: string | null): SearchStageTimingStatus {
  const status = normalizeText(value);
  if (status === "failed" || status === "paused" || status === "stopped" || status === "completed") {
    return status;
  }
  return endedAt ? "completed" : "running";
}

function elapsedFromDates(startedAt: string, endedAt: string | null) {
  const start = Date.parse(startedAt);
  const end = endedAt ? Date.parse(endedAt) : Date.now();
  if (!Number.isFinite(start) || !Number.isFinite(end)) return 0;
  return Math.max(0, Math.round(end - start));
}

export function normalizeSearchStageTiming(input: SearchStageTimingInput | null | undefined): SearchStageTiming | null {
  if (!input) return null;

  const startedAt = normalizeDate(input.started_at ?? input.startedAt);
  if (!startedAt) return null;

  const endedAt = normalizeDate(input.ended_at ?? input.endedAt);
  const durationMs = normalizeNonNegativeNumber(input.duration_ms ?? input.durationMs);
  const elapsedMs = durationMs ?? elapsedFromDates(startedAt, endedAt);

  return {
    taskId: normalizeText(input.task_id ?? input.taskId),
    materialId: normalizeText(input.material_id ?? input.materialId),
    materialName: normalizeText(input.material_name ?? input.materialName),
    stageOrder: normalizeNonNegativeNumber(input.stage_order ?? input.stageOrder),
    stageLabel: normalizeText(input.stage_label ?? input.stageLabel),
    stageKind: normalizeText(input.stage_kind ?? input.stageKind),
    startedAt,
    endedAt,
    durationMs,
    elapsedMs,
    status: normalizeStageStatus(input.status, endedAt),
  };
}

export function buildSearchStageTimingSnapshot(params: {
  startedAt?: string | null;
  finishedAt?: string | null;
  searchProgress?: (SearchStageTimingInput & { stageStartedAt?: string | null }) | null;
  completedStages?: SearchStageTimingInput[] | null;
}): SearchStageTimingSnapshot {
  const currentStage = normalizeSearchStageTiming(params.searchProgress
    ? {
        ...params.searchProgress,
        startedAt: params.searchProgress.startedAt ?? params.searchProgress.stageStartedAt,
      }
    : null);
  const completedStages = (params.completedStages ?? [])
    .map((stage) => normalizeSearchStageTiming(stage))
    .filter((stage): stage is SearchStageTiming => Boolean(stage));

  const taskStartedAt = normalizeDate(params.startedAt);
  const taskFinishedAt = normalizeDate(params.finishedAt);
  const totalElapsedMs = taskStartedAt
    ? elapsedFromDates(taskStartedAt, taskFinishedAt)
    : null;

  return {
    currentStage,
    completedStages,
    totalElapsedMs,
  };
}

export function formatDurationMs(value: number | null | undefined) {
  const duration = normalizeNonNegativeNumber(value);
  if (duration == null) return "-";

  const totalSeconds = Math.max(0, Math.floor(duration / 1000));
  const minutes = Math.floor(totalSeconds / 60);
  const seconds = totalSeconds % 60;
  if (minutes > 0) {
    return `${minutes}分${String(seconds).padStart(2, "0")}秒`;
  }
  return `${seconds}秒`;
}
