"use client";

import { createContext, useCallback, useContext, useMemo, useState, type ReactNode } from "react";
import { useRouter } from "next/navigation";
import { translate } from "@/lib/i18n";
import { api } from "@/lib/api-client";
import type { Category } from "@/lib/constants";

export type SessionUser = {
  id: string;
  email: string;
  displayName: string;
  handle: string;
  avatarUrl: string | null;
  role: string;
  emailVerified: boolean;
  language: string;
  theme: string;
};

export type SessionChannel = {
  id: string;
  name: string;
  handle: string;
  avatarUrl: string | null;
  bannerUrl: string | null;
  isVerified: boolean;
  isMonetized: boolean;
};

type Ctx = {
  user: SessionUser | null;
  channel: SessionChannel | null;
  unread: number;
  categories: Category[];
  theme: "dark" | "light";
  lang: string;
  t: (key: string) => string;
  setTheme: (theme: "dark" | "light") => void;
  setLang: (lang: string) => void;
  setUnread: (n: number | ((prev: number) => number)) => void;
  refresh: () => Promise<void>;
  logout: () => Promise<void>;
};

const SessionContext = createContext<Ctx | null>(null);

export function SessionProvider({
  children,
  initialUser,
  initialChannel,
  initialUnread,
  categories,
}: {
  children: ReactNode;
  initialUser: SessionUser | null;
  initialChannel: SessionChannel | null;
  initialUnread: number;
  categories: Category[];
}) {
  const router = useRouter();
  const [user, setUser] = useState(initialUser);
  const [channel, setChannel] = useState(initialChannel);
  const [unread, setUnread] = useState(initialUnread);
  const [theme, setThemeState] = useState<"dark" | "light">(
    initialUser?.theme === "light" || initialUser?.theme === "dark" ? initialUser.theme : "dark",
  );
  const [lang, setLangState] = useState(initialUser?.language ?? "en");

  const setTheme = useCallback(
    (next: "dark" | "light") => {
      setThemeState(next);
      document.documentElement.setAttribute("data-theme", next);
      try {
        localStorage.setItem("playtube-theme", next);
      } catch {}
      if (user) void api("/api/me", { method: "PATCH", json: { theme: next } }).catch(() => undefined);
    },
    [user],
  );

  const setLang = useCallback(
    (next: string) => {
      setLangState(next);
      document.documentElement.setAttribute("lang", next);
      document.documentElement.setAttribute("dir", next === "ar" ? "rtl" : "ltr");
      try {
        localStorage.setItem("playtube-lang", next);
      } catch {}
      if (user) void api("/api/me", { method: "PATCH", json: { language: next } }).catch(() => undefined);
    },
    [user],
  );

  const refresh = useCallback(async () => {
    try {
      const data = await api<{ user: SessionUser | null; channel: SessionChannel | null }>("/api/auth/session");
      setUser(data.user);
      setChannel(data.channel);
    } catch {
      /* ignore */
    }
  }, []);

  const logout = useCallback(async () => {
    await api("/api/auth/logout", { method: "POST" }).catch(() => undefined);
    setUser(null);
    setChannel(null);
    setUnread(0);
    router.push("/");
    router.refresh();
  }, [router]);

  const value = useMemo<Ctx>(
    () => ({
      user,
      channel,
      unread,
      categories,
      theme,
      lang,
      t: (key: string) => translate(lang, key),
      setTheme,
      setLang,
      setUnread,
      refresh,
      logout,
    }),
    [user, channel, unread, categories, theme, lang, setTheme, setLang, refresh, logout],
  );

  return <SessionContext.Provider value={value}>{children}</SessionContext.Provider>;
}

export function useSession(): Ctx {
  const ctx = useContext(SessionContext);
  if (!ctx) throw new Error("useSession must be used inside SessionProvider");
  return ctx;
}
