import type { ReactNode } from "react";
import { createContext, useState, useEffect, useRef } from "react";

import { apiAccountLoginCreate, apiAccountLogoutCreate } from "@/api/generated/public/account";
import { apiAccountUserMeRetrieve } from "@/api/generated/private/account/account";
import { AUTH_FLAG } from "@/hooks/useAuth";

import type { CustomTokenObtainPair } from "@/api/generated/public/models/customTokenObtainPair";
import type { CustomUser } from "@/api/generated/private/models/customUser";

export interface AuthContextType {
  user: CustomUser | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  login: (payload: CustomTokenObtainPair & { turnstile_token?: string }) => Promise<void>;
  logout: () => Promise<void>;
  refreshUser: () => Promise<void>;
}

export const AuthContext = createContext<AuthContextType | undefined>(undefined);

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<CustomUser | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const initialized = useRef(false);

  const isAuthenticated = !!user;

  async function refreshUser() {
    const wasLoggedIn = localStorage.getItem(AUTH_FLAG);

    if (!wasLoggedIn) {
      setUser(null);
      setIsLoading(false);
      return;
    }

    try {
      const userData = await apiAccountUserMeRetrieve();
      setUser(userData);
    } catch {
      setUser(null);
      localStorage.removeItem(AUTH_FLAG);
    } finally {
      setIsLoading(false);
    }
  }

  useEffect(() => {
    if (!initialized.current) {
      initialized.current = true;
      refreshUser();
    }
  }, []);

  async function login(payload: CustomTokenObtainPair & { turnstile_token?: string }) {
    await apiAccountLoginCreate(payload as CustomTokenObtainPair);
    localStorage.setItem(AUTH_FLAG, "true");
    await refreshUser();
  }

  async function logout() {
    setIsLoading(true);
    try {
      localStorage.removeItem(AUTH_FLAG);
      await apiAccountLogoutCreate();
    } catch (err: any) {
      console.error("Logout error:", err);
    } finally {
      setUser(null);
      setIsLoading(false);
    }
  }

  return (
    <AuthContext.Provider value={{ user, isAuthenticated, isLoading, login, logout, refreshUser }}>
      {children}
    </AuthContext.Provider>
  );
}
