import React, { createContext, useContext, useEffect, useState } from "react";
import { tokenStore } from "./token";
import { createApiClient } from "./axios";
import { AuthUser } from "./models";

interface AuthContextModel {
  currentUser: AuthUser | null;
  token: string | null;
  loading: boolean;
  error: string | null;
  login(username: string, password: string): Promise<void>;
  register(username: string, password: string): Promise<void>;
  logout(): void;
}

const AuthContext = createContext<AuthContextModel | undefined>(undefined);

export function AuthProvider({
  children,
  authBaseUrl,
}: {
  children: React.ReactNode;
  authBaseUrl: string;
}) {
  const [currentUser, setCurrentUser] = useState<AuthUser | null>(null);
  const [token, setToken] = useState<string | null>(tokenStore.get());
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const auth = createApiClient(authBaseUrl);

  const login = async (username: string, password: string) => {
    try {
      setLoading(true);
      setError(null);

      const res = await auth.post("/login", { username, password });
      const { access_token, user } = res.data;

      tokenStore.set(access_token);
      setToken(access_token);
      setCurrentUser(user);
    } catch (e: any) {
      setError(e.response?.data?.detail ?? "Login failed");
    } finally {
      setLoading(false);
    }
  };

  const register = async (username: string, password: string) => {
    try {
      setLoading(true);
      setError(null);

      await auth.post("/register", { username, password });
      await login(username, password);
    } catch (e: any) {
      setError(e.response?.data?.detail ?? "Registration failed");
    } finally {
      setLoading(false);
    }
  };

  const logout = () => {
    tokenStore.clear();
    setToken(null);
    setCurrentUser(null);
  };

  const fetchCurrentUser = async () => {
    if (!token) return;
    try {
      const me = await auth.get("/me");
      setCurrentUser({ ...me.data });
    } catch {
      logout();
    }
  };

  useEffect(() => {
    fetchCurrentUser();
  }, [token]);

  return (
    <AuthContext.Provider
      value={{ currentUser, token, loading, error, login, logout, register }}
    >
      {children}
    </AuthContext.Provider>
  );
}

export function useAuth(): AuthContextModel {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error("useAuth must be used inside AuthProvider");
  return ctx;
}
