/**
 * Flock get-a-quote 表单交互 — 匿名录制路径 + 登录后 Quick 路径
 */
import type { Page } from "playwright";
import {
  clickFirstVisibleFromSpecs,
  fillFirstVisibleFromSpecs,
  parseSelectorSpecs,
} from "@/lib/rpa/selector-specs";
import {
  fillFlockField,
  getFlockSelectorSpecs,
} from "@/lib/rpa/flock-selector-specs";
import { getFlockFieldPauseMs, getFlockFormWaitMs } from "@/lib/flock/env";
import { waitWithFlockStallWatch } from "@/workers/rpa/flock/stall-watch";
import { isFlockQuoteLimitReached } from "@/workers/rpa/flock/page-state";
import { flockLocatorCount } from "@/workers/rpa/flock/page-alive";
import {
  clickFlockLoggedInQuoteSubmit,
  fillFlockLoggedInQuoteForm,
  isFlockLoggedInQuoteForm,
} from "@/workers/rpa/flock/logged-in-form";
import type { FlockQuoteInput } from "@/workers/rpa/flock/types";

const DISPLAY_DATE_RE = /^(\d{2})\/(\d{2})\/(\d{4})$/;
const FIELD_WAIT_MS = 20_000;

function fieldPauseMs(): number {
  return getFlockFieldPauseMs();
}

async function fillTextboxByNames(
  page: Page,
  names: Array<string | RegExp>,
  value: string,
): Promise<boolean> {
  for (const name of names) {
    const loc = page.getByRole("textbox", { name }).first();
    try {
      await loc.waitFor({ state: "visible", timeout: FIELD_WAIT_MS });
      await loc.fill(value);
      return true;
    } catch {
      continue;
    }
  }
  return false;
}

async function fillWithEnvOrRecording(
  page: Page,
  envKey: string,
  recordingNames: Array<string | RegExp>,
  value: string,
): Promise<boolean> {
  const envSpecs = parseSelectorSpecs(process.env[envKey]);
  if (envSpecs.length > 0) {
    const ok = await fillFirstVisibleFromSpecs(page, envSpecs, value, {
      retries: 3,
    });
    if (ok) return true;
  }

  if (await fillTextboxByNames(page, recordingNames, value)) {
    return true;
  }

  return fillFlockField(page, envKey, value);
}

/** 等待查价表单挂载（React hydration）；遇上限页立即失败 */
export async function waitForFlockQuoteForm(page: Page): Promise<boolean> {
  async function formReady(): Promise<boolean> {
    if (await isFlockQuoteLimitReached(page)) {
      return false;
    }
    if (await isFlockLoggedInQuoteForm(page)) {
      return true;
    }
    const markers = [
      page.getByRole("textbox", { name: /Pickup ZIP Code/i }),
      page.getByRole("textbox", { name: /Delivery ZIP Code/i }),
      page.getByTestId(
        "anonymous_marketing_lead_quote_request_page__quote_request__submit_button",
      ),
    ];
    for (const loc of markers) {
      if (
        (await flockLocatorCount(loc)) > 0 &&
        (await loc.first().isVisible().catch(() => false))
      ) {
        return true;
      }
    }
    return false;
  }

  const { ok } = await waitWithFlockStallWatch(page, "等待查价表单", formReady, {
    timeoutMs: getFlockFormWaitMs(),
    pollMs: 400,
  });
  return ok;
}

/** 日历选日：录制为 Choose date → gridcell */
export async function fillFlockPickupDate(
  page: Page,
  pickupDateDisplay: string,
): Promise<boolean> {
  const m = DISPLAY_DATE_RE.exec(pickupDateDisplay.trim());
  if (!m) {
    return fillWithEnvOrRecording(
      page,
      "FLOCK_SELECTOR_PICKUP_DATE",
      [/Shipment Pickup/i, /Pickup Date/i, /取货日期/i],
      pickupDateDisplay,
    );
  }

  const dayRaw = m[2]!;
  const dayNum = String(Number(dayRaw));

  const dateBtn = page
    .getByRole("button", { name: /Choose date|选择日期/i })
    .first();
  if ((await flockLocatorCount(dateBtn)) > 0) {
    await dateBtn.click().catch(() => undefined);
    await page.waitForTimeout(400);

    for (const dayLabel of [dayNum, dayRaw]) {
      const cell = page.getByRole("gridcell", { name: dayLabel }).first();
      if ((await flockLocatorCount(cell)) > 0) {
        await cell.click();
        return true;
      }
    }
  }

  return fillWithEnvOrRecording(
    page,
    "FLOCK_SELECTOR_PICKUP_DATE",
    [/Shipment Pickup/i, /Pickup Date/i, /取货日期/i],
    pickupDateDisplay,
  );
}

/** 按录制顺序填写查价表单（自动识别匿名 / 登录后 Quick） */
export async function fillFlockQuoteForm(
  page: Page,
  input: FlockQuoteInput,
): Promise<{ ok: boolean; error?: string }> {
  if (
    input.formMode === "logged_in_quick" ||
    (await isFlockLoggedInQuoteForm(page))
  ) {
    console.log(
      "[flock-form] 登录后 Quick 表单路径（对齐 quote-request-quick-form__submit_button）",
    );
    return fillFlockLoggedInQuoteForm(page, input);
  }

  const fields: Array<{
    envKey: string;
    names: Array<string | RegExp>;
    value: string;
    label: string;
  }> = [
    {
      envKey: "FLOCK_SELECTOR_PICKUP_ZIP",
      names: ["Pickup ZIP Code", /Pickup ZIP/i, /取件.*ZIP/i],
      value: input.pickupZip,
      label: "取件 ZIP",
    },
    {
      envKey: "FLOCK_SELECTOR_DELIVERY_ZIP",
      names: ["Delivery ZIP Code", /Delivery ZIP/i, /投递.*ZIP/i],
      value: input.deliveryZip,
      label: "投递 ZIP",
    },
    {
      envKey: "FLOCK_SELECTOR_PALLET_COUNT",
      names: ["Number of pallets", /Quantity/i, /pallets/i, /托盘/i],
      value: String(input.palletCount),
      label: "托盘数",
    },
    {
      envKey: "FLOCK_SELECTOR_TOTAL_WEIGHT",
      names: [
        "Total shipment weight (lbs)",
        /Total Weight \(lbs\)/i,
        /Total shipment weight/i,
        /总.*重/i,
      ],
      value: String(input.totalWeightLb),
      label: "总重量",
    },
    {
      envKey: "FLOCK_SELECTOR_LENGTH",
      names: ["Length (in)", /Length/i, /长度/i],
      value: String(input.lengthIn),
      label: "长度",
    },
    {
      envKey: "FLOCK_SELECTOR_WIDTH",
      names: ["Width (in)", /Width/i, /宽度/i],
      value: String(input.widthIn),
      label: "宽度",
    },
    {
      envKey: "FLOCK_SELECTOR_HEIGHT",
      names: ["Height (in)", /Height/i, /高度/i],
      value: String(input.heightIn),
      label: "高度",
    },
  ];

  if (
    !(await fillWithEnvOrRecording(
      page,
      fields[0]!.envKey,
      fields[0]!.names,
      fields[0]!.value,
    ))
  ) {
    return { ok: false, error: "QUOTE_ENTRY_UNAVAILABLE：无法定位取件 ZIP" };
  }
  if (fieldPauseMs() > 0) {
    await page.waitForTimeout(fieldPauseMs());
  }

  if (!(await fillFlockPickupDate(page, input.pickupDate))) {
    return { ok: false, error: "QUOTE_ENTRY_UNAVAILABLE：无法填写取货日期" };
  }
  if (fieldPauseMs() > 0) {
    await page.waitForTimeout(fieldPauseMs());
  }

  for (const field of fields.slice(1)) {
    if (
      !(await fillWithEnvOrRecording(
        page,
        field.envKey,
        field.names,
        field.value,
      ))
    ) {
      return {
        ok: false,
        error: `QUOTE_ENTRY_UNAVAILABLE：无法定位${field.label}`,
      };
    }
    if (fieldPauseMs() > 0) {
      await page.waitForTimeout(fieldPauseMs());
    }
  }

  return { ok: true };
}

export async function clickFlockQuoteSubmit(page: Page): Promise<boolean> {
  if (await clickFlockLoggedInQuoteSubmit(page)) {
    return true;
  }
  const testId = page.getByTestId(
    "anonymous_marketing_lead_quote_request_page__quote_request__submit_button",
  );
  if ((await flockLocatorCount(testId)) > 0) {
    await testId.first().click();
    return true;
  }
  return clickFirstVisibleFromSpecs(
    page,
    getFlockSelectorSpecs("FLOCK_SELECTOR_NEXT"),
  );
}

/** 结果页「Build another quote」或回入口 */
export async function navigateFlockNewQuote(
  page: Page,
  quoteUrl: string,
): Promise<void> {
  const buildAnother = page
    .getByRole("link", { name: /Build another quote/i })
    .first();
  if ((await flockLocatorCount(buildAnother)) > 0) {
    await buildAnother.click();
    await page.waitForLoadState("domcontentloaded").catch(() => undefined);
    await page.waitForTimeout(2_000);
    return;
  }
  const { gotoWithResilience } = await import("@/lib/rpa/page-goto");
  await gotoWithResilience(page, quoteUrl);
}
