import fs from "node:fs";
import path from "node:path";
import type { Page } from "playwright";
import { RPA_WIDGET_HYDRATION_TIMEOUT_MS } from "@/lib/constants/rpa";
import { getSelector } from "@/lib/rpa/selectors";
import { SCROLL_WIDGET_INTO_VIEW } from "@/workers/rpa/kernel/browser-scripts";
import {
  resolveRPAContext,
  type RPAContext,
} from "@/workers/rpa/kernel/context";

const SCROLL_COOLDOWN_MS = 4_000;
const WIDGET_HYDRATION_POLL_MS = 400;
const PLACES_SCRIPT_TIMEOUT_MS = 20_000;

export type QuoterWidgetHydrationProbe = {
  hydrated: boolean;
  editableSearchInputs: number;
  widgetTextPreview: string;
};

export function isQuoterWidgetHydrated(
  editableSearchInputs: number,
  widgetTextPreview: string,
): boolean {
  const skeletonLike =
    editableSearchInputs === 0 &&
    /sign up and book|get a quote|loading/i.test(widgetTextPreview) &&
    widgetTextPreview.length < 120;

  return editableSearchInputs >= 1 && !skeletonLike;
}

/** 浏览器内探测 quoter widget 是否完成 hydration（非骨架屏） */
export function probeQuoterWidgetHydration(
  widgetSelector: string,
): QuoterWidgetHydrationProbe {
  const widget = document.querySelector(widgetSelector);
  if (!widget) {
    return { hydrated: false, editableSearchInputs: 0, widgetTextPreview: "" };
  }

  const probeText = (
    (widget as HTMLElement).innerText ??
    widget.textContent ??
    ""
  )
    .replace(/\s+/g, " ")
    .trim();

  const searchInputs = widget.querySelectorAll<HTMLElement>(
    'input[placeholder*="Search" i], input[placeholder*="搜索"], [role="textbox"], [role="combobox"] input, input[type="text"]',
  );
  let editableSearchInputs = 0;
  for (const node of searchInputs) {
    const inp =
      node instanceof HTMLInputElement
        ? node
        : node.querySelector<HTMLInputElement>("input");
    const target = inp ?? node;
    const visible = target.offsetParent !== null;
    const editable =
      target instanceof HTMLInputElement
        ? !target.disabled &&
          target.readOnly === false &&
          target.getAttribute("aria-readonly") !== "true"
        : target.getAttribute("aria-disabled") !== "true" &&
          target.getAttribute("contenteditable") !== "false";
    if (visible && editable) {
      editableSearchInputs += 1;
    }
  }

  const hasPickupSection = /从何处取货|pick up from|where to pick up/i.test(
    probeText,
  );
  const skeletonLike =
    editableSearchInputs === 0 &&
    /sign up and book|get a quote|loading/i.test(probeText) &&
    probeText.length < 120;

  return {
    hydrated:
      (editableSearchInputs >= 1 || hasPickupSection) && !skeletonLike,
    editableSearchInputs,
    widgetTextPreview: probeText.slice(0, 220),
  };
}

function resolveCtx(pageOrCtx: Page | RPAContext): RPAContext {
  return resolveRPAContext(pageOrCtx);
}

const HIDE_COOKIE_OVERLAY = `() => {
  var selectors = [
    ".cky-consent-container",
    ".cky-modal",
    "#cookieyes",
    ".cky-overlay",
    "[class*='cookieyes']",
  ];
  selectors.forEach(function(sel) {
    document.querySelectorAll(sel).forEach(function(el) {
      el.style.setProperty("display", "none", "important");
      el.style.setProperty("visibility", "hidden", "important");
      el.style.setProperty("pointer-events", "none", "important");
    });
  });
}`;

/** 关闭 CookieYes / 通用 Cookie 横幅，避免遮挡报价 widget */
export async function dismissCookieConsent(page: Page): Promise<void> {
  const candidates = [
    page.getByRole("button", { name: /^accept$/i }),
    page.getByRole("button", { name: /accept all/i }),
    page.getByRole("button", { name: /全部接受|接受全部/i }),
    page.locator('button:has-text("Accept All")'),
    page.locator('button:has-text("Accept all")'),
    page.locator(".cky-btn-accept"),
    page.locator("#cookieyes button.cky-btn-accept"),
  ];

  for (const loc of candidates) {
    const btn = loc.first();
    if (await btn.isVisible().catch(() => false)) {
      await btn.click({ timeout: 3_000, force: true }).catch(() => undefined);
      await page.waitForTimeout(400);
      await page.evaluate(HIDE_COOKIE_OVERLAY).catch(() => undefined);
      return;
    }
  }

  await page.evaluate(HIDE_COOKIE_OVERLAY).catch(() => undefined);
}

/** 将首页嵌入报价 widget 滚入视口（滚动时间戳存于 ctx，无模块级全局） */
export async function scrollQuoteWidgetIntoView(
  pageOrCtx: Page | RPAContext,
  options?: { force?: boolean },
): Promise<void> {
  const ctx = resolveCtx(pageOrCtx);
  const now = Date.now();
  const last = ctx.getWidgetScrollAt();
  if (!options?.force && now - last < SCROLL_COOLDOWN_MS) {
    return;
  }

  const widget = ctx.selectors.widget(ctx.page);

  await widget
    .scrollIntoViewIfNeeded({ timeout: 10_000 })
    .catch(() => undefined);

  await ctx.exec
    .evaluateOnLocator(widget, SCROLL_WIDGET_INTO_VIEW)
    .catch(() => undefined);

  ctx.setWidgetScrollAt(Date.now());
  await ctx.page.waitForTimeout(150);
}

/** 打开页面后的稳定化：Cookie + 滚动到报价区（入口强制滚一次） */
export async function stabilizeQuoteLandingPage(
  pageOrCtx: Page | RPAContext,
): Promise<void> {
  const ctx = resolveCtx(pageOrCtx);
  await dismissCookieConsent(ctx.page);
  await scrollQuoteWidgetIntoView(ctx, { force: true });
}

async function waitForQuoterAssets(page: Page): Promise<void> {
  await page
    .waitForResponse(
      (response) =>
        /quoter|landing-plugin|mothership.*widget/i.test(response.url()) &&
        response.status() === 200,
      { timeout: RPA_WIDGET_HYDRATION_TIMEOUT_MS },
    )
    .catch(() => undefined);

  await page
    .waitForResponse(
      (response) =>
        response.url().includes("maps.googleapis.com") &&
        response.status() === 200,
      { timeout: PLACES_SCRIPT_TIMEOUT_MS },
    )
    .catch(() => undefined);
}

/** 等待 MotherShip 嵌入 quoter 完成 hydration（可编辑地址框出现） */
export async function waitForQuoterWidgetHydrated(
  page: Page,
  timeoutMs = RPA_WIDGET_HYDRATION_TIMEOUT_MS,
): Promise<QuoterWidgetHydrationProbe> {
  const widgetSelector = getSelector("RPA_SELECTOR_QUOTE_WIDGET");
  await waitForQuoterAssets(page);

  const deadline = Date.now() + timeoutMs;
  let last: QuoterWidgetHydrationProbe = {
    hydrated: false,
    editableSearchInputs: 0,
    widgetTextPreview: "",
  };

  while (Date.now() < deadline) {
    last = await page.evaluate(probeQuoterWidgetHydration, widgetSelector);
    if (last.hydrated) {
      return last;
    }
    await page.waitForTimeout(WIDGET_HYDRATION_POLL_MS);
  }

  return last;
}

/** @deprecated 使用 lib/rpa/env.shouldKeepBrowserOpen */
export { shouldKeepBrowserOpen } from "@/lib/rpa/env";

/** 失败时落盘截图，便于对照 Cookie/滚动/填表阶段 */
export async function captureRpaDebugScreenshot(
  page: Page,
  label: string,
): Promise<void> {
  const dir = path.join(process.cwd(), ".dev", "logs");
  await fs.promises.mkdir(dir, { recursive: true });
  const ts = new Date().toISOString().replace(/[:.]/g, "-");
  const file = path.join(dir, `rpa-${label}-${ts}.png`);
  await page.screenshot({ path: file, fullPage: true }).catch(() => undefined);
}
