import {
  createSignal,
  createEffect,
  onCleanup,
  onMount,
  type VoidComponent,
} from "solid-js";

import Sun from "@icons/sun.svg?raw";
import Moon from "@icons/moon.svg?raw";

export interface ThemeProps {
  theme: "light" | "dark";
  system: "light" | "dark";
}

export const getCurrentTheme = (): ThemeProps => {
  if (
    typeof localStorage !== "undefined" &&
    (localStorage.theme === "dark" ||
      (!("theme" in localStorage) &&
        window.matchMedia("(prefers-color-scheme: dark)")
          .matches))
  ) {
    return {
      theme: "dark",
      system: window.matchMedia("(prefers-color-scheme: dark)")
        .matches
        ? "dark"
        : "light",
    };
  }
  return {
    theme: "light",
    system: window.matchMedia("(prefers-color-scheme: dark)")
      .matches
      ? "dark"
      : "light",
  };
};

const updateTheme = () => {
  document.documentElement.classList.add("changing-theme");
  if (
    localStorage.theme === "dark" ||
    (!("theme" in localStorage) &&
      window.matchMedia("(prefers-color-scheme: dark)").matches)
  ) {
    document.documentElement.classList.add("dark");
  } else {
    document.documentElement.classList.remove("dark");
  }
  requestAnimationFrame(() => {
    requestAnimationFrame(() => {
      document.documentElement.classList.remove("changing-theme");
    });
  });
};

export const ThemeSelect: VoidComponent = () => {
  const [currentTheme, setCurrentTheme] =
    createSignal<ThemeProps>({
      theme: "dark",
      system: "dark",
    });
  const [mounted, setMounted] = createSignal(false);

  const toggleTheme = () => {
    if (!mounted()) return;
    setCurrentTheme(getCurrentTheme());
    if (currentTheme()!.theme !== currentTheme()!.system) {
      localStorage.removeItem("theme");
    } else {
      localStorage.theme =
        currentTheme()!.theme === "dark" ? "light" : "dark";
    }
    updateTheme();
    setCurrentTheme(getCurrentTheme());
  };

  onMount(() => {
    setMounted(true);
    setCurrentTheme(getCurrentTheme());
  });

  createEffect(() => {
    const mediaQuery = window.matchMedia(
      "(prefers-color-scheme: dark)"
    );
    mediaQuery.addEventListener("change", updateTheme);
    window.addEventListener("storage", updateTheme);

    onCleanup(() => {
      mediaQuery.removeEventListener("change", updateTheme);
      window.removeEventListener("storage", updateTheme);
      setMounted(false);
    });
  });

  return (
    <div
      onclick={toggleTheme}
      class="theme-toggle"
      innerHTML={
        (mounted() && currentTheme().theme === "light") ||
          currentTheme().system === "light"
          ? Sun
          : Moon
      }
    />
  );
};
