/**
 * 用 page.route + window 钩子捕获 POST /user/quotes body
 */
import fs from "node:fs";
import path from "node:path";
import { resolveFlockQuoteAccount } from "@/lib/flock/resolve-account";
import { getFlockQuoteUrl, getFlockQuoteWaitMs } from "@/lib/flock/env";
import { createRpaBrowserContext } from "@/lib/rpa/browser-context";
import { launchRpaBrowser } from "@/lib/rpa/browser-launch";
import { gotoWithResilience } from "@/lib/rpa/page-goto";
import { DEFAULT_FLOCK_DEMO } from "@/workers/rpa/flock/demo-input";
import {
  clickFlockQuoteSubmit,
  fillFlockQuoteForm,
  waitForFlockQuoteForm,
} from "@/workers/rpa/flock/form-interactions";
import type { FlockQuoteInput } from "@/workers/rpa/flock/types";

const OUT_DIR = path.join(process.cwd(), ".rpa", "flock-network-poc");

async function main(): Promise<void> {
  fs.mkdirSync(OUT_DIR, { recursive: true });
  const input: FlockQuoteInput = {
    pickupDate: DEFAULT_FLOCK_DEMO.pickupDateDisplay,
    pickupZip: DEFAULT_FLOCK_DEMO.pickupZip,
    deliveryZip: DEFAULT_FLOCK_DEMO.deliveryZip,
    palletCount: DEFAULT_FLOCK_DEMO.palletCount,
    totalWeightLb: DEFAULT_FLOCK_DEMO.totalWeightLb,
    lengthIn: DEFAULT_FLOCK_DEMO.lengthIn,
    widthIn: DEFAULT_FLOCK_DEMO.widthIn,
    heightIn: DEFAULT_FLOCK_DEMO.heightIn,
  };
  const account = resolveFlockQuoteAccount(input);
  const captured: string[] = [];

  const browser = await launchRpaBrowser({
    headless: process.env.RPA_HEADLESS !== "false",
    incognito: true,
  });
  try {
    const context = await createRpaBrowserContext(browser);

    await context.addInitScript(() => {
      const w = window as unknown as {
        __flockQuoteBodies?: string[];
      };
      w.__flockQuoteBodies = [];
      const origFetch = window.fetch.bind(window);
      window.fetch = async (...args: Parameters<typeof fetch>) => {
        try {
          const inputArg = args[0];
          const init = args[1];
          const url =
            typeof inputArg === "string"
              ? inputArg
              : inputArg instanceof Request
                ? inputArg.url
                : String(inputArg);
          if (/api\.flockfreight\.com\/user\/quotes/i.test(url)) {
            let bodyText = "";
            if (init?.body) {
              if (typeof init.body === "string") bodyText = init.body;
              else if (init.body instanceof URLSearchParams) {
                bodyText = init.body.toString();
              } else if (init.body instanceof Blob) {
                bodyText = await init.body.text();
              } else {
                bodyText = String(init.body);
              }
            } else if (inputArg instanceof Request) {
              bodyText = await inputArg.clone().text();
            }
            w.__flockQuoteBodies?.push(bodyText);
          }
        } catch {
          /* ignore */
        }
        return origFetch(...args);
      };

      const XO = XMLHttpRequest.prototype.open;
      const XS = XMLHttpRequest.prototype.send;
      XMLHttpRequest.prototype.open = function (
        method: string,
        url: string | URL,
        ...rest: unknown[]
      ) {
        (this as unknown as { __flockUrl?: string }).__flockUrl = String(url);
        return XO.apply(this, [method, url, ...rest] as never);
      };
      XMLHttpRequest.prototype.send = function (body?: Document | XMLHttpRequestBodyInit | null) {
        const url = (this as unknown as { __flockUrl?: string }).__flockUrl ?? "";
        if (/api\.flockfreight\.com\/user\/quotes/i.test(url)) {
          const text =
            typeof body === "string"
              ? body
              : body == null
                ? ""
                : String(body);
          w.__flockQuoteBodies?.push(text);
        }
        return XS.call(this, body);
      };
    });

    await context.route("**/api.flockfreight.com/user/quotes**", async (route) => {
      const req = route.request();
      const post = req.postData();
      if (post) {
        captured.push(post);
        console.log(`[route] bodyLen=${post.length}`);
      } else {
        console.log(`[route] no postData method=${req.method()}`);
      }
      await route.continue();
    });

    const page = await context.newPage();
    await gotoWithResilience(page, getFlockQuoteUrl());
    if (!(await waitForFlockQuoteForm(page))) throw new Error("表单未出现");
    const filled = await fillFlockQuoteForm(page, input);
    if (!filled.ok) throw new Error(filled.error ?? "填表失败");
    if (!(await clickFlockQuoteSubmit(page))) throw new Error("无提交按钮");

    const deadline = Date.now() + getFlockQuoteWaitMs();
    while (Date.now() < deadline) {
      const fromPage = await page.evaluate(() => {
        const w = window as unknown as { __flockQuoteBodies?: string[] };
        return w.__flockQuoteBodies ?? [];
      });
      if (fromPage.length || captured.length) {
        for (const b of fromPage) {
          if (b && !captured.includes(b)) captured.push(b);
        }
        break;
      }
      await page.waitForTimeout(400);
    }
    await page.waitForTimeout(2000);
    const late = await page.evaluate(() => {
      const w = window as unknown as { __flockQuoteBodies?: string[] };
      return w.__flockQuoteBodies ?? [];
    });
    for (const b of late) {
      if (b && !captured.includes(b)) captured.push(b);
    }

    const outPath = path.join(OUT_DIR, "user-quotes-request-body.json");
    fs.writeFileSync(
      outPath,
      JSON.stringify(
        {
          capturedAt: new Date().toISOString(),
          email: account.email,
          bodies: captured,
        },
        null,
        2,
      ),
      "utf8",
    );
    console.log(`wrote ${outPath} count=${captured.length}`);
    if (!captured.length || !captured.some((b) => b.trim())) {
      console.error("仍未捕获到 body");
      process.exit(3);
    }
    console.log(captured.find((b) => b.trim())!.slice(0, 5000));
  } finally {
    await browser.close();
  }
}

main().catch((e) => {
  console.error(e);
  process.exit(1);
});
