/**
 * Authentication Provider
 * 认证提供者 - 管理用户认证状态和 token
 */

import { useState, useEffect } from "react";
import type { ReactNode } from "react";
import type { AuthResponse } from "@/api";
import { AXIOS_INSTANCE, setAuthToken } from "@/api";
import { globalCache } from "@/shared/services/artifact-cache";
import { AuthContext, type User } from "./AuthContext";
import { normalizeUser } from "./auth-model";

interface AuthProviderProps {
  children: ReactNode;
  devMode?: boolean;
}

/**
 * Auth Provider Component
 * Manages authentication state and provides auth context
 */
export const AuthProvider = ({ children, devMode = false }: AuthProviderProps) => {
  const [token, setToken] = useState<string | null>(() => {
    if (devMode) return "dev-token";
    return localStorage.getItem("access_token");
  });
  const [user, setUser] = useState<User | null>(() => {
    if (devMode) return null;
    const storedUser = localStorage.getItem("user");
    if (!storedUser) return null;
    try {
      return normalizeUser(JSON.parse(storedUser));
    } catch {
      localStorage.removeItem("user");
      return null;
    }
  });
  const [isHydratingUser, setIsHydratingUser] = useState(false);

  if (token) {
    setAuthToken(token);
  }

  const persistUser = (nextUser: User) => {
    localStorage.setItem("user", JSON.stringify(nextUser));
    setUser(nextUser);
  };

  const refreshUser = async () => {
    const activeToken = localStorage.getItem("access_token");
    if (!activeToken) {
      return;
    }

    setIsHydratingUser(true);
    try {
      setAuthToken(activeToken);
      const response = await AXIOS_INSTANCE.get("/auth/me");
      const nextUser = normalizeUser(response.data as Record<string, unknown>, user);
      persistUser(nextUser);
    } catch (error: any) {
      if (error?.response?.status === 401) {
        logout();
      } else if (error?.response?.status !== 404) {
        console.info("Unable to hydrate user profile from /auth/me:", error);
      }
    } finally {
      setIsHydratingUser(false);
    }
  };

  // Initialize: read token and user from localStorage
  useEffect(() => {
    if (devMode) {
      const devUser: User = {
        userId: "dev-user",
        username: "dev-user",
        role: "admin",
        workspaceId: "dev-workspace",
        workspaceName: "Development",
        namespace: "ocdp-ws-development",
        permissions: ["*"],
      };
      localStorage.setItem("access_token", "dev-token");
      localStorage.setItem("user", JSON.stringify(devUser));
      setToken("dev-token");
      setUser(devUser);
      return;
    }

    const storedToken = localStorage.getItem("access_token");

    if (storedToken) {
      setToken(storedToken);
      setAuthToken(storedToken);
    }
    if (storedToken) {
      void refreshUser();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [devMode]);

  // Sync token changes to axios headers
  useEffect(() => {
    setAuthToken(token);
  }, [token]);

  // Handle login (JWT format)
  const login = (response: AuthResponse) => {
    // JWT 格式: { accessToken, refreshToken, username, ... }
    const accessToken = response.accessToken || "";
    const refreshToken = response.refreshToken || "";
    
    localStorage.setItem("access_token", accessToken);
    localStorage.setItem("refresh_token", refreshToken);
    
    const nextUser = normalizeUser(response as Record<string, unknown>);
    
    setToken(accessToken);
    setAuthToken(accessToken);
    persistUser(nextUser);
    void refreshUser();
  };

  // Handle logout
  const logout = () => {
    localStorage.removeItem("access_token");
    localStorage.removeItem("refresh_token");
    localStorage.removeItem("user");
    setToken(null);
    setUser(null);
    setAuthToken(null);
    globalCache.clearAll();
  };

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

// useAuth hook is now exported from ./useAuth.ts for Fast Refresh compatibility
