import { createContext, createEffect, createMemo, createSignal, onMount, useContext, type JSX } from "solid-js"
import { createTheme, ThemeProvider as MuiThemeProvider } from "@suid/material/styles"
import CssBaseline from "@suid/material/CssBaseline"
import { useConfig } from "../stores/preferences"

export type ThemeMode = "system" | "light" | "dark"

interface ThemeContextValue {
  isDark: () => boolean
  themeMode: () => ThemeMode
  setThemeMode: (mode: ThemeMode) => void
  cycleThemeMode: () => void
}

const ThemeContext = createContext<ThemeContextValue>()

function applyThemeMode(mode: ThemeMode) {
  if (typeof document === "undefined") return
  if (mode === "system") {
    document.documentElement.removeAttribute("data-theme")
    return
  }
  document.documentElement.setAttribute("data-theme", mode)
}

interface ResolvedPaletteColors {
  backgroundDefault: string
  backgroundPaper: string
  primary: string
  primaryContrast: string
  textPrimary: string
  textSecondary: string
  divider: string
}

const lightPaletteFallbacks: ResolvedPaletteColors = {
  backgroundDefault: "#ffffff",
  backgroundPaper: "#f5f5f5",
  primary: "#0066ff",
  primaryContrast: "#ffffff",
  textPrimary: "#1a1a1a",
  textSecondary: "#666666",
  divider: "#e0e0e0",
}

const darkPaletteFallbacks: ResolvedPaletteColors = {
  backgroundDefault: "#1a1a1a",
  backgroundPaper: "#2a2a2a",
  primary: "#0080ff",
  primaryContrast: "#1a1a1a",
  textPrimary: "#cfd4dc",
  textSecondary: "#999999",
  divider: "#3a3a3a",
}

const readCssVar = (token: string, fallback: string, rootStyle: CSSStyleDeclaration | null) => {
  if (!rootStyle) return fallback
  const value = rootStyle.getPropertyValue(token)
  if (!value) return fallback
  const trimmed = value.trim()
  return trimmed || fallback
}

const resolvePaletteColors = (dark: boolean): ResolvedPaletteColors => {
  const fallbackSet = dark ? darkPaletteFallbacks : lightPaletteFallbacks
  const rootStyle = typeof window !== "undefined" ? getComputedStyle(document.documentElement) : null

  return {
    backgroundDefault: readCssVar("--surface-base", fallbackSet.backgroundDefault, rootStyle),
    backgroundPaper: readCssVar("--surface-secondary", fallbackSet.backgroundPaper, rootStyle),
    primary: readCssVar("--accent-primary", fallbackSet.primary, rootStyle),
    primaryContrast: readCssVar("--text-inverted", fallbackSet.primaryContrast, rootStyle),
    textPrimary: readCssVar("--text-primary", fallbackSet.textPrimary, rootStyle),
    textSecondary: readCssVar("--text-secondary", fallbackSet.textSecondary, rootStyle),
    divider: readCssVar("--border-base", fallbackSet.divider, rootStyle),
  }
}

export function ThemeProvider(props: { children: JSX.Element }) {
  const mediaQuery = typeof window !== "undefined" ? window.matchMedia("(prefers-color-scheme: dark)") : null
  const { themePreference, setThemePreference } = useConfig()
  const [isDark, setIsDarkSignal] = createSignal(true)
  const [themeRevision, setThemeRevision] = createSignal(0)

  const themeMode = () => themePreference() as ThemeMode

  const resolveDarkTheme = () => {
    const mode = themeMode()
    if (mode === "dark") return true
    if (mode === "light") return false
    return mediaQuery?.matches ?? false
  }

  const applyResolvedTheme = () => {
    const mode = themeMode()
    const dark = resolveDarkTheme()
    if (mode === "system") {
      applyThemeMode("system")
    } else {
      applyThemeMode(mode)
    }
    setIsDarkSignal(dark)
    if (typeof window !== "undefined") {
      requestAnimationFrame(() => setThemeRevision((v) => v + 1))
    } else {
      setThemeRevision((v) => v + 1)
    }
  }

  createEffect(() => {
    applyResolvedTheme()
  })

  onMount(() => {
    if (!mediaQuery) return
    const handleSystemThemeChange = () => {
      applyResolvedTheme()
    }

    mediaQuery.addEventListener("change", handleSystemThemeChange)

    return () => {
      mediaQuery.removeEventListener("change", handleSystemThemeChange)
    }
  })

  const setThemeMode = (mode: ThemeMode) => {
    setThemePreference(mode)
  }

  const cycleThemeMode = () => {
    const current = themeMode()
    const next: ThemeMode = current === "system" ? "light" : current === "light" ? "dark" : "system"
    setThemeMode(next)
  }

  const muiTheme = createMemo(() => {
    themeRevision()
    const paletteColors = resolvePaletteColors(isDark())
    return createTheme({
      palette: {
        mode: isDark() ? "dark" : "light",
        primary: {
          main: paletteColors.primary,
          contrastText: paletteColors.primaryContrast,
        },
        secondary: {
          main: paletteColors.primary,
        },
        background: {
          default: paletteColors.backgroundDefault,
          paper: paletteColors.backgroundPaper,
        },
        text: {
          primary: paletteColors.textPrimary,
          secondary: paletteColors.textSecondary,
        },
        divider: paletteColors.divider,
      },
      typography: {
        fontFamily: "var(--font-family-sans)",
      },
      shape: {
        borderRadius: 8,
      },
      components: {
        MuiIconButton: {
          styleOverrides: {
            root: {
              color: "inherit",
              "&.Mui-disabled": {
                color: "var(--text-muted)",
                opacity: 0.55,
              },
            },
          },
        },
        MuiDrawer: {
          styleOverrides: {
            paper: {
              backgroundColor: "var(--surface-secondary)",
              color: "var(--text-primary)",
            },
          },
        },
        MuiAppBar: {
          styleOverrides: {
            root: {
              backgroundColor: "var(--surface-secondary)",
              color: "var(--text-primary)",
              boxShadow: "none",
              borderBottom: "1px solid var(--border-base)",
              zIndex: 10,
            },
          },
        },
        MuiToolbar: {
          styleOverrides: {
            root: {
              minHeight: "56px",
            },
          },
        },
      } as any,
    })
  })

  return (
    <ThemeContext.Provider value={{ isDark, themeMode, setThemeMode, cycleThemeMode }}>
      <MuiThemeProvider theme={muiTheme()}>
        <CssBaseline />
        {props.children}
      </MuiThemeProvider>
    </ThemeContext.Provider>
  )
}

export function useTheme() {
  const context = useContext(ThemeContext)
  if (!context) {
    throw new Error("useTheme must be used within ThemeProvider")
  }
  return context
}
