import type { Page } from "playwright";
import type { AxelSelectionBridge } from "@/workers/rpa/axel-selection-bridge";
import { normalizeAxelPlaceId } from "@/workers/rpa/axel-selection-bridge";

const AXEL_PLACE_BASE = "https://services.mothership.com/axel/location/place/";
const COMMIT_TIMEOUT_MS = 10_000;

/**
 * 在浏览器上下文 GET place 并尝试沿 React Fiber 写入地址（widget 无 Google pac 时的兜底）。
 * 为何：Node 侧 prefetch 不触发 widget 状态机；需在页面内 fetch 才可能被监听。
 */
/** Playwright evaluate 须为可执行 async 函数体，勿用未调用的 function 表达式 */
export const BROWSER_FETCH_AND_INJECT_PLACE = `async (arg) => {
  var sideArg = arg.sideArg;
  var pid = arg.pid;
  var desc = arg.desc;
  var base = arg.base;
  var url = base + encodeURIComponent(pid);
  var res;
  try {
    res = await fetch(url, { credentials: "include", headers: { accept: "application/json" } });
  } catch (e) {
    return { ok: false, reason: "fetch-failed" };
  }
  if (!res.ok) {
    return { ok: false, reason: "http-" + res.status, status: res.status };
  }
  var loc;
  try {
    loc = await res.json();
  } catch (e2) {
    return { ok: false, reason: "json-failed" };
  }
  var widget = document.querySelector("#react-quoter-landing-plugin");
  if (!widget) {
    return { ok: false, reason: "no-widget", status: res.status };
  }
  var fiberKey = Object.keys(widget).find(function(k) {
    return k.indexOf("__reactFiber$") === 0 || k.indexOf("__reactInternalInstance$") === 0;
  });
  if (!fiberKey) {
    return { ok: false, reason: "no-fiber", status: res.status };
  }
  var addressData = {
    placeId: pid,
    location: loc,
    formattedAddress: desc,
    isCommitted: true,
  };
  var stateKey = sideArg === "pickup" ? "pickupAddress" : "deliveryAddress";
  var injected = false;
  var fiber = widget[fiberKey];
  while (fiber) {
    var stateNode = fiber.stateNode;
    if (stateNode && typeof stateNode.setState === "function") {
      var state = stateNode.state || {};
      if (
        "pickupAddress" in state ||
        "deliveryAddress" in state ||
        "pickup" in state ||
        "delivery" in state ||
        "addresses" in state
      ) {
        var patch = {};
        patch[stateKey] = addressData;
        if (sideArg === "delivery" && state.pickupAddress) {
          patch.pickupAddress = state.pickupAddress;
        }
        stateNode.setState(patch);
        injected = true;
        break;
      }
    }
    var props = fiber.memoizedProps || {};
    if (typeof props.onSelect === "function") {
      try {
        props.onSelect({ placeId: pid, description: desc, location: loc });
        injected = true;
        break;
      } catch (e3) {}
    }
    if (typeof props.onAddressSelect === "function") {
      try {
        props.onAddressSelect({ placeId: pid, description: desc, location: loc });
        injected = true;
        break;
      } catch (e4) {}
    }
    fiber = fiber.return;
  }
  return { ok: injected, reason: injected ? "injected" : "inject-failed", status: res.status };
}`;

export async function commitViaBrowserPlaceFetch(
  page: Page,
  bridge: AxelSelectionBridge,
  placeId: string,
  description: string,
  side: "pickup" | "delivery",
): Promise<{ ok: boolean; method: string }> {
  const normalized = normalizeAxelPlaceId(placeId);
  const result = (await page.evaluate(BROWSER_FETCH_AND_INJECT_PLACE, {
    sideArg: side,
    pid: normalized,
    desc: description,
    base: AXEL_PLACE_BASE,
  })) as { ok: boolean; reason?: string; status?: number };

  if (!result?.ok) {
    console.log(
      `[rpa] browser-place-fetch: failed reason=${result?.reason ?? "unknown"} status=${result?.status ?? 0}`,
    );
    return { ok: false, method: "browser-place-fetch" };
  }

  const committed = await bridge.waitForPlaceCommit(normalized, COMMIT_TIMEOUT_MS);
  if (committed) {
    bridge.setPlaceDetails(normalized, {});
    console.log(`[rpa] browser-place-fetch: place/${normalized} status=${result.status}`);
    return { ok: true, method: "browser-place-fetch" };
  }

  bridge.recordPlaceCommit(normalized);
  return { ok: true, method: "browser-place-fetch-inject" };
}
