"use client";

import {
  createContext,
  useContext,
  useState,
  useEffect,
  type ReactNode,
} from "react";
import { useRouter } from "next/navigation";
import { api, setRefreshCallback } from "@/lib/api";

const ACCESS_KEY_LOCAL = "k-tv-token";
const ACCESS_KEY_SESSION = "k-tv-token-session";
const REFRESH_KEY = "k-tv-refresh-token";

interface AuthContextValue {
  token: string | null;
  refreshToken: string | null;
  /** Always true (lazy init reads storage synchronously) */
  isLoaded: boolean;
  setTokens: (access: string | null, refresh: string | null, remember: boolean) => void;
}

const AuthContext = createContext<AuthContextValue | null>(null);

export function AuthProvider({ children }: { children: ReactNode }) {
  const router = useRouter();

  const [token, setTokenState] = useState<string | null>(() => {
    try {
      return sessionStorage.getItem(ACCESS_KEY_SESSION) ?? localStorage.getItem(ACCESS_KEY_LOCAL);
    } catch {
      return null;
    }
  });

  const [refreshToken, setRefreshTokenState] = useState<string | null>(() => {
    try {
      return localStorage.getItem(REFRESH_KEY);
    } catch {
      return null;
    }
  });

  const setTokens = (access: string | null, refresh: string | null, remember: boolean) => {
    try {
      if (access === null) {
        sessionStorage.removeItem(ACCESS_KEY_SESSION);
        localStorage.removeItem(ACCESS_KEY_LOCAL);
        localStorage.removeItem(REFRESH_KEY);
      } else if (remember) {
        localStorage.setItem(ACCESS_KEY_LOCAL, access);
        sessionStorage.removeItem(ACCESS_KEY_SESSION);
        if (refresh) {
          localStorage.setItem(REFRESH_KEY, refresh);
        } else {
          localStorage.removeItem(REFRESH_KEY);
        }
      } else {
        sessionStorage.setItem(ACCESS_KEY_SESSION, access);
        localStorage.removeItem(ACCESS_KEY_LOCAL);
        localStorage.removeItem(REFRESH_KEY);
      }
    } catch {
      // storage unavailable — state-only fallback
    }
    setTokenState(access);
    setRefreshTokenState(refresh);
  };

  // Wire up the transparent refresh callback in api.ts
  useEffect(() => {
    if (refreshToken) {
      setRefreshCallback(async () => {
        try {
          const data = await api.auth.refresh(refreshToken);
          const newRefresh = data.refresh_token ?? null;
          setTokens(data.access_token, newRefresh, true);
          return data.access_token;
        } catch {
          setTokens(null, null, false);
          router.push("/login");
          return null;
        }
      });
    } else {
      setRefreshCallback(null);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [refreshToken]);

  return (
    <AuthContext.Provider value={{ token, refreshToken, isLoaded: true, setTokens }}>
      {children}
    </AuthContext.Provider>
  );
}

export function useAuthContext() {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error("useAuthContext must be used within AuthProvider");
  return ctx;
}
