/**
 * Flock RPA 可观测进度（入库 quotes_json.__flock_progress，轮询回传前端）
 */
export const FLOCK_RPA_STAGES = [
  "queued",
  "lock",
  "login",
  "open_quote",
  "fill_form",
  "submit",
  "wait_quote",
  "done",
] as const;

export type FlockRpaStage = (typeof FLOCK_RPA_STAGES)[number];

export const FLOCK_RPA_STAGE_LABELS: Record<FlockRpaStage, string> = {
  queued: "任务已入队，等待 Worker 领取",
  lock: "获取 Flock 官网互斥锁",
  login: "登录 Flock 官网（填写账密）",
  open_quote: "打开登录态查价页",
  fill_form: "填写 Quick 查价表单",
  submit: "点击生成报价",
  wait_quote: "等待并解析官网报价",
  done: "报价完成",
};

export type FlockProgressPayload = {
  stage: FlockRpaStage;
  label: string;
  at: string;
};

export type FlockStageReporter = (
  stage: FlockRpaStage,
) => void | Promise<void>;

export async function reportFlockStage(
  onStage: FlockStageReporter | undefined,
  stage: FlockRpaStage,
): Promise<void> {
  try {
    await onStage?.(stage);
  } catch {
    /* 进度回写失败不阻断查价 */
  }
}

export function buildFlockProgressPayload(
  stage: FlockRpaStage,
): { __flock_progress: FlockProgressPayload } {
  return {
    __flock_progress: {
      stage,
      label: FLOCK_RPA_STAGE_LABELS[stage],
      at: new Date().toISOString(),
    },
  };
}

export function parseFlockProgress(
  quotesJson: unknown,
): FlockProgressPayload | null {
  if (!quotesJson || typeof quotesJson !== "object") return null;
  const raw = (quotesJson as Record<string, unknown>).__flock_progress;
  if (!raw || typeof raw !== "object") return null;
  const o = raw as Record<string, unknown>;
  const stage = o.stage;
  if (typeof stage !== "string") return null;
  if (!(FLOCK_RPA_STAGES as readonly string[]).includes(stage)) return null;
  const label =
    typeof o.label === "string" && o.label
      ? o.label
      : FLOCK_RPA_STAGE_LABELS[stage as FlockRpaStage];
  return {
    stage: stage as FlockRpaStage,
    label,
    at: typeof o.at === "string" ? o.at : "",
  };
}

/** 根据失败文案定位卡在哪一步；matched=false 表示未识别，勿用返回 stage 覆盖 Worker 进度 */
export function mapFlockErrorToStage(errorMessage?: string | null): {
  stage: FlockRpaStage;
  hint: string;
  matched: boolean;
} {
  const msg = errorMessage ?? "";
  if (/FLOCK_LOGIN_FAILED|无法填写登录表单|账密但解密失败|账号或密码错误|PROVIDER_LOGIN_FAILED/i.test(msg)) {
    return {
      stage: "login",
      hint: "卡在登录：账号或密码可能不正确。请确认承运商账密是否正确，以及修改后是否已在本系统即时保存更新。",
      matched: true,
    };
  }
  if (/SESSION_EXPIRED/i.test(msg)) {
    return {
      stage: "login",
      hint: "卡在登录：会话失效且重登失败。请确认承运商账密是否正确，以及修改后是否已在本系统即时保存更新。",
      matched: true,
    };
  }
  if (/QUOTE_ENTRY_UNAVAILABLE|STRUCT_CHANGE：.*查价|表单未加载/i.test(msg)) {
    return {
      stage: "open_quote",
      hint: "卡在打开查价页：登录后未进入 Let's build a quote，请确认 quote URL 与账密权限。",
      matched: true,
    };
  }
  if (/无法选择|无法填写|无法定位|QUOTE_ENTRY_UNAVAILABLE：无法/i.test(msg)) {
    return {
      stage: "fill_form",
      hint: "卡在填表：某个字段定位失败，请对照官网字段或更新 RPA 选项映射。",
      matched: true,
    };
  }
  if (/未找到提交按钮|Generate my quote/i.test(msg)) {
    return {
      stage: "submit",
      hint: "卡在提交：未找到「Generate my quote」按钮。",
      matched: true,
    };
  }
  if (/FLOCK_RATES_PENDING|still looking for the best rates|约需\s*15\s*分钟/i.test(msg)) {
    return {
      stage: "wait_quote",
      hint: "官网已出单但尚未给出即时报价（仍在寻价约 15 分钟）；本单已结束，请稍后用参考编号回查，勿重复提交。",
      matched: true,
    };
  }
  if (
    /RPA_DATA_INVALID|未拿到报价|flock-stalls|未返回 Flock|报价档位/i.test(msg)
  ) {
    return {
      stage: "wait_quote",
      hint: "卡在取价：已提交但未解析到报价，可查看 .rpa/flock-stalls/ 截图。",
      matched: true,
    };
  }
  if (/FLOCK_QUOTE_LIMIT|Thank you for your interest/i.test(msg)) {
    return {
      stage: "wait_quote",
      hint: "卡在取价：官网报价次数达上限，请换账号或稍后重试。",
      matched: true,
    };
  }
  if (
    /Target (page|closed)|browser.*(closed|disconnected)|Page crashed|Execution context was destroyed|locator\.count|has been closed|BROWSER_CLOSED/i.test(
      msg,
    )
  ) {
    return {
      stage: "wait_quote",
      hint: "卡在取价：浏览器会话中断（关窗竞态/页跳转销毁上下文），请勿手动关窗并重试。",
      matched: true,
    };
  }
  if (/询价超时|请稍后重试（可在进度条|POLL|timeout/i.test(msg)) {
    return {
      stage: "wait_quote",
      hint: "卡在取价：前端轮询超时，Worker 可能仍在跑；请稍候或刷新后查看历史询价。",
      matched: true,
    };
  }
  if (/互斥|exclusive|busy|占锁|防互踩/i.test(msg)) {
    return {
      stage: "lock",
      hint: "卡在互斥锁：其他 Flock 任务正在占用浏览器，请稍候。",
      matched: true,
    };
  }
  // 未识别：禁止默认钉在「互斥锁」（会误导）；保留 wait_quote 作展示用，matched=false 不覆盖 Worker 阶段
  return {
    stage: "wait_quote",
    hint: "查价失败，请根据下方错误明细排查 Worker 与官网状态。",
    matched: false,
  };
}

/** 失败时应否把 progress 写成 mapped.stage（禁止把已走过的阶段回退到 lock） */
export function shouldOverwriteFlockFailureStage(
  currentStage: string | null | undefined,
  mapped: { stage: FlockRpaStage; matched: boolean },
): boolean {
  if (!mapped.matched) {
    return false;
  }
  if (
    !currentStage ||
    !(FLOCK_RPA_STAGES as readonly string[]).includes(currentStage)
  ) {
    return true;
  }
  return (
    flockStageIndex(mapped.stage) >=
    flockStageIndex(currentStage as FlockRpaStage)
  );
}

export function flockStageIndex(stage: FlockRpaStage): number {
  return FLOCK_RPA_STAGES.indexOf(stage);
}
