// ============================================================
// ThemeProvider — 主题 Context + Provider + Hook + 工具函数
//
// 桌面端（Electron）使用 View Transitions API 驱动主题切换：
// GPU 合成器截取旧/新两帧做一次 cross-fade，替代 80+ 个
// 独立 CSS 过渡，消除 Electron Chromium 的合成器卡顿。
// 浏览器不支持时回退到 CSS transition 方案。
// ============================================================

import { createContext, useContext, useState, useEffect, useLayoutEffect, useCallback, type ReactNode } from 'react';
import { flushSync } from 'react-dom';
import { ConfigProvider } from 'antd';
import zhCN from 'antd/locale/zh_CN';

import { getThemeConfig } from '@/shared/theme/antd-theme';

// ---------- Context 类型 ----------

export interface ThemeContextValue {
   isDark: boolean;
   toggleTheme: () => void;
   setLight: () => void;
   setDark: () => void;
}

export const ThemeContext = createContext<ThemeContextValue | null>(null);

// ---------- localStorage 工具函数 ----------

export const STORAGE_KEY = 'ele-heixiu-theme';

export function readStoredTheme(): boolean {
   try {
      const stored = localStorage.getItem(STORAGE_KEY);
      if (stored === 'dark') return true;
      if (stored === 'light') return false;
   } catch {
      /* 静默忽略 */
   }
   if (typeof window !== 'undefined' && window.matchMedia) {
      return window.matchMedia('(prefers-color-scheme: dark)').matches;
   }
   return false;
}

export function writeStoredTheme(isDark: boolean): void {
   try {
      localStorage.setItem(STORAGE_KEY, isDark ? 'dark' : 'light');
   } catch {
      /* 静默忽略 */
   }
}

export function applyHtmlTheme(isDark: boolean): void {
   document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');
   if (isDark) {
      document.documentElement.classList.add('dark');
   } else {
      document.documentElement.classList.remove('dark');
   }
}

// ---------- Consumer Hook ----------

export function useTheme(): ThemeContextValue {
   const ctx = useContext(ThemeContext);
   if (!ctx) {
      throw new Error('useTheme() 必须在 <ThemeProvider> 内部调用');
   }
   return ctx;
}

// ---------- Provider 组件 ----------

interface ThemeProviderProps {
   children: ReactNode;
}

/** 检测 View Transitions API 是否可用（Chromium 111+，Electron 28+） */
function supportsViewTransition(): boolean {
   return typeof document !== 'undefined' && 'startViewTransition' in document;
}

export function ThemeProvider({ children }: ThemeProviderProps) {
   const [isDark, setIsDark] = useState<boolean>(readStoredTheme);

   useLayoutEffect(() => {
      applyHtmlTheme(isDark);
   }, [isDark]);

   const toggleTheme = useCallback(() => {
      if (supportsViewTransition()) {
         // View Transitions API：GPU 合成器 cross-fade，1 个动画替代 N 个 CSS 过渡
         document.startViewTransition(() => {
            flushSync(() => {
               setIsDark((prev) => {
                  const next = !prev;
                  writeStoredTheme(next);
                  return next;
               });
            });
         });
      } else {
         // 回退：普通 React 状态更新 + CSS transition
         setIsDark((prev) => {
            const next = !prev;
            writeStoredTheme(next);
            return next;
         });
      }
   }, []);

   const setLight = useCallback(() => {
      if (supportsViewTransition()) {
         document.startViewTransition(() => {
            flushSync(() => {
               setIsDark(false);
               writeStoredTheme(false);
            });
         });
      } else {
         setIsDark(false);
         writeStoredTheme(false);
      }
   }, []);

   const setDark = useCallback(() => {
      if (supportsViewTransition()) {
         document.startViewTransition(() => {
            flushSync(() => {
               setIsDark(true);
               writeStoredTheme(true);
            });
         });
      } else {
         setIsDark(true);
         writeStoredTheme(true);
      }
   }, []);

   // 监听系统主题变化（仅用户从未手动切换时跟随）
   useEffect(() => {
      const mq = window.matchMedia('(prefers-color-scheme: dark)');
      const handleChange = (e: MediaQueryListEvent) => {
         const stored = localStorage.getItem(STORAGE_KEY);
         if (stored === null) {
            setIsDark(e.matches);
         }
      };
      mq.addEventListener('change', handleChange);
      return () => mq.removeEventListener('change', handleChange);
   }, []);

   const ctx: ThemeContextValue = { isDark, toggleTheme, setLight, setDark };

   return (
      <ThemeContext.Provider value={ctx}>
         <ConfigProvider theme={getThemeConfig(isDark)} locale={zhCN}>{children}</ConfigProvider>
      </ThemeContext.Provider>
   );
}
