import { useCallback, useEffect, useState, useSyncExternalStore } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Bell, Monitor, Pause, Play, RefreshCw, User, X } from "lucide-react";
import { SCHEMES, type Scheme, type ThemePrefs } from "../lib/theme";
import { api, type Me } from "../lib/api";
import {
  configureNotifications,
  getNotifSettings,
  notify,
  type NotifSettings,
} from "../lib/notifications";
import { hintsEnabled, setHintsEnabled, subscribeHints } from "../lib/hints";
import Tooltip from "./Tooltip";

type TabId = "appearance" | "notifications" | "sync" | "account";
const TABS: { id: TabId; label: string; icon: typeof Monitor }[] = [
  { id: "appearance", label: "Appearance", icon: Monitor },
  { id: "notifications", label: "Notifications", icon: Bell },
  { id: "sync", label: "Sync", icon: RefreshCw },
  { id: "account", label: "Account", icon: User },
];

export default function SettingsPanel({
  me,
  theme,
  setTheme,
  view,
  setView,
  onClose,
}: {
  me: Me;
  theme: ThemePrefs;
  setTheme: (t: ThemePrefs) => void;
  view: "grid" | "list";
  setView: (v: "grid" | "list") => void;
  onClose: () => void;
}) {
  const [tab, setTab] = useState<TabId>("appearance");
  const [closing, setClosing] = useState(false);

  const close = useCallback(() => {
    setClosing(true);
    setTimeout(onClose, 190);
  }, [onClose]);

  useEffect(() => {
    function onKey(e: KeyboardEvent) {
      if (e.key === "Escape") close();
    }
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [close]);

  return (
    <div className="fixed inset-0 z-40 flex justify-end">
      <div
        className={`absolute inset-0 bg-black/30 backdrop-blur-lg ${
          closing ? "animate-[overlayOut_0.19s_ease_forwards]" : "animate-[overlayIn_0.2s_ease]"
        }`}
        onClick={close}
      />
      <div
        className={`glass relative self-start m-3 w-[min(94vw,520px)] max-h-[calc(100vh-1.5rem)] rounded-2xl overflow-hidden flex flex-col ${
          closing
            ? "animate-[panelOut_0.19s_ease-in_forwards]"
            : "animate-[panelIn_0.26s_cubic-bezier(0.22,1,0.36,1)]"
        }`}
      >
        <div className="flex items-center justify-between px-4 h-14 border-b border-border/60 shrink-0">
          <div className="text-base font-semibold">Settings</div>
          <button
            onClick={close}
            className="p-2 rounded-lg text-muted hover:text-fg hover:bg-card/60 transition"
          >
            <X className="w-5 h-5" />
          </button>
        </div>

        <div className="flex flex-1 min-h-0">
          {/* Vertical tab rail — never wraps; active is a clear accent pill. */}
          <nav className="w-32 sm:w-36 shrink-0 border-r border-border/60 p-2 flex flex-col gap-1">
            {TABS.map((t) => {
              const active = tab === t.id;
              return (
                <button
                  key={t.id}
                  onClick={() => setTab(t.id)}
                  className={`flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-left transition ${
                    active
                      ? "bg-accent text-accent-fg font-medium shadow-md shadow-accent/20"
                      : "text-muted hover:text-fg hover:bg-card/60"
                  }`}
                >
                  <t.icon className="w-4 h-4 shrink-0" />
                  {t.label}
                </button>
              );
            })}
          </nav>

          {/* All tabs stacked in one grid cell so the panel sizes to the tallest tab
              (stable height, no jump on switch); the active one is shown on top. */}
          <div className="grid flex-1 overflow-y-auto">
            {TABS.map((t) => (
              <div
                key={t.id}
                className={`[grid-area:1/1] p-4 ${
                  tab === t.id ? "" : "invisible pointer-events-none"
                }`}
              >
                {t.id === "appearance" && (
                  <Appearance theme={theme} setTheme={setTheme} view={view} setView={setView} />
                )}
                {t.id === "notifications" && <Notifications />}
                {t.id === "sync" && <Sync me={me} />}
                {t.id === "account" && <Account me={me} />}
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

function Section({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <div className="mb-6">
      <div className="text-xs uppercase tracking-wide text-muted mb-2">{title}</div>
      {children}
    </div>
  );
}

function Row({
  label,
  hint,
  children,
}: {
  label: string;
  hint?: string;
  children: React.ReactNode;
}) {
  return (
    <div className="flex items-center justify-between gap-3 py-1.5 text-sm">
      <Tooltip hint={hint ?? ""}>
        <span
          className={
            hint ? "underline decoration-dotted decoration-muted/40 underline-offset-4 cursor-help" : ""
          }
        >
          {label}
        </span>
      </Tooltip>
      {children}
    </div>
  );
}

function Switch({ checked, onChange }: { checked: boolean; onChange: (v: boolean) => void }) {
  return (
    <button
      type="button"
      onClick={() => onChange(!checked)}
      className={`w-9 h-5 rounded-full transition relative shrink-0 ${checked ? "bg-accent" : "bg-border"}`}
    >
      <span
        className={`absolute top-0.5 w-4 h-4 rounded-full bg-white shadow transition-all ${
          checked ? "left-[18px]" : "left-0.5"
        }`}
      />
    </button>
  );
}

const PERF_KEY = "subfeed.perfMode";

function Appearance({
  theme,
  setTheme,
  view,
  setView,
}: {
  theme: ThemePrefs;
  setTheme: (t: ThemePrefs) => void;
  view: "grid" | "list";
  setView: (v: "grid" | "list") => void;
}) {
  const [perf, setPerf] = useState(() => localStorage.getItem(PERF_KEY) === "1");
  const hints = useSyncExternalStore(subscribeHints, hintsEnabled, hintsEnabled);

  useEffect(() => {
    document.documentElement.dataset.perf = perf ? "1" : "";
  }, [perf]);
  function togglePerf(v: boolean) {
    setPerf(v);
    localStorage.setItem(PERF_KEY, v ? "1" : "0");
    api.savePrefs({ performanceMode: v }).catch(() => {});
  }
  function toggleHints(v: boolean) {
    setHintsEnabled(v);
    api.savePrefs({ hints: v }).catch(() => {});
  }

  return (
    <>
      <Section title="Color scheme">
        <div className="grid grid-cols-4 gap-2">
          {SCHEMES.map((s) => (
            <Tooltip key={s.id} hint={s.name}>
              <button
                onClick={() => setTheme({ ...theme, scheme: s.id as Scheme })}
                className={`h-9 w-full rounded-lg border-2 transition ${
                  theme.scheme === s.id ? "border-fg" : "border-transparent"
                }`}
                style={{ background: s.swatch }}
              />
            </Tooltip>
          ))}
        </div>
      </Section>

      <Section title="Display">
        <Row label="Dark mode">
          <Switch
            checked={theme.mode === "dark"}
            onChange={(v) => setTheme({ ...theme, mode: v ? "dark" : "light" })}
          />
        </Row>
        <Row label="List view" hint="Show the feed as a compact list instead of a grid of cards.">
          <Switch checked={view === "list"} onChange={(v) => setView(v ? "list" : "grid")} />
        </Row>
        <Row
          label="Performance mode"
          hint="Turns off the translucent glass blur and soft shadows for snappier rendering on slower machines."
        >
          <Switch checked={perf} onChange={togglePerf} />
        </Row>
        <Row
          label="Show hints"
          hint="These little hover explanations. Turn them off once you know your way around."
        >
          <Switch checked={hints} onChange={toggleHints} />
        </Row>
      </Section>

      <Section title="Text size">
        <input
          type="range"
          min={0.9}
          max={1.3}
          step={0.02}
          value={theme.fontScale}
          onChange={(e) => setTheme({ ...theme, fontScale: Number(e.target.value) })}
          className="w-full accent-accent"
        />
        <div className="text-right text-xs text-muted">{Math.round(theme.fontScale * 100)}%</div>
      </Section>
    </>
  );
}

function Notifications() {
  const [cfg, setCfg] = useState<NotifSettings>(() => getNotifSettings());
  function update(p: Partial<NotifSettings>) {
    const next = { ...cfg, ...p };
    setCfg(next);
    configureNotifications(next);
    api.savePrefs({ notifications: next }).catch(() => {});
  }
  const autoOn = cfg.durationMs > 0;

  return (
    <Section title="Notifications">
      <Row
        label="Sound on alerts"
        hint="Play a short tone when a notification needs your attention (e.g. errors, prompts)."
      >
        <Switch checked={cfg.sound} onChange={(v) => update({ sound: v })} />
      </Row>
      <Row
        label="Auto-dismiss toasts"
        hint="When off, pop-up toasts stay until you close them. When on, they fade after the set time."
      >
        <Switch checked={autoOn} onChange={(v) => update({ durationMs: v ? 6000 : 0 })} />
      </Row>
      {autoOn && (
        <div className="py-1.5 text-sm">
          <div className="flex items-center justify-between">
            <span className="text-muted text-xs">Dismiss after</span>
            <span className="text-muted text-xs">{(cfg.durationMs / 1000).toFixed(0)}s</span>
          </div>
          <input
            type="range"
            min={2000}
            max={15000}
            step={1000}
            value={cfg.durationMs}
            onChange={(e) => update({ durationMs: Number(e.target.value) })}
            className="w-full accent-accent mt-1"
          />
        </div>
      )}
      <button
        onClick={() =>
          notify({
            level: "info",
            title: "Test notification",
            message: "This is what a notification looks like.",
            sound: true,
          })
        }
        className="mt-2 text-sm text-accent hover:underline"
      >
        Send a test notification
      </button>
    </Section>
  );
}

function Sync({ me }: { me: Me }) {
  const qc = useQueryClient();
  const status = useQuery({ queryKey: ["my-status"], queryFn: api.myStatus });
  const s = status.data;
  const syncSubs = useMutation({
    mutationFn: () => api.syncSubscriptions(),
    onSuccess: (r: { subscriptions?: number }) => {
      qc.invalidateQueries({ queryKey: ["my-status"] });
      qc.invalidateQueries({ queryKey: ["channels"] });
      notify({ level: "success", message: `Synced ${r.subscriptions ?? 0} subscriptions` });
    },
    onError: () => notify({ level: "error", message: "Sync failed" }),
  });
  const pauseResume = useMutation({
    mutationFn: (paused: boolean) => (paused ? api.resumeSync() : api.pauseSync()),
    onSuccess: () => qc.invalidateQueries({ queryKey: ["my-status"] }),
  });

  return (
    <>
      <Section title="My sync status">
        {s ? (
          <div className="space-y-1.5 text-sm">
            <Row label="Channels" hint="How many channels you're subscribed to.">
              {s.channels_total}
            </Row>
            <Row
              label="Recent synced"
              hint="Channels whose recent uploads (~last year) are already in the local database, so they show in your feed."
            >
              {`${s.channels_recent_synced}/${s.channels_total}`}
            </Row>
            <Row
              label="Full history"
              hint="Channels whose entire back-catalog has been fetched. The rest backfill gradually (opt in per channel)."
            >
              {`${s.channels_deep_done}/${s.channels_total}`}
            </Row>
            <Row label="My videos" hint="Total videos available to you across your subscribed channels.">
              {s.my_videos.toLocaleString()}
            </Row>
            <Row
              label="Quota left today"
              hint="Shared YouTube API budget remaining today (resets midnight US Pacific). Backfill yields to it."
            >
              {s.quota_remaining_today.toLocaleString()}
            </Row>
          </div>
        ) : (
          <div className="text-muted text-sm">Loading…</div>
        )}
      </Section>

      <Section title="Actions">
        <Tooltip hint="Re-import your YouTube subscriptions and pull in any newly-followed channels.">
          <button
            onClick={() => syncSubs.mutate()}
            disabled={syncSubs.isPending}
            className="glass-card glass-hover flex items-center gap-2 px-3 py-2 rounded-xl text-sm disabled:opacity-50 transition"
          >
            <RefreshCw className={`w-4 h-4 ${syncSubs.isPending ? "animate-spin" : ""}`} />
            Sync subscriptions
          </button>
        </Tooltip>
      </Section>

      {me.role === "admin" && s && (
        <Section title="Admin">
          <Tooltip hint="Pause or resume the background sync for the whole app (all users).">
            <button
              onClick={() => pauseResume.mutate(s.paused)}
              className="glass-card glass-hover flex items-center gap-2 px-3 py-2 rounded-xl text-sm transition"
            >
              {s.paused ? <Play className="w-4 h-4" /> : <Pause className="w-4 h-4" />}
              {s.paused ? "Resume background sync" : "Pause background sync"}
            </button>
          </Tooltip>
        </Section>
      )}
    </>
  );
}

function Account({ me }: { me: Me }) {
  return (
    <Section title="Account">
      <div className="flex items-center gap-3 mb-3">
        {me.avatar_url ? (
          <img src={me.avatar_url} alt="" className="w-12 h-12 rounded-full" />
        ) : (
          <div className="w-12 h-12 rounded-full bg-card grid place-items-center font-semibold">
            {(me.display_name?.[0] ?? me.email[0] ?? "?").toUpperCase()}
          </div>
        )}
        <div className="min-w-0">
          <div className="font-semibold truncate">{me.display_name ?? me.email.split("@")[0]}</div>
          <div className="text-xs text-muted truncate">{me.email}</div>
          <div className="text-xs text-muted capitalize">{me.role}</div>
        </div>
      </div>
      <p className="text-xs text-muted leading-relaxed">
        Playlist editing &amp; YouTube export, and the admin approval queue, arrive in the next
        phases of this milestone.
      </p>
    </Section>
  );
}
