import {
  ADDRESS_CANDIDATES_TIMEOUT_MS,
} from "@/lib/constants/rpa";
import type {
  AddressLookupInput,
  MothershipAddressCandidate,
  MothershipCandidatesResult,
} from "@/modules/address/types";
import { RpaError } from "@/modules/rpa/errors";
import { saveQuoteSessionFromContext } from "@/lib/rpa/quote-session-store";
import {
  enumerateAddressCandidates,
  isMotherShipEchoCandidate,
  labelToCandidate,
} from "@/workers/rpa/address-suggestions";
import { openAddressSide, visibleStreetInput } from "@/workers/rpa/address-side";
import { RPAContext } from "@/workers/rpa/kernel/context";
import {
  captureRpaDebugScreenshot,
  dismissCookieConsent,
  scrollQuoteWidgetIntoView,
} from "@/workers/rpa/page-prep";
import { quotePageAdapter } from "@/workers/rpa/quote-page-adapter";
import { parkQuoteSession, canPersistParkedQuoteSession } from "@/workers/rpa/parked-quote-session";
import { isParkedSessionEnabled, shouldKeepBrowserWarm } from "@/lib/rpa/env";
import {
  closeBrowser,
  openQuotePage,
  persistContext,
  withRpaSessionLock,
} from "@/workers/rpa/session-manager";

async function dismissAddressSuggestionDropdown(
  ctx: RPAContext,
): Promise<void> {
  await ctx.page.keyboard.press("Escape").catch(() => undefined);
  await ctx.page.waitForTimeout(150);
}

async function listSideCandidates(
  ctx: RPAContext,
  side: "pickup" | "delivery",
  address: AddressLookupInput,
): Promise<MothershipAddressCandidate[]> {
  await openAddressSide(ctx, side, { enumerationMode: true });

  const input = await visibleStreetInput(ctx, side, {
    deliverySectionOpened: side === "delivery",
    enumerationMode: true,
  });
  if (!input) {
    throw new RpaError(
      "STRUCT_CHANGE",
      `${side === "pickup" ? "提货" : "派送"}地址输入框不可见`,
      { retryable: false },
    );
  }
  if (!(await input.isEditable().catch(() => false))) {
    throw new RpaError(
      "STRUCT_CHANGE",
      `${side === "pickup" ? "提货" : "派送"}地址输入框不可编辑`,
      { retryable: false },
    );
  }

  if (side === "delivery") {
    const current = ((await input.inputValue().catch(() => "")) || "")
      .replace(/\s+/g, " ")
      .trim();
    if (current.length >= 8) {
      await input.fill("").catch(() => undefined);
      await input.press("Control+A").catch(() => undefined);
      await input.press("Backspace").catch(() => undefined);
      await ctx.page.waitForTimeout(150);
    }
  }

  const labels = await enumerateAddressCandidates(ctx.page, input, address);
  console.log(`[DEBUG] ${side} labels (${labels.length}):`, labels.slice(0, 5));
  
  const seen = new Set<string>();
  const candidates: MothershipAddressCandidate[] = [];

  const absorbLabel = (label: string, skipEchoFilter: boolean) => {
    const item = labelToCandidate(label, address);
    if (!item) {
      return;
    }
    if (!skipEchoFilter && isMotherShipEchoCandidate(item, address)) {
      return;
    }
    const key = item.option_id;
    if (seen.has(key)) {
      return;
    }
    seen.add(key);
    candidates.push(item);
  };

  for (const label of labels) {
    absorbLabel(label, false);
  }

  if (candidates.length === 0) {
    for (const label of labels) {
      absorbLabel(label, true);
    }
  }

  if (candidates.length === 0) {
    throw new RpaError(
      "ADDRESS_SUGGESTION_NOT_FOUND",
      `MotherShip 未返回可区分的地址候选项，请检查地址或稍后重试`,
      { retryable: true },
    );
  }

  const streetNum = address.street.match(/^\d+/)?.[0];
  if (streetNum) {
    candidates.sort((a, b) => {
      const aHit = `${a.street} ${a.display_label}`.includes(streetNum) ? 1 : 0;
      const bHit = `${b.street} ${b.display_label}`.includes(streetNum) ? 1 : 0;
      return bHit - aHit;
    });
  }

  // 允许部分解析失败：只要有 1 个以上候选即可继续
  // MotherShip 可能返回不完整的联想（如缺少门牌号），这些会被过滤掉
  if (candidates.length === 1 && labels.length >= 3) {
    console.warn(
      `[candidates] ${side}: ${labels.length} labels 中仅解析出 1 个候选，已跳过无效项`,
      labels,
    );
  }

  await dismissAddressSuggestionDropdown(ctx);
  return candidates;
}

async function fetchMothershipAddressCandidatesInner(input: {
  pickup: AddressLookupInput;
  delivery: AddressLookupInput;
}): Promise<MothershipCandidatesResult> {
  return withRpaSessionLock(async () => {
    let ctx: RPAContext | null = null;
    let page: Awaited<ReturnType<typeof openQuotePage>>["page"] | null = null;
    let context: Awaited<ReturnType<typeof openQuotePage>>["context"] | null =
      null;
    let parked = false;

    try {
      const opened = await openQuotePage(quotePageAdapter, false);
      page = opened.page;
      context = opened.context;
      ctx = RPAContext.fromSession(opened.page, opened.context);

      await quotePageAdapter.preCheck(opened.page);

      const pickup_candidates = await listSideCandidates(
        ctx,
        "pickup",
        input.pickup,
      );
      const delivery_candidates = await listSideCandidates(
        ctx,
        "delivery",
        input.delivery,
      );

      const quote_session_id = await saveQuoteSessionFromContext(
        opened.context,
        {
          pickup: input.pickup,
          delivery: input.delivery,
        },
      );
      await persistContext(opened.context);

      // 用户确认弹窗期间保持同页驻留（仅 worker 进程有效；spawn 子进程无法跨进程复用）
      await dismissCookieConsent(page);
      await scrollQuoteWidgetIntoView(page, { force: true });
      if (isParkedSessionEnabled() && canPersistParkedQuoteSession()) {
        await parkQuoteSession(quote_session_id, page, context);
        parked = true;
        page = null;
        context = null;
      } else {
        console.warn(
          "[candidates] 非 worker 进程，跳过驻留页（询价将重开浏览器）",
        );
      }

      return {
        pickup_candidates,
        delivery_candidates,
        requires_selection: true,
        quote_session_id,
      };
    } catch (error) {
      if (ctx?.page) {
        await captureRpaDebugScreenshot(ctx.page, "address-candidates-failure");
      }
      throw error;
    } finally {
      if (!parked) {
        await page?.close().catch(() => undefined);
        await context?.close().catch(() => undefined);
      }
      if (!shouldKeepBrowserWarm()) {
        await closeBrowser();
      }
    }
  });
}

/** 真实 RPA：枚举 MotherShip 地址联想项（与询价共用 worker / session-manager） */
export async function fetchMothershipAddressCandidates(input: {
  pickup: AddressLookupInput;
  delivery: AddressLookupInput;
}): Promise<MothershipCandidatesResult> {
  let timer: ReturnType<typeof setTimeout> | undefined;
  try {
    return await Promise.race([
      fetchMothershipAddressCandidatesInner(input),
      new Promise<MothershipCandidatesResult>((_, reject) => {
        timer = setTimeout(() => {
          reject(
            new RpaError(
              "PAGE_LOAD_TIMEOUT",
              "MotherShip 地址联想超时，请检查网络或稍后重试",
              { retryable: true },
            ),
          );
        }, ADDRESS_CANDIDATES_TIMEOUT_MS);
      }),
    ]);
  } finally {
    if (timer) {
      clearTimeout(timer);
    }
  }
}
