/**
 * fix-place 浏览器脚本（纯字符串）。禁止改为 function 传入 page.evaluate。
 */

export const INVOKE_CAPTURED_PLACE_CHANGED = `(arg) => {
  const pid = arg.pid;
  const desc = arg.desc;
  const loc = arg.loc || {};
  const handlers = window.__rpaPlaceChangedHandlers || [];
  if (!handlers.length) {
    return { ok: false, reason: "no-captured-handlers", handlerCount: 0 };
  }
  const active = document.activeElement;
  const lat =
    typeof loc.latitude === "number"
      ? loc.latitude
      : typeof loc.lat === "number"
        ? loc.lat
        : 0;
  const lng =
    typeof loc.longitude === "number"
      ? loc.longitude
      : typeof loc.lng === "number"
        ? loc.lng
        : 0;
  const placePayload = {
    place_id: pid,
    formatted_address: desc,
    name: (desc.split(",")[0] || "").trim(),
    geometry: {
      location: {
        lat: function() { return lat; },
        lng: function() { return lng; },
      },
    },
    address_components: loc.addressComponents || loc.address_components || [],
  };
  const ordered = handlers.slice().reverse();
  const activeInput =
    active && (active.tagName === "INPUT" || active.tagName === "TEXTAREA")
      ? active
      : null;
  const tryInvoke = function(entry) {
    const inst = entry.instance;
    const handler = entry.handler;
    if (!inst || typeof handler !== "function") {
      return { ok: false, reason: "bad-entry" };
    }
    const originalGetPlace =
      typeof inst.getPlace === "function"
        ? inst.getPlace.bind(inst)
        : function() { return {}; };
    inst.getPlace = function() {
      return placePayload;
    };
    try {
      handler.call(inst);
      return { ok: true, reason: "handler-invoked" };
    } catch (e) {
      return { ok: false, reason: "handler-threw:" + String(e) };
    } finally {
      setTimeout(function() {
        inst.getPlace = originalGetPlace;
      }, 120);
    }
  };
  if (activeInput) {
    for (let i = 0; i < ordered.length; i += 1) {
      const entry = ordered[i];
      if (entry.inputEl === activeInput) {
        const result = tryInvoke(entry);
        if (result.ok) {
          return { ok: true, reason: result.reason, handlerCount: handlers.length };
        }
      }
    }
  }
  for (let j = 0; j < ordered.length; j += 1) {
    const fallback = tryInvoke(ordered[j]);
    if (fallback.ok) {
      return { ok: true, reason: fallback.reason, handlerCount: handlers.length };
    }
  }
  return { ok: false, reason: "all-handlers-failed", handlerCount: handlers.length };
}`;

export const TRIGGER_GOOGLE_PLACE_CHANGED = `(arg) => {
  const pid = arg.pid;
  const desc = arg.desc;
  const gmaps = window.google;
  const resolveInstance = function() {
    const instances = window.__rpaAutocompleteInstances || [];
    if (instances.length > 0) {
      return instances[instances.length - 1];
    }
    if (gmaps && gmaps.maps && gmaps.maps.places && gmaps.maps.places.Autocomplete) {
      const AutocompleteCtor = gmaps.maps.places.Autocomplete;
      const globalKeys = Object.keys(window).filter(function(k) {
        try {
          return window[k] instanceof AutocompleteCtor;
        } catch (e) {
          return false;
        }
      });
      if (globalKeys.length > 0) {
        return window[globalKeys[0]];
      }
    }
    const pacInput =
      document.querySelector(".pac-target-input") ||
      document.querySelector("#react-quoter-landing-plugin input");
    if (!pacInput) {
      return null;
    }
    const keys = Object.keys(pacInput);
    for (let i = 0; i < keys.length; i += 1) {
      const key = keys[i];
      if (key.indexOf("gm_") !== 0) continue;
      const val = pacInput[key];
      if (val && typeof val.getPlace === "function") {
        return val;
      }
    }
    return null;
  };
  const autocompleteInstance = resolveInstance();
  if (!autocompleteInstance) {
    return { ok: false, reason: "no-autocomplete-instance" };
  }
  if (!gmaps || !gmaps.maps || !gmaps.maps.event || typeof gmaps.maps.event.trigger !== "function") {
    return { ok: false, reason: "google-maps-unavailable" };
  }
  const originalGetPlace = autocompleteInstance.getPlace.bind(autocompleteInstance);
  autocompleteInstance.getPlace = function() {
    return {
      place_id: pid,
      formatted_address: desc,
      name: desc.split(",")[0],
      geometry: { location: { lat: function() { return 0; }, lng: function() { return 0; } } },
    };
  };
  gmaps.maps.event.trigger(autocompleteInstance, "place_changed");
  setTimeout(function() {
    autocompleteInstance.getPlace = originalGetPlace;
  }, 100);
  return { ok: true, reason: "triggered" };
}`;

export const CHECK_PICKUP_IN_REACT_STATE = `() => {
  const widget = document.querySelector("#react-quoter-landing-plugin");
  if (!widget) return false;
  const fiberKey = Object.keys(widget).find(function(k) {
    return k.indexOf("__reactFiber$") === 0 || k.indexOf("__reactInternalInstance$") === 0;
  });
  if (!fiberKey) return false;
  let fiber = widget[fiberKey];
  while (fiber) {
    const state = fiber.stateNode && fiber.stateNode.state;
    if (state) {
      const pickup = state.pickupAddress || state.pickup || (state.addresses && state.addresses.pickup);
      if (pickup && (pickup.placeId || pickup.formattedAddress)) {
        return true;
      }
    }
    fiber = fiber.return;
  }
  return false;
}`;

export const INJECT_REACT_STATE = `(arg) => {
  const sideArg = arg.sideArg;
  const pid = arg.pid;
  const loc = arg.loc;
  const desc = arg.desc;
  const widget = document.querySelector("#react-quoter-landing-plugin");
  if (!widget) return false;
  const fiberKey = Object.keys(widget).find(function(k) {
    return k.indexOf("__reactFiber$") === 0 || k.indexOf("__reactInternalInstance$") === 0;
  });
  if (!fiberKey) return false;
  let fiber = widget[fiberKey];
  while (fiber) {
    const stateNode = fiber.stateNode;
    if (stateNode && typeof stateNode.setState === "function") {
      const state = stateNode.state;
      if (state && ("pickupAddress" in state || "pickup" in state || "addresses" in state)) {
        const addressData = {
          placeId: pid,
          location: loc,
          formattedAddress: desc,
          isCommitted: true,
        };
        const stateKey = sideArg === "pickup" ? "pickupAddress" : "deliveryAddress";
        stateNode.setState({ [stateKey]: addressData });
        return true;
      }
    }
    fiber = fiber.return;
  }
  return false;
}`;
