/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

// eslint-disable-next-line no-unused-vars
import React, { useEffect, useLayoutEffect, useState } from "react";
// eslint-disable-next-line no-unused-vars
import { DocsContainer as BaseContainer } from "@storybook/addon-docs";
import { addons } from "@storybook/preview-api";
import {
  GLOBALS_UPDATED,
  UPDATE_GLOBALS,
  SET_GLOBALS,
} from "@storybook/core-events";
import darkTheme from "./theme-dark.mjs";
import lightTheme from "./theme-light.mjs";

/* -------- helpers -------- */
function getSelectedFromUrl() {
  const g = new URLSearchParams(location.search).get("globals");
  return g?.match(/(?:^|,)theme:([^,]+)/)?.[1] ?? "system"; // 'light' | 'dark' | 'system'
}
function getOsDark() {
  return window.matchMedia("(prefers-color-scheme: dark)").matches;
}
function mergeGlobalsParam(existing, key, value) {
  const parts = (existing || "").split(",").filter(Boolean);
  const map = new Map(parts.map(s => s.split(":")));
  map.set(key, value);
  return [...map.entries()].map(([k, v]) => `${k}:${v}`).join(",");
}
function syncGlobalsUrl(key, value) {
  // update this iframe URL
  try {
    const u = new URL(window.location.href);
    const prev = u.searchParams.get("globals") || "";
    const merged = mergeGlobalsParam(prev, key, value);
    if (merged !== prev) {
      u.searchParams.set("globals", merged);
      window.history.replaceState({}, "", u.toString());
    }
  } catch {}
  // update top/manager URL (same-origin)
  try {
    const topWin = window.parent || window.top;
    const u2 = new URL(topWin.location.href);
    const prev2 = u2.searchParams.get("globals") || "";
    const merged2 = mergeGlobalsParam(prev2, key, value);
    if (merged2 !== prev2) {
      u2.searchParams.set("globals", merged2);
      topWin.history.replaceState({}, "", u2.toString());
    }
  } catch {}
}
function applyDocsDomTheme(dark) {
  const mode = dark ? "dark" : "light";
  const html = document.documentElement;
  html.style.colorScheme = mode; // UA widgets
  html.classList.toggle("dark", dark); // your CSS hook
  const root = document.getElementById("storybook-docs");
  if (root) {
    root.classList.toggle("dark", dark);
  }
}

/* -------- container -------- */
export default function DocsContainer(props) {
  // initial selection from URL; "system" follows OS via mql below
  const [selected, setSelected] = useState(getSelectedFromUrl()); // 'light' | 'dark' | 'system'
  const [osDark, setOsDark] = useState(getOsDark());

  // concrete resolution
  const isDark = selected === "dark" || (selected !== "light" && osDark);

  // apply before paint on initial load + any theme change
  useLayoutEffect(() => {
    applyDocsDomTheme(isDark);
  }, [isDark]);

  // follow OS flips when toolbar = "system"
  useEffect(() => {
    const mql = window.matchMedia("(prefers-color-scheme: dark)");
    const onChange = e => setOsDark(e.matches);
    mql.addEventListener?.("change", onChange) || mql.addListener?.(onChange);
    return () => {
      mql.removeEventListener?.("change", onChange) ||
        mql.removeListener?.(onChange);
    };
  }, []);

  // toolbar changes → sync URL, flip DOM immediately, update state
  useEffect(() => {
    const channel = addons.getChannel();
    const onUpdate = payload => {
      const next = payload?.globals?.theme; // 'light' | 'dark' | 'system'
      if (!next) {
        return;
      }
      syncGlobalsUrl("theme", next); // make refresh consistent
      applyDocsDomTheme(next === "dark" || (next === "system" && getOsDark()));
      setSelected(prev => (prev === next ? prev : next));
    };
    channel.on(SET_GLOBALS, onUpdate);
    channel.on(GLOBALS_UPDATED, onUpdate);
    channel.on(UPDATE_GLOBALS, onUpdate);
    return () => {
      channel.off(SET_GLOBALS, onUpdate);
      channel.off(GLOBALS_UPDATED, onUpdate);
      channel.off(UPDATE_GLOBALS, onUpdate);
    };
  }, []);

  // Storybook theme object (NOT strings)
  const themeObj = isDark ? darkTheme : lightTheme;
  const themeKey = isDark ? "dark" : "light"; // remounts docs subtree when theme flips

  return <BaseContainer key={themeKey} {...props} theme={themeObj} />;
}

/*
 * If your Storybook doesn't export DocsContainer from '@storybook/addon-docs',
 * replace the import with:
 *   import { DocsContainer as BaseContainer } from "@storybook/blocks";
 */
