import "@mantine/core/styles.css";
import "@mantine/dropzone/styles.css";
import "./styles/index.css";

import React, { useEffect } from "react";
import ReactDOM from "react-dom/client";
import {
    MantineProvider,
    createTheme,
    type MantineColorsTuple,
} from "@mantine/core";
import { RouterProvider, createRouter } from "@tanstack/react-router";
import { ToastViewport } from "./ui/feedback";
import { routeTree } from "./routeTree.gen";
import { useAppStore, type ThemeMode } from "./store";
import { bootstrapAuth } from "./features/auth/auth";
import { startCjkAutospace } from "./utils/cjkAutospace";
import { initDesktopMenuBridge, isDesktop, loadDesktopSettings } from "./net/desktop";

// Mantine 需要 10 阶静态色，硬编码值与 tokens.semantic.css 的 --accent-* 阶
// 严格对齐（Dracula Purple 谱）。组件颜色仍读 var(--accent)，这里仅满足
// Mantine 内部 primaryColor 索引。
//
// primaryShade = { light: 7, dark: 4 }：
//   - light 取 [7] = #644AC9（Alucard Purple）
//   - dark  取 [4] = #AA99FF（Dracula Base BrightBlue，Purple 的官方亮版,
//     在深色背景上对比度 6.7:1，作链接/选中文字可读性达 AAA Large）
const accentTuple: MantineColorsTuple = [
    "#F3F0FF",
    "#E4DEFF",
    "#C9BEFF",
    "#AC9BFE",
    "#AA99FF",
    "#9580FF",
    "#7458EE",
    "#644AC9",
    "#523CA8",
    "#3F2D85",
];

const theme = createTheme({
    primaryColor: "accent",
    primaryShade: { light: 7, dark: 4 },
    defaultRadius: "md",
    radius: { sm: "6px", md: "10px", lg: "14px" },
    fontFamily: "var(--font-sans)",
    fontFamilyMonospace: "var(--font-mono)",
    headings: { fontFamily: "var(--font-sans)" },
    colors: { accent: accentTuple },
});

const router = createRouter({ routeTree, defaultPreload: "intent" });

// 桌面端：菜单栏「设置」→ 路由到 /settings（浏览器里为 no-op）。
initDesktopMenuBridge(() => { void router.navigate({ to: "/settings" }); });
// 桌面端：启动即加载本地配置，把剪贴板同步开关应用到门控（浏览器里为 no-op）。
void loadDesktopSettings();

// Cmd+,（macOS）/ Ctrl+,（Windows·Linux）→ 打开设置，桌面与浏览器通用。桌面端
// 原生菜单未占用 ⌘,，故按键会落到 WebView 由此处理；未登录时 /settings 守卫会
// 自行重定向，无需额外判断。
window.addEventListener("keydown", (e) =>
{
    if ((e.metaKey || e.ctrlKey) && !e.altKey && e.key === ",")
    {
        e.preventDefault();
        void router.navigate({ to: "/settings" });
    }
});

declare module "@tanstack/react-router"
{
    interface Register
    {
        router: typeof router;
    }
}

// system 模式：移除 data-theme attribute，让 tokens.semantic.css 中的
// @media (prefers-color-scheme: dark) 接管；light / dark 时写死 attribute。
function applyTheme(mode: ThemeMode): void
{
    const root = document.documentElement;
    if (mode === "system") { root.removeAttribute("data-theme"); }
    else { root.setAttribute("data-theme", mode); }
}

// 切语言时给 RouterProvider 换 key 强制全树重挂载，让所有 t() 调用以新 locale
// 重新求值；t() 仍是纯函数，避免改造每个调用点。这样比 location.reload() 安全
// （内存里的 refresh_token 不丢）。
function App()
{
    const locale = useAppStore((s) => s.locale);
    const theme$ = useAppStore((s) => s.theme);

    useEffect(() => { applyTheme(theme$); }, [ theme$ ]);

    // Mantine 自身也维护 colorScheme（决定 [data-mantine-color-scheme]）。
    // light / dark 用 forceColorScheme 锁死；system 时不传 force，让其
    // 内部跟随 prefers-color-scheme。store.theme 作为单一来源同步双方。
    const force = theme$ === "system" ? undefined : theme$;

    return (
        <MantineProvider
            theme={theme}
            defaultColorScheme="auto"
            forceColorScheme={force}
        >
            <ToastViewport />
            <RouterProvider key={locale} router={router} />
        </MantineProvider>
    );
}

// 首屏在 React 挂载前先应用一次主题，避免 FOUC。桌面壳的登录态已在 store 初始化
// 时从注入的 window.__CDROP_BOOT__ 同步水合（store/helpers.ts），无需异步等待。
applyTheme(useAppStore.getState().theme);

function mount(): void
{
    ReactDOM.createRoot(document.getElementById("root")!).render(
        <React.StrictMode>
            <App />
        </React.StrictMode>,
    );
    // CJK 自动间距 shim：在 React 完成首次挂载后启动。MutationObserver 后续
    // 增量处理 React 重渲染产生的新文本节点。放在 createRoot 之后,首帧绘制
    // 完会触发一次 runShim() 处理已挂载的子树。
    requestAnimationFrame(() => { startCjkAutospace(); });
}

// 浏览器端「免重登」：首屏渲染前用 HttpOnly cookie 尝试静默续期。命中则直接以已
// 登录态挂载，避免登录页 / 设置页闪现；未命中（401）即照常落到登录页。桌面 / dev /
// sessionStorage 已有令牌时 bootstrapAuth 立即返回，几乎无延迟。4s 超时兜底：万一
// refresh 卡死，也不至于把整个应用永久挡在首屏外。
const BOOT_AUTH_TIMEOUT_MS = 4000;
void Promise.race([
    bootstrapAuth().catch(() => { /* ignore：失败即落登录页 */ }),
    new Promise<void>((resolve) => { window.setTimeout(resolve, BOOT_AUTH_TIMEOUT_MS); }),
]).finally(mount);

// PWA service worker：仅在浏览器 + prod 注册。dev 下会干扰 Vite HMR；桌面壳
// （Wails WebView，wails:// / loopback origin）已是原生应用且 SW 行为不可靠，
// 故跳过。SW 只缓存静态壳、绝不拦截 /api（SSE / 剪贴板 / 中继），见 public/sw.js。
if (import.meta.env.PROD && !isDesktop() && "serviceWorker" in navigator)
{
    window.addEventListener("load", () =>
    {
        void navigator.serviceWorker.register("/sw.js").catch(() => {});
    });
}
