import { existsSync, readFileSync } from "node:fs";
import { join } from "node:path";

/** 逆向工程辅助：Google Places Autocomplete 探测（headed 调试用） */

const DEFAULT_VERDICT: ReconVerdict = {
  googleMapsLoaded: false,
  triggerAvailable: false,
  autocompleteAccessPath: "not-found",
  pacTargetInputSelector: "",
  reactFiberKey: "not-found",
  widgetComponentName: "unknown",
  widgetStateStructure: {},
  cspRestrictions: "none",
  placeChangedTriggerOk: false,
  verdict: "PLAN_B",
};

/** 读取 headed 逆向产物；缺失时默认 PLAN_B（自绘联想路径） */
export function loadReconVerdict(): ReconVerdict {
  const path = join(process.cwd(), ".rpa", "recon", "verdict.json");
  if (!existsSync(path)) {
    return DEFAULT_VERDICT;
  }
  try {
    return { ...DEFAULT_VERDICT, ...JSON.parse(readFileSync(path, "utf8")) };
  } catch {
    return DEFAULT_VERDICT;
  }
}

export const AUTOCOMPLETE_MONKEY_PATCH_INIT = `(() => {
  if (window.__rpaAutocompletePatched) return;
  window.__rpaAutocompletePatched = true;
  window.__rpaAutocompleteInstances = window.__rpaAutocompleteInstances || [];
  window.__rpaPlaceChangedHandlers = window.__rpaPlaceChangedHandlers || [];
  const waitForGoogle = () => {
    if (typeof google === "undefined" || !google.maps || !google.maps.places || !google.maps.places.Autocomplete) {
      setTimeout(waitForGoogle, 200);
      return;
    }
    const orig = google.maps.places.Autocomplete;
    google.maps.places.Autocomplete = function (...args) {
      const inputEl = args[0] || null;
      const instance = new orig(...args);
      window.__rpaAutocompleteInstances.push(instance);
      if (inputEl) {
        instance.__rpaInputEl = inputEl;
      }
      if (typeof instance.addListener === "function") {
        const origAddListener = instance.addListener.bind(instance);
        instance.addListener = function(eventName, handler) {
          if (eventName === "place_changed" && typeof handler === "function") {
            window.__rpaPlaceChangedHandlers.push({
              instance: instance,
              handler: handler,
              inputEl: inputEl,
            });
          }
          return origAddListener(eventName, handler);
        };
      }
      return instance;
    };
    google.maps.places.Autocomplete.prototype = orig.prototype;
  };
  waitForGoogle();
})();`;

export type ReconVerdict = {
  googleMapsLoaded: boolean;
  triggerAvailable: boolean;
  autocompleteAccessPath: string;
  pacTargetInputSelector: string;
  reactFiberKey: string;
  widgetComponentName: string;
  widgetStateStructure: Record<string, unknown>;
  cspRestrictions: string;
  placeChangedTriggerOk: boolean;
  verdict: "PLAN_A" | "PLAN_B";
};

export const RUN_RECON_PROBE = `() => {
  try {
  const result = {
    googleMapsLoaded: typeof google !== "undefined" && typeof google.maps !== "undefined",
    triggerAvailable: typeof google?.maps?.event?.trigger === "function",
    placesLoaded: typeof google?.maps?.places?.Autocomplete === "function",
    globalAutocompleteVars: [],
    inputProbes: [],
    pacTargetInputSelector: "",
    autocompleteAccessPath: "not-found",
    autocompleteInstanceFound: false,
    reactFiberKey: "not-found",
    widgetComponentName: "unknown",
    widgetStateStructure: {},
    cspRestrictions: "none",
    placeChangedTriggerOk: false,
  };

  if (result.googleMapsLoaded) {
    try {
      result.globalAutocompleteVars = Object.keys(window).filter((k) => {
        try {
          return window[k] instanceof google.maps.places.Autocomplete;
        } catch {
          return false;
        }
      });
    } catch {
      result.globalAutocompleteVars = [];
    }
  }

  const widget = document.querySelector("#react-quoter-landing-plugin");
  if (widget) {
    const fiberKey = Object.keys(widget).find(
      (k) => k.startsWith("__reactFiber$") || k.startsWith("__reactInternalInstance$"),
    );
    if (fiberKey) {
      result.reactFiberKey = fiberKey;
      let fiber = widget[fiberKey];
      const components = [];
      while (fiber) {
        if (fiber.stateNode && typeof fiber.stateNode.setState === "function") {
          const state = fiber.stateNode.state || {};
          const stateKeys = Object.keys(state);
          if (stateKeys.some((k) => /pickup|delivery|address/i.test(k))) {
            result.widgetComponentName =
              fiber.type?.name || fiber.type?.displayName || "unknown";
            result.widgetStateStructure = Object.fromEntries(
              stateKeys
                .filter((k) => /pickup|delivery|address/i.test(k))
                .map((k) => [k, typeof state[k]]),
            );
          }
          components.push({
            name: fiber.type?.name || fiber.type?.displayName || "unknown",
            stateKeys,
          });
        }
        fiber = fiber.return;
      }
    }
  }

  const inputs = widget
    ? Array.from(widget.querySelectorAll('input[type="text"]'))
    : Array.from(document.querySelectorAll('input[type="text"]'));

  for (let i = 0; i < inputs.length; i += 1) {
    const input = inputs[i];
    const gm = Object.keys(input).filter((k) => k.startsWith("gm_"));
    const pac = input.classList.contains("pac-target-input");
    result.inputProbes.push({
      index: i,
      gmKeys: gm.length,
      pacTarget: pac,
      placeholder: input.placeholder || "",
    });
    if (pac && !result.pacTargetInputSelector) {
      result.pacTargetInputSelector = ".pac-target-input";
    }
  }

  if (!result.pacTargetInputSelector && inputs.length > 0) {
    result.pacTargetInputSelector = "#react-quoter-landing-plugin input";
  }

  const resolveInstance = () => {
    const instances = window.__rpaAutocompleteInstances || [];
    if (instances.length > 0) {
      result.autocompleteAccessPath = "window.__rpaAutocompleteInstances";
      return instances[instances.length - 1];
    }
    if (result.globalAutocompleteVars.length > 0) {
      result.autocompleteAccessPath = "window." + result.globalAutocompleteVars[0];
      return window[result.globalAutocompleteVars[0]];
    }
    const pacInput =
      document.querySelector(".pac-target-input") ||
      document.querySelector("#react-quoter-landing-plugin input");
    if (pacInput) {
      for (const key of Object.keys(pacInput)) {
        if (!key.startsWith("gm_")) continue;
        const val = pacInput[key];
        if (val && typeof val.getPlace === "function") {
          result.autocompleteAccessPath = "input[gm_*].getPlace";
          return val;
        }
      }
    }
    return null;
  };

  const instance = resolveInstance();
  result.autocompleteInstanceFound = Boolean(instance);

  const meta = document.querySelector('meta[http-equiv="Content-Security-Policy"]');
  result.cspRestrictions = meta?.content ?? "none";

  if (
    instance &&
    result.triggerAvailable &&
    typeof instance.getPlace === "function"
  ) {
    try {
      const originalGetPlace = instance.getPlace.bind(instance);
      instance.getPlace = () => ({
        place_id: "ChIJReconProbePlaceId0000000",
        formatted_address: "1234 Recon Probe St, Los Angeles, CA",
        name: "1234 Recon Probe St",
        geometry: { location: { lat: () => 34.05, lng: () => -118.25 } },
      });
      google.maps.event.trigger(instance, "place_changed");
      result.placeChangedTriggerOk = true;
      setTimeout(() => {
        instance.getPlace = originalGetPlace;
      }, 50);
    } catch {
      result.placeChangedTriggerOk = false;
    }
  }

  return result;
  } catch (error) {
    return {
      googleMapsLoaded: false,
      triggerAvailable: false,
      placesLoaded: false,
      globalAutocompleteVars: [],
      inputProbes: [],
      pacTargetInputSelector: "",
      autocompleteAccessPath: "not-found",
      autocompleteInstanceFound: false,
      reactFiberKey: "not-found",
      widgetComponentName: "unknown",
      widgetStateStructure: {},
      cspRestrictions: "none",
      placeChangedTriggerOk: false,
      probeError: String(error),
    };
  }
}`;

export function buildVerdict(
  probe: {
    googleMapsLoaded: boolean;
    triggerAvailable: boolean;
    placesLoaded: boolean;
    autocompleteAccessPath: string;
    pacTargetInputSelector: string;
    reactFiberKey: string;
    widgetComponentName: string;
    widgetStateStructure: Record<string, unknown>;
    cspRestrictions: string;
    autocompleteInstanceFound: boolean;
    placeChangedTriggerOk: boolean;
  },
): ReconVerdict {
  const r2Pass =
    probe.googleMapsLoaded && probe.triggerAvailable && probe.placesLoaded;
  const r3Pass = probe.autocompleteInstanceFound;
  const r4Pass = probe.placeChangedTriggerOk;

  let verdict: "PLAN_A" | "PLAN_B" = "PLAN_A";
  if (!r2Pass || !r3Pass || !r4Pass) {
    verdict = "PLAN_B";
  }

  return {
    googleMapsLoaded: probe.googleMapsLoaded,
    triggerAvailable: probe.triggerAvailable,
    autocompleteAccessPath: probe.autocompleteAccessPath,
    pacTargetInputSelector: probe.pacTargetInputSelector,
    reactFiberKey: probe.reactFiberKey,
    widgetComponentName: probe.widgetComponentName,
    widgetStateStructure: probe.widgetStateStructure,
    cspRestrictions: probe.cspRestrictions,
    placeChangedTriggerOk: probe.placeChangedTriggerOk,
    verdict,
  };
}
