import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
import { apiRequest, clearTokens, getAccessToken, setTokens, setUnauthorizedHandler } from "../api/client";

export type MemberMe = {
  tenant_id: string;
  uid: string;
  email: string;
  display_name?: string;
  status: string;
  roles?: string[];
};

type AuthContextValue = {
  member: MemberMe | null;
  loading: boolean;
  login: (tenantId: string, email: string, password: string) => Promise<void>;
  register: (tenantId: string, email: string, password: string, displayName?: string) => Promise<void>;
  logout: () => Promise<void>;
  reloadMember: () => Promise<void>;
};

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

type TokenPair = {
  access_token: string;
  refresh_token: string;
};

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [member, setMember] = useState<MemberMe | null>(null);
  const [loading, setLoading] = useState(true);

  const reloadMember = useCallback(async () => {
    if (!getAccessToken()) {
      setMember(null);
      setLoading(false);
      return;
    }
    setLoading(true);
    try {
      const data = await apiRequest<MemberMe>("/api/v1/members/me", { auth: true });
      setMember(data);
    } catch {
      clearTokens();
      setMember(null);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    setUnauthorizedHandler(() => {
      clearTokens();
      setMember(null);
    });
    void reloadMember();
    return () => setUnauthorizedHandler(undefined);
  }, [reloadMember]);

  const login = useCallback(
    async (tenantId: string, email: string, password: string) => {
      const data = await apiRequest<TokenPair>("/api/v1/auth/login", {
        method: "POST",
        body: { tenant_id: tenantId, email, password }
      });
      setTokens(data.access_token, data.refresh_token);
      await reloadMember();
    },
    [reloadMember]
  );

  const register = useCallback(
    async (tenantId: string, email: string, password: string, displayName?: string) => {
      const data = await apiRequest<TokenPair>("/api/v1/auth/register", {
        method: "POST",
        body: { tenant_id: tenantId, email, password, display_name: displayName }
      });
      setTokens(data.access_token, data.refresh_token);
      await reloadMember();
    },
    [reloadMember]
  );

  const logout = useCallback(async () => {
    try {
      await apiRequest<null>("/api/v1/auth/logout", { method: "POST", auth: true });
    } catch {
      // Local logout still needs to complete if the server token is already invalid.
    }
    clearTokens();
    setMember(null);
  }, []);

  const value = useMemo(
    () => ({ member, loading, login, register, logout, reloadMember }),
    [member, loading, login, register, logout, reloadMember]
  );

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

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