"use client";

import { useTheme } from "next-themes";
import { useEffect, useRef, useState } from "react";
import { themeToggleDict } from "@/components/theme-toggle/dict";

const themes = [
  { value: "light", label: themeToggleDict.light },
  { value: "dark", label: themeToggleDict.dark },
  { value: "system", label: themeToggleDict.system },
] as const;

type ThemeValue = (typeof themes)[number]["value"];

function getResolvedThemeLabel(resolvedTheme?: string) {
  if (resolvedTheme === "dark") {
    return themeToggleDict.dark;
  }

  if (resolvedTheme === "light") {
    return themeToggleDict.light;
  }

  return resolvedTheme ?? "";
}

function ThemeIcon({ theme }: { theme: ThemeValue }) {
  if (theme === "light") {
    return (
      <svg
        aria-hidden="true"
        className="size-4"
        fill="none"
        viewBox="0 0 24 24"
        stroke="currentColor"
        strokeWidth={1.75}
      >
        <circle cx="12" cy="12" r="4" />
        <path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41" />
      </svg>
    );
  }

  if (theme === "dark") {
    return (
      <svg
        aria-hidden="true"
        className="size-4"
        fill="none"
        viewBox="0 0 24 24"
        stroke="currentColor"
        strokeWidth={1.75}
      >
        <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
      </svg>
    );
  }

  return (
    <svg
      aria-hidden="true"
      className="size-4"
      fill="none"
      viewBox="0 0 24 24"
      stroke="currentColor"
      strokeWidth={1.75}
    >
      <rect x="2" y="3" width="20" height="14" rx="2" />
      <path d="M8 21h8M12 17v4" />
    </svg>
  );
}

type ThemeToggleProps = {
  menuPlacement?: "top" | "bottom";
};

export function ThemeToggle({ menuPlacement = "bottom" }: ThemeToggleProps) {
  const { theme, setTheme, resolvedTheme } = useTheme();
  const [mounted, setMounted] = useState(false);
  const [open, setOpen] = useState(false);
  const menuRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    setMounted(true);
  }, []);

  useEffect(() => {
    if (!open) {
      return;
    }

    const handleClickOutside = (event: MouseEvent) => {
      if (!menuRef.current?.contains(event.target as Node)) {
        setOpen(false);
      }
    };

    const handleEscape = (event: KeyboardEvent) => {
      if (event.key === "Escape") {
        setOpen(false);
      }
    };

    document.addEventListener("mousedown", handleClickOutside);
    document.addEventListener("keydown", handleEscape);

    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
      document.removeEventListener("keydown", handleEscape);
    };
  }, [open]);

  const activeTheme = (theme ?? "system") as ThemeValue;
  const activeLabel =
    activeTheme === "system"
      ? themeToggleDict.systemWithResolved.replace(
          "{resolved}",
          getResolvedThemeLabel(resolvedTheme),
        )
      : themes.find((item) => item.value === activeTheme)?.label ?? themeToggleDict.label;

  if (!mounted) {
    return (
      <button
        type="button"
        className="inline-flex items-center gap-2 rounded-lg border border-border bg-card px-3 py-2 text-sm font-medium text-card-foreground"
        aria-label={themeToggleDict.toggleAriaLabel}
        disabled
      >
        <ThemeIcon theme="system" />
        {themeToggleDict.label}
      </button>
    );
  }

  return (
    <div className="relative" ref={menuRef}>
      <button
        type="button"
        onClick={() => setOpen((current) => !current)}
        aria-expanded={open}
        aria-haspopup="menu"
        aria-label={themeToggleDict.toggleAriaLabel}
        className="inline-flex items-center gap-2 rounded-lg border border-border bg-card px-3 py-2 text-sm font-medium text-card-foreground transition-colors hover:bg-accent hover:text-accent-foreground"
      >
        <ThemeIcon theme={activeTheme} />
        {activeLabel}
      </button>

      {open ? (
        <div
          role="menu"
          className={`absolute start-0 z-50 min-w-40 overflow-hidden rounded-lg border border-border bg-popover p-1 shadow-lg ${
            menuPlacement === "top" ? "bottom-full mb-2" : "top-full mt-2"
          }`}
        >
          {themes.map((item) => {
            const isActive = activeTheme === item.value;

            return (
              <button
                key={item.value}
                type="button"
                role="menuitemradio"
                aria-checked={isActive}
                onClick={() => {
                  setTheme(item.value);
                  setOpen(false);
                }}
                className={`flex w-full items-center gap-2 rounded-md px-3 py-2 text-start text-sm transition-colors ${
                  isActive
                    ? "bg-accent text-accent-foreground"
                    : "text-popover-foreground hover:bg-accent hover:text-accent-foreground"
                }`}
              >
                <ThemeIcon theme={item.value} />
                {item.label}
              </button>
            );
          })}
        </div>
      ) : null}
    </div>
  );
}
