/**
 * 登录后 Quick 表单填完后的页面回读校验（不提交）
 */
import type { Page } from "playwright";
import { FLOCK_LOCATION_ACCESSORIALS } from "@/components/flock/flock-logged-in-quote-form";
import { flockLocationRpaLabels } from "@/lib/flock/logged-in-rpa-options";
import { flockLocatorCount } from "@/workers/rpa/flock/page-alive";

function locationAccessorialFlags(typeId: string): {
  liftgate: boolean;
  inside: boolean;
  palletJack: boolean;
} | null {
  const flags =
    FLOCK_LOCATION_ACCESSORIALS[
      typeId as keyof typeof FLOCK_LOCATION_ACCESSORIALS
    ];
  return flags ?? null;
}

export type LoggedInFormVerifyExpect = {
  pickupTypeId: string;
  deliveryTypeId: string;
  pickupZip: string;
  deliveryZip: string;
  pickupLiftgate?: boolean;
  pickupInside?: boolean;
  pickupPalletJack?: boolean;
  deliveryLiftgate?: boolean;
  deliveryInside?: boolean;
  deliveryPalletJack?: boolean;
};

export type LoggedInFormVerifyIssue = {
  field: string;
  expected: string;
  actual: string;
  analysis: string;
};

async function readComboboxDisplay(
  page: Page,
  fieldName: RegExp,
): Promise<string | null> {
  for (const role of ["combobox", "button"] as const) {
    const loc = page.getByRole(role, { name: fieldName }).first();
    if ((await flockLocatorCount(loc)) === 0) continue;
    const inner = ((await loc.innerText().catch(() => "")) || "").trim();
    if (inner) return inner;
    const input = await loc.inputValue().catch(() => "");
    if (input.trim()) return input.trim();
  }
  return null;
}

async function readTextbox(
  page: Page,
  fieldName: RegExp,
): Promise<string | null> {
  const loc = page.getByRole("textbox", { name: fieldName }).first();
  if ((await flockLocatorCount(loc)) === 0) return null;
  return (await loc.inputValue().catch(() => "")) || null;
}

function matchLocationLabel(
  actual: string | null,
  typeId: string,
): { ok: boolean; expected: string } {
  const candidates = [...flockLocationRpaLabels(typeId)];
  const primary = candidates[0] ?? typeId;
  if (!actual?.trim()) {
    return { ok: false, expected: primary };
  }
  const norm = actual.replace(/\s+/g, " ").trim();
  const ok = candidates.some((c) =>
    norm.toLowerCase().includes(c.toLowerCase()),
  );
  return { ok, expected: candidates.join(" | ") };
}

function pushComboboxIssue(
  issues: LoggedInFormVerifyIssue[],
  side: "Pickup" | "Delivery",
  actual: string | null,
  typeId: string,
): void {
  const { ok, expected } = matchLocationLabel(actual, typeId);
  if (ok) return;
  issues.push({
    field: `${side} Type`,
    expected,
    actual: actual ?? "(空/未读到)",
    analysis:
      actual == null
        ? `官网未出现 ${side} Type 下拉或 RPA 未点开选项；检查 combobox 名称是否仍为「${side} Type *」`
        : `选项文案与映射表不一致：系统 id=${typeId}，请核对 lib/flock/logged-in-rpa-options.ts`,
  });
}

function pushCheckboxIssue(
  issues: LoggedInFormVerifyIssue[],
  field: string,
  want: boolean | undefined,
  visible: boolean,
  checked: boolean | null,
  index: number,
): void {
  if (want === undefined) return;

  if (want && !visible) {
    issues.push({
      field,
      expected: "勾选且可见",
      actual: "页面上无此 checkbox",
      analysis:
        "系统要求勾选，但官网该地点类型区块未渲染此选项；可能类型切换后附属项 DOM 不同步或 selector 索引错误",
    });
    return;
  }

  if (!want && visible && checked === true) {
    issues.push({
      field,
      expected: "不勾选",
      actual: "已勾选",
      analysis:
        "系统未要求勾选，但页面仍为选中态；RPA setCheckbox(false) 未生效或官网默认强制勾选",
    });
    return;
  }

  if (want && visible && checked !== true) {
    issues.push({
      field,
      expected: "已勾选",
      actual: checked === false ? "未勾选" : "状态未知",
      analysis:
        index > 0
          ? `同名 checkbox 第 ${index + 1} 个未命中；提货/派送区 Liftgate 或 Pallet Jack 可能需调整 nth 索引`
          : "RPA applyLoggedInLocationAccessorials 点击失败，或选项在类型切换后才出现需加长等待",
    });
  }
}

/** 填表后回读官网 DOM，对比系统期望 */
export async function verifyLoggedInFormOnPage(
  page: Page,
  expect: LoggedInFormVerifyExpect,
): Promise<{ ok: boolean; issues: LoggedInFormVerifyIssue[] }> {
  const issues: LoggedInFormVerifyIssue[] = [];

  const pickupZip = await readTextbox(page, /Pickup ZIP/i);
  const deliveryZip = await readTextbox(page, /Delivery ZIP/i);
  if (pickupZip?.trim() !== expect.pickupZip) {
    issues.push({
      field: "Pickup ZIP",
      expected: expect.pickupZip,
      actual: pickupZip ?? "(空)",
      analysis: "ZIP 未写入或字段名变化",
    });
  }
  if (deliveryZip?.trim() !== expect.deliveryZip) {
    issues.push({
      field: "Delivery ZIP",
      expected: expect.deliveryZip,
      actual: deliveryZip ?? "(空)",
      analysis: "ZIP 未写入或字段名变化",
    });
  }

  const pickupTypeText = await readComboboxDisplay(page, /Pickup Type/i);
  const deliveryTypeText = await readComboboxDisplay(page, /Delivery Type/i);
  pushComboboxIssue(issues, "Pickup", pickupTypeText, expect.pickupTypeId);
  pushComboboxIssue(issues, "Delivery", deliveryTypeText, expect.deliveryTypeId);

  const pickupFlags = locationAccessorialFlags(expect.pickupTypeId);
  const deliveryFlags = locationAccessorialFlags(expect.deliveryTypeId);

  const liftgatePickup = page.getByRole("checkbox", {
    name: /Liftgate Required for Pickup/i,
  });
  const liftgateDelivery = page.getByRole("checkbox", {
    name: /Liftgate Required for Delivery/i,
  });
  const pallet = page.getByRole("checkbox", {
    name: /Location has Pallet Jack and Forklift/i,
  });
  const palletCount = await flockLocatorCount(pallet);
  // 提货侧无 Pallet 时，nth(0) 实际是派送侧——禁止误读
  const pickupPalletIndex = pickupFlags?.palletJack ? 0 : -1;
  const deliveryPalletIndex = deliveryFlags?.palletJack
    ? pickupFlags?.palletJack && palletCount > 1
      ? 1
      : 0
    : -1;

  const checks: Array<{
    field: string;
    loc: ReturnType<Page["getByRole"]>;
    want: boolean | undefined;
    index: number;
    enabled: boolean;
  }> = [
    {
      field: "Pickup Liftgate",
      loc: liftgatePickup,
      want: expect.pickupLiftgate,
      index: 0,
      enabled: Boolean(pickupFlags?.liftgate),
    },
    {
      field: "Delivery Liftgate",
      loc: liftgateDelivery,
      want: expect.deliveryLiftgate,
      index: 0,
      enabled: Boolean(deliveryFlags?.liftgate),
    },
    {
      field: "Pickup Inside",
      loc: page.getByRole("checkbox", { name: /Inside Pickup/i }),
      want: expect.pickupInside,
      index: 0,
      enabled: Boolean(pickupFlags?.inside),
    },
    {
      field: "Delivery Inside",
      loc: page.getByRole("checkbox", { name: /Inside Delivery/i }),
      want: expect.deliveryInside,
      index: 0,
      enabled: Boolean(deliveryFlags?.inside),
    },
    {
      field: "Pickup Pallet Jack",
      loc: pallet,
      want: expect.pickupPalletJack,
      index: pickupPalletIndex,
      enabled: pickupPalletIndex >= 0,
    },
    {
      field: "Delivery Pallet Jack",
      loc: pallet,
      want: expect.deliveryPalletJack,
      index: deliveryPalletIndex,
      enabled: deliveryPalletIndex >= 0,
    },
  ];

  for (const c of checks) {
    if (!c.enabled || c.want === undefined || c.index < 0) continue;
    const box = c.loc.nth(c.index);
    const visible = (await flockLocatorCount(box)) > 0;
    if (!visible && c.want === false) continue;
    const checked =
      visible ? await box.isChecked().catch(() => false) : null;
    pushCheckboxIssue(issues, c.field, c.want, visible, checked, c.index);
  }

  return { ok: issues.length === 0, issues };
}
