/**
 * 中控 iframe 壳:顶栏/统计常驻,tab 内容走 /api/embed/page/<tab>.
 * 各 tab 面板常驻 DOM,切换时 show/hide;脚本延后到首次激活,回访零请求.
 */
(function (global) {
  const TAB_PATH = {
    dashboard: "/dashboard",
    key_monitor: "/key_monitor",
    trade: "/trade",
    strategy: "/strategy",
    strategy_records: "/strategy/records",
    options: "/options",
    options_review: "/options/review",
    hedge_plan: "/hedge-plan",
    records: "/records",
    stats: "/stats",
    risk_policy: "/risk_policy",
    env_config: "/env_config",
    settings: "/settings",
  };

  let navToken = 0;
  let loadingTab = false;
  let pendingTabLoad = null;
  const tabPanes = new Map();
  const tabBooted = new Set();

  /** 自带校验后 form.submit() 的表单,勿在捕获阶段再 fetch 一份(会双发 POST) */
  const CUSTOM_SUBMIT_FORM_IDS = new Set(["add-order-form", "key-form", "roll-form"]);

  function isEmbedShell() {
    return document.body && document.body.getAttribute("data-embed-shell") === "1";
  }

  function getTab() {
    try {
      const t = new URLSearchParams(location.search).get("tab");
      if (t) return t;
    } catch (_) {}
    return document.body.getAttribute("data-page") || "trade";
  }

  function listWindowQueryString() {
    if (typeof global.listWindowQueryString === "function") {
      return global.listWindowQueryString();
    }
    return "";
  }

  function pageRoot() {
    return document.getElementById("embed-page-root");
  }

  function setNavActive(tab) {
    document.querySelectorAll(".embed-top-nav [data-embed-tab]").forEach((a) => {
      a.classList.toggle("active", a.getAttribute("data-embed-tab") === tab);
    });
  }

  function pageNavAllowed(tab) {
    if (global.InstanceSettingsPrefs && typeof global.InstanceSettingsPrefs.pageNavAllowed === "function") {
      return global.InstanceSettingsPrefs.pageNavAllowed(tab);
    }
    return true;
  }

  function syncUrl(tab, replace) {
    const q = new URLSearchParams(location.search);
    q.set("tab", tab);
    q.set("embed", "1");
    const qs = q.toString();
    const url = "/embed?" + qs;
    if (replace) history.replaceState({ embedTab: tab }, "", url);
    else history.pushState({ embedTab: tab }, "", url);
  }

  function notifyParentTabSwitch(tab) {
    try {
      window.parent.postMessage({ type: "instance-frame-navigating", embedShellTab: true, tab: tab }, "*");
    } catch (_) {}
  }

  function runPageInit(tab, opts) {
    const options = opts || {};
    const revisit = !!options.revisit;
    document.body.setAttribute("data-page", tab);
    if (!revisit && typeof global.attachListWindowToExports === "function") {
      global.attachListWindowToExports();
    }
    if (tab === "trade") {
      if (!revisit && typeof global.refreshOrderDefaults === "function") global.refreshOrderDefaults();
      if (!revisit && typeof global.initOrderEntryModelSelect === "function") {
        const root = pageRoot() || document;
        global.initOrderEntryModelSelect(root);
      }
      if (!revisit && global.ManualOrderRrPreview && typeof global.ManualOrderRrPreview.wire === "function") {
        global.ManualOrderRrPreview.wire();
      }
    }
    if (!revisit && tab === "key_monitor" && global.KeyMonitorForm && typeof global.KeyMonitorForm.init === "function") {
      global.KeyMonitorForm.init();
    }
    if (tab === "dashboard" && global.InstanceDashboard && typeof global.InstanceDashboard.init === "function") {
      global.InstanceDashboard.init(!!revisit);
    }
    if (!revisit && tab === "strategy" && typeof global.initStrategyRollForm === "function") {
      global.initStrategyRollForm();
    }
    if (tab === "records") {
      if (global.RecordsReviewPage && typeof global.RecordsReviewPage.init === "function") {
        global.RecordsReviewPage.init({ refresh: !!revisit });
      } else {
        if (!revisit && typeof global.loadJournals === "function") global.loadJournals();
        if (!revisit && typeof global.loadReviews === "function") global.loadReviews();
      }
      if (global.InstanceTheme && typeof global.InstanceTheme.initReviewEditModeSync === "function") {
        global.InstanceTheme.initReviewEditModeSync();
      } else if (typeof global.toggleReviewMode === "function") {
        global.toggleReviewMode();
      }
    }
    if (tab === "stats") {
      if (typeof global.initStatsSegmentFromUrl === "function") global.initStatsSegmentFromUrl();
    }
    if (tab === "settings" || tab === "env_config") {
      if (global.InstanceSettingsPrefs) {
        if (typeof global.InstanceSettingsPrefs.bindEvents === "function") {
          global.InstanceSettingsPrefs.bindEvents();
        }
        if (tab === "settings" && typeof global.InstanceSettingsPrefs.loadDisplayPrefsForm === "function") {
          global.InstanceSettingsPrefs.loadDisplayPrefsForm();
        }
        if (tab === "env_config") {
          if (typeof global.InstanceSettingsPrefs.loadEnvConfig === "function") {
            global.InstanceSettingsPrefs.loadEnvConfig();
          }
          if (typeof global.InstanceSettingsPrefs.bindEnvTabs === "function") {
            global.InstanceSettingsPrefs.bindEnvTabs();
          }
        }
      }
    }
    if (!revisit) {
      if (typeof global.refreshAccountSnapshot === "function") {
        global.refreshAccountSnapshot({ silent: true });
      }
      if (typeof global.refreshPriceSnapshotConditional === "function") {
        global.refreshPriceSnapshotConditional();
      }
      if (global.SymbolLivePrice && typeof global.SymbolLivePrice.init === "function") {
        const root = pageRoot() || document;
        global.SymbolLivePrice.init(root);
      }
      if (global.JournalUploadSlots && typeof global.JournalUploadSlots.init === "function") {
        const root = pageRoot() || document;
        global.JournalUploadSlots.init(root);
      }
    }
  }

  function runScripts(container) {
    container.querySelectorAll("script").forEach((old) => {
      const s = document.createElement("script");
      if (old.src) s.src = old.src;
      else s.textContent = old.textContent;
      old.replaceWith(s);
    });
  }

  function showPane(tab) {
    tabPanes.forEach((pane, name) => {
      const on = name === tab;
      pane.hidden = !on;
      pane.classList.toggle("is-active-pane", on);
    });
  }

  function bootPaneScripts(tab) {
    if (tabBooted.has(tab)) return;
    const pane = tabPanes.get(tab);
    if (!pane) return;
    runScripts(pane);
    tabBooted.add(tab);
  }

  function mountPane(tab, html) {
    const root = pageRoot();
    if (!root) return null;
    const existing = tabPanes.get(tab);
    if (existing) existing.remove();

    const pane = document.createElement("div");
    pane.className = "embed-tab-pane";
    pane.setAttribute("data-embed-pane", tab);
    pane.hidden = true;

    const holder = document.createElement("div");
    holder.innerHTML = html;
    while (holder.firstChild) pane.appendChild(holder.firstChild);

    root.appendChild(pane);
    tabPanes.set(tab, pane);
    return pane;
  }

  function initBootPane() {
    const root = pageRoot();
    if (!root || tabPanes.size > 0) return;
    const tab = getTab();
    if (root.querySelector("[data-embed-pane]")) return;
    if (!root.childNodes.length) return;

    const pane = document.createElement("div");
    pane.className = "embed-tab-pane is-active-pane";
    pane.setAttribute("data-embed-pane", tab);
    Array.from(root.childNodes).forEach((node) => pane.appendChild(node));
    root.appendChild(pane);
    tabPanes.set(tab, pane);
    tabBooted.add(tab);
    showPane(tab);
  }

  function embedPageUrl(tab) {
    const qs = listWindowQueryString();
    let url = "/api/embed/page/" + encodeURIComponent(tab);
    const parts = [];
    if (qs) parts.push(qs);
    parts.push("embed=1");
    return url + "?" + parts.join("&");
  }

  async function fetchTabHtml(tab) {
    const r = await fetch(embedPageUrl(tab), {
      credentials: "same-origin",
      headers: { "X-Instance-Soft-Nav": "1" },
    });
    const ct = (r.headers.get("content-type") || "").toLowerCase();
    if (!ct.includes("application/json")) {
      throw new Error("加载失败(HTTP " + r.status + ")");
    }
    const j = await r.json();
    if (!j.ok || !j.html) throw new Error(j.msg || "加载失败");
    return j.html;
  }

  function warmTabCache(tab) {
    if (!tab || tabPanes.has(tab) || loadingTab) return;
    fetchTabHtml(tab)
      .then((html) => {
        if (!tabPanes.has(tab)) mountPane(tab, html);
      })
      .catch(() => {});
  }

  function preloadAllTabs() {
    const tabs = Object.keys(TAB_PATH);
    const current = getTab();
    const heavyLast = new Set(["options", "records", "stats"]);
    const ordered = tabs.filter((t) => t !== current && !heavyLast.has(t))
      .concat(tabs.filter((t) => heavyLast.has(t) && t !== current));
    let idx = 0;
    function step() {
      if (idx >= ordered.length) return;
      const tab = ordered[idx++];
      if (tabPanes.has(tab)) {
        step();
        return;
      }
      fetchTabHtml(tab)
        .then((html) => {
          if (!tabPanes.has(tab)) mountPane(tab, html);
        })
        .catch(() => {})
        .finally(() => {
          setTimeout(step, heavyLast.has(tab) ? 400 : 180);
        });
    }
    const ric = global.requestIdleCallback || function (fn) {
      setTimeout(fn, 2000);
    };
    ric(step);
  }

  function clearTabCache() {
    tabPanes.forEach((pane) => pane.remove());
    tabPanes.clear();
    tabBooted.clear();
  }

  function syncShellChrome(tab) {
    const hideTopBar = tab === "settings" || tab === "risk_policy" || tab === "env_config";
    document.querySelectorAll(".instance-top-bar").forEach((el) => {
      el.hidden = hideTopBar;
    });
  }

  function initPaneThemeToggle(tab) {
    if (tab !== "settings") return;
    const pane = tabPanes.get(tab);
    if (!pane || !global.InstanceTheme) return;
    if (typeof global.InstanceTheme.initToggleUI === "function") {
      global.InstanceTheme.initToggleUI(pane);
    }
    if (typeof global.InstanceTheme.syncToggleUI === "function") {
      global.InstanceTheme.syncToggleUI(pane);
    }
  }

  function activateTab(tab, opts) {
    const options = opts || {};
    const revisit = !!options.revisit;
    const firstBoot = !tabBooted.has(tab);
    syncShellChrome(tab);
    showPane(tab);
    setNavActive(tab);
    if (!options.skipUrl) syncUrl(tab, !!options.replace);
    notifyParentTabSwitch(tab);
    if (firstBoot) {
      bootPaneScripts(tab);
      initPaneThemeToggle(tab);
      runPageInit(tab, { revisit: false });
      return;
    }
    if (revisit) {
      document.body.setAttribute("data-page", tab);
      runPageInit(tab, { revisit: true });
      return;
    }
    runPageInit(tab, { revisit: false });
  }

  async function loadTab(tab, opts) {
    const options = opts || {};
    if (!tab) return;
    if (!pageNavAllowed(tab)) {
      void loadTab("trade", { replace: true });
      return;
    }

    if (tabPanes.has(tab) && !options.force) {
      activateTab(tab, Object.assign({}, options, { revisit: true }));
      return;
    }

    if (loadingTab) {
      pendingTabLoad = { tab: tab, opts: options };
      return;
    }
    const token = ++navToken;
    loadingTab = true;
    try {
      const html = await fetchTabHtml(tab);
      if (token !== navToken) return;
      mountPane(tab, html);
      activateTab(tab, options);
    } catch (e) {
      if (token === navToken) {
        const flash = document.getElementById("embed-flash");
        if (flash) {
          flash.style.display = "";
          flash.textContent = String(e && e.message ? e.message : e);
        }
      }
    } finally {
      if (token === navToken) loadingTab = false;
      if (pendingTabLoad) {
        const pending = pendingTabLoad;
        pendingTabLoad = null;
        if (pending.tab !== tab) void loadTab(pending.tab, pending.opts);
      }
    }
  }

  function reloadCurrentTab() {
    const tab = getTab();
    const pane = tabPanes.get(tab);
    if (pane) pane.remove();
    tabPanes.delete(tab);
    tabBooted.delete(tab);
    return loadTab(tab, { replace: true, skipUrl: true, force: true });
  }

  function postFormAndReload(form, label) {
    if (!form) return Promise.resolve();
    if (global.FormSubmitGuard) {
      if (global.FormSubmitGuard.isLocked(form)) {
        global.FormSubmitGuard.setSubmitLabel(form, label || "提交中…");
      } else {
        global.FormSubmitGuard.lock(form, label || "提交中…");
      }
    }
    const fd = new FormData(form);
    return fetch(form.action, {
      method: form.method || "POST",
      body: fd,
      credentials: "same-origin",
      redirect: "manual",
    })
      .then(() => reloadCurrentTab())
      .catch(() => reloadCurrentTab());
  }

  function patchApplyListWindow() {
    if (typeof global.applyListWindow !== "function") return;
    global.applyListWindow = function embedApplyListWindow() {
      clearTabCache();
      const qs = listWindowQueryString();
      const tab = getTab();
      const q = new URLSearchParams(qs);
      q.set("tab", tab);
      q.set("embed", "1");
      window.location.href = "/embed?" + q.toString();
    };
  }

  function patchHardNavigations() {
    const resubmitPaths =
      /^\/(del_|delete_|add_|stop_|strategy\/|trend_|roll_|cancel_|place_)/;

    document.addEventListener(
      "click",
      (ev) => {
        if (!isEmbedShell()) return;
        const a = ev.target.closest("a[href]");
        if (!a || ev.defaultPrevented) return;
        if (a.closest(".embed-top-nav")) return;
        if (a.hasAttribute("download") || a.target === "_blank") return;
        const raw = a.getAttribute("href");
        if (!raw || raw.startsWith("#") || raw.startsWith("javascript:")) return;
        let url;
        try {
          url = new URL(raw, location.href);
        } catch (_) {
          return;
        }
        if (url.origin !== location.origin) return;
        if (url.pathname.startsWith("/export/") || url.pathname.startsWith("/order_focus") || url.pathname.startsWith("/key_focus")) {
          return;
        }
        if (!resubmitPaths.test(url.pathname)) return;
        ev.preventDefault();
        fetch(url.pathname + url.search, { credentials: "same-origin", redirect: "manual" })
          .then(() => reloadCurrentTab())
          .catch(() => reloadCurrentTab());
      },
      false
    );

    document.addEventListener(
      "submit",
      (ev) => {
        if (!isEmbedShell()) return;
        const form = ev.target;
        if (!(form instanceof HTMLFormElement)) return;
        if (form.method && form.method.toUpperCase() === "GET") return;
        if (CUSTOM_SUBMIT_FORM_IDS.has(form.id)) return;
        ev.preventDefault();
        const fd = new FormData(form);
        fetch(form.action, {
          method: form.method || "POST",
          body: fd,
          credentials: "same-origin",
          redirect: "manual",
        })
          .then(() => reloadCurrentTab())
          .catch(() => reloadCurrentTab());
      },
      true
    );
  }

  function bindNav() {
    document.querySelectorAll(".embed-top-nav [data-embed-tab]").forEach((a) => {
      a.addEventListener("mouseenter", () => {
        warmTabCache(a.getAttribute("data-embed-tab"));
      });
      a.addEventListener("click", (ev) => {
        ev.preventDefault();
        const tab = a.getAttribute("data-embed-tab");
        if (!tab || tab === getTab()) return;
        void loadTab(tab);
      });
    });
    window.addEventListener("popstate", () => {
      const tab = getTab();
      void loadTab(tab, { replace: true, skipUrl: true });
    });
  }

  function boot() {
    if (!isEmbedShell()) return;
    patchApplyListWindow();
    patchHardNavigations();
    initBootPane();
    const bootTab = getTab();
    if (!pageNavAllowed(bootTab)) {
      void loadTab("trade", { replace: true });
      return;
    }
    if (bootTab === "settings") {
      initPaneThemeToggle("settings");
    }
    bindNav();
    syncShellChrome(getTab());
    runPageInit(getTab());
    preloadAllTabs();
    try {
      window.parent.postMessage({ type: "instance-frame-ready" }, "*");
    } catch (_) {}
  }

  global.InstanceEmbed = {
    loadTab,
    reloadCurrentTab,
    getTab,
    postFormAndReload,
    clearTabCache,
  };

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", boot);
  } else {
    boot();
  }
})(typeof window !== "undefined" ? window : globalThis);
