#!/usr/bin/env tsx
/**
 * 可视全链验收：MotherShip widget 填址 → 货物 → 提交报价（单浏览器 headed）
 *
 * 用法:
 *   npm run visual:quote-full-chain
 *   $env:RPA_HEADLESS="false"; npm run visual:quote-full-chain
 */
import { randomUUID } from "node:crypto";
import { mkdirSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { loadDevEnv } from "@/lib/dev-env";
import { shouldKeepBrowserOpen } from "@/lib/rpa/env";
import { hostFetchMothershipCandidates } from "@/lib/frontend/api-client";
import { applyMothershipCandidate } from "@/lib/frontend/mothership-address";
import { RPAContext } from "@/workers/rpa/kernel/context";
import { runMothershipQuoteKernel } from "@/workers/rpa/kernel/orchestrator";
import {
  stabilizeQuoteLandingPage,
  waitForQuoterWidgetHydrated,
} from "@/workers/rpa/page-prep";
import { closeBrowser, openQuotePage } from "@/workers/rpa/session-manager";
import { quotePageAdapter } from "@/workers/rpa/quote-page-adapter";
import type { QuoteRequest } from "@/modules/providers/quote-provider";

process.env.RPA_MOCK_MODE = "false";
process.env.RPA_ADDRESS_MODE = "real";
process.env.RPA_VISUAL_RUSH = process.env.RPA_VISUAL_RUSH ?? "true";
process.env.RPA_DUAL_ADDRESS_PATCH = process.env.RPA_DUAL_ADDRESS_PATCH ?? "false";
process.env.RPA_DWELL_MS = process.env.RPA_DWELL_MS ?? "3000";
process.env.RPA_HEADLESS = process.env.RPA_HEADLESS ?? "false";
process.env.RPA_SLOW_MO_MS = process.env.RPA_SLOW_MO_MS ?? "0";
process.env.RPA_HUMAN_PACING = process.env.RPA_HUMAN_PACING ?? "false";
process.env.RPA_KEEP_BROWSER_OPEN = process.env.RPA_KEEP_BROWSER_OPEN ?? "true";

loadDevEnv();

const BASE = process.env.PROVE_BASE_URL ?? "http://localhost:3000";
const TOKEN = "demo-host-token";
const CUSTOMER_ID = "CUST_001";

const PAIR = {
  label: "真人录证 5519e0ea：293 Pike St → 826 Ocean Dr",
  pickup: { street: "293 Pike St", city: "Seattle", state: "WA" },
  delivery: { street: "826 Ocean Dr", city: "Miami Beach", state: "FL" },
  cargo: {
    pallet_count: 2,
    weight_lb: 500,
    length_in: 48,
    width_in: 40,
    height_in: 48,
  },
};

function draftAddress(d: { street: string; city: string; state: string }) {
  return {
    street: d.street.trim(),
    city: d.city.trim(),
    state: d.state.trim(),
    zip: "",
    place_id: `draft_${d.street}_${d.city}_${d.state}`.replace(/\s+/g, "_").slice(0, 64),
    formatted_address: `${d.street}, ${d.city}, ${d.state}`,
    selected_from_suggestions: true,
  };
}

async function main(): Promise<void> {
  let opened:
    | Awaited<ReturnType<typeof openQuotePage>>
    | null = null;
  const runId = randomUUID().slice(0, 8);
  const startedAt = Date.now();

  console.log(`[visual] 全链验收 ${runId}：${PAIR.label}`);
  console.log("[visual] 阶段：候选 API → 打开浏览器 → 填址 → 货物 → 报价");
  console.log("[visual] RPA_VISUAL_RUSH=true（跳过锁定/契约闸门，填完即点报价）");

  const userPickup = draftAddress(PAIR.pickup);
  const userDelivery = draftAddress(PAIR.delivery);

  const cand = await hostFetchMothershipCandidates(
    BASE,
    TOKEN,
    CUSTOMER_ID,
    userPickup,
    userDelivery,
  );
  if (cand.code !== 0 || !cand.data?.pickup_candidates[0] || !cand.data.delivery_candidates[0]) {
    throw new Error(cand.message ?? "候选 API 失败（请先 npm run dev:start）");
  }

  const pc = cand.data.pickup_candidates[0];
  const dc = cand.data.delivery_candidates[0];
  const pickupApplied = applyMothershipCandidate(userPickup, pc);
  const deliveryApplied = applyMothershipCandidate(userDelivery, dc);

  const req: QuoteRequest = {
    cargoHash: `visual_${runId}`,
    pickup: {
      street: pickupApplied.street,
      city: pickupApplied.city,
      state: pickupApplied.state,
      zip: pickupApplied.zip ?? "",
      placeId: pc.option_id,
      formattedAddress: pickupApplied.formatted_address,
      selectedFromSuggestions: true,
      mothershipOptionId: pc.option_id,
      mothershipDisplayLabel: pc.display_label,
      selectedFromMothership: true,
    },
    delivery: {
      street: deliveryApplied.street,
      city: deliveryApplied.city,
      state: deliveryApplied.state,
      zip: deliveryApplied.zip ?? "",
      placeId: dc.option_id,
      formattedAddress: deliveryApplied.formatted_address,
      selectedFromSuggestions: true,
      mothershipOptionId: dc.option_id,
      mothershipDisplayLabel: dc.display_label,
      selectedFromMothership: true,
    },
    palletCount: PAIR.cargo.pallet_count,
    weightLb: PAIR.cargo.weight_lb,
    dimsIn: {
      l: PAIR.cargo.length_in,
      w: PAIR.cargo.width_in,
      h: PAIR.cargo.height_in,
    },
    cargoType: "general_freight",
  };

  console.log(`[visual] 提货：${pc.display_label}`);
  console.log(`[visual] 派送：${dc.display_label}`);

  opened = await openQuotePage(quotePageAdapter, false, undefined, {
    freshCargoContext: true,
  });
  const ctx = RPAContext.fromSession(opened.page, opened.context);

  console.log("[visual] 等待 widget 加载…");
  await stabilizeQuoteLandingPage(ctx);
  await waitForQuoterWidgetHydrated(ctx.page, 90_000);

  console.log("[visual] ▶ 开始 kernel：填址（提货 → 派送）…");
  const tAddr = Date.now();
  const items = await runMothershipQuoteKernel(ctx, req);
  const addrMs = Date.now() - tAddr;

  const finalUrl = opened.page.url();
  const report = {
    runId,
    pair: PAIR.label,
    finishedAt: new Date().toISOString(),
    durationMs: Date.now() - startedAt,
    kernelMs: addrMs,
    finalUrl,
    tierCount: items.length,
    tiers: items.map((q) => ({
      tier: `${q.serviceLevel}/${q.rateOption}`,
      final_total: q.rawTotal,
    })),
    verdict:
      items.length >= 4
        ? "PASS"
        : items.length > 0
          ? "PARTIAL"
          : finalUrl.includes("sign-up-quote")
            ? "PASS_PAGE"
            : "FAIL",
  };

  const outDir = join(process.cwd(), ".rpa", "visual-full-chain");
  mkdirSync(outDir, { recursive: true });
  const reportPath = join(outDir, `visual-${runId}.json`);
  writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");

  console.log("\n════════ 可视全链结果 ════════");
  console.log(`档位数量: ${items.length}`);
  for (const q of items.slice(0, 6)) {
    console.log(`  ${q.serviceLevel}/${q.rateOption}: $${q.rawTotal}`);
  }
  console.log(`verdict: ${report.verdict}`);
  console.log(`报告: ${reportPath}`);

  const success =
    report.verdict === "PASS" ||
    report.verdict === "PARTIAL" ||
    report.verdict === "PASS_PAGE";

  if (!shouldKeepBrowserOpen()) {
    const dwellMs = Number(process.env.RPA_DWELL_MS ?? 8_000);
    if (dwellMs > 0) {
      console.log(`[visual] 完成后停留 ${dwellMs}ms 便于核对页面…`);
      await opened.page.waitForTimeout(dwellMs).catch(() => undefined);
    }
    await opened.page.close().catch(() => undefined);
    await opened.context.close().catch(() => undefined);
    await closeBrowser();
    process.exit(success ? 0 : 1);
  }

  console.log("\n[visual] 浏览器保持打开，请核对页面报价。按 Ctrl+C 结束。");
  await new Promise<void>((resolve) => {
    process.once("SIGINT", () => resolve());
    process.once("SIGTERM", () => resolve());
  });
  await opened.page.close().catch(() => undefined);
  await opened.context.close().catch(() => undefined);
  await closeBrowser();
  process.exit(success ? 0 : 1);
}

main().catch(async (e) => {
  console.error(e);
  const dwellMs = Number(process.env.RPA_DWELL_MS ?? 15_000);
  if (process.env.RPA_HEADLESS === "false" && dwellMs > 0) {
    console.log(`[visual] 失败后停留 ${dwellMs}ms，便于观察卡点…`);
    await new Promise((resolve) => setTimeout(resolve, dwellMs));
  }
  process.exit(1);
});
