/**
 * Authentication Context
 * Manages user login state and provides auth utilities
 */
"use client";

import React, { createContext, useContext, useState, useEffect, useCallback, ReactNode } from "react";
import { clearApiSettings, saveApiSettingsAsync } from "@/lib/storage";
import { clearAllReports, saveReport } from "@/lib/reports-db";
import { getCloudSettings, getCloudReports } from "@/lib/user-api";

// User interface
export interface User {
  id: string;
  email: string;
  name: string | null;
  avatar_url: string | null;
}

// Auth context interface
interface AuthContextType {
  user: User | null;
  token: string | null;
  isLoading: boolean;
  isAuthenticated: boolean;
  login: () => void;
  logout: () => Promise<void>;
  setAuthFromCallback: (token: string) => Promise<void>;
}

// Create context
const AuthContext = createContext<AuthContextType | undefined>(undefined);

// Token storage key
const TOKEN_KEY = "tradingagents_auth_token";

/**
 * Auth Provider Component
 */
export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<User | null>(null);
  const [token, setToken] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [googleClientId, setGoogleClientId] = useState<string>("");

  // Fetch Google Client ID from API (runtime)
  useEffect(() => {
    fetch("/api/config")
      .then(res => res.json())
      .then(data => {
        setGoogleClientId(data.googleClientId || "");
      })
      .catch(err => {
        console.error("Failed to fetch config:", err);
      });
  }, []);

  // Parse JWT token to get user info
  const parseToken = useCallback((token: string): User | null => {
    try {
      const payload = JSON.parse(atob(token.split(".")[1]));
      return {
        id: payload.sub,
        email: payload.email,
        name: payload.name,
        avatar_url: payload.avatar_url,
      };
    } catch {
      return null;
    }
  }, []);

  // Check if token is expired
  const isTokenExpired = useCallback((token: string): boolean => {
    try {
      const payload = JSON.parse(atob(token.split(".")[1]));
      const exp = payload.exp * 1000; // Convert to milliseconds
      return Date.now() > exp;
    } catch {
      return true;
    }
  }, []);

  // Initialize auth state from localStorage
  useEffect(() => {
    const initAuth = () => {
      if (typeof window === "undefined") {
        setIsLoading(false);
        return;
      }

      const storedToken = localStorage.getItem(TOKEN_KEY);
      
      if (storedToken && !isTokenExpired(storedToken)) {
        const userData = parseToken(storedToken);
        if (userData) {
          setToken(storedToken);
          setUser(userData);
        } else {
          localStorage.removeItem(TOKEN_KEY);
        }
      } else if (storedToken) {
        // Token expired, remove it
        localStorage.removeItem(TOKEN_KEY);
      }
      
      setIsLoading(false);
    };

    initAuth();
  }, [parseToken, isTokenExpired]);

  // Auto-clear local data when unauthenticated user leaves the page
  useEffect(() => {
    if (typeof window === "undefined") return;

    const handleBeforeUnload = () => {
      // Only clear data if user is not authenticated
      const currentToken = localStorage.getItem(TOKEN_KEY);
      if (!currentToken) {
        // Clear API settings (synchronous)
        clearApiSettings();
        
        // Clear reports - use synchronous approach for beforeunload
        // IndexedDB operations are async, but we can at least attempt it
        clearAllReports().catch(() => {
          // Ignore errors during unload
        });
        
        console.log("Cleared local data for unauthenticated user on page leave");
      }
    };

    // Use both beforeunload and pagehide for better browser compatibility
    window.addEventListener("beforeunload", handleBeforeUnload);
    window.addEventListener("pagehide", handleBeforeUnload);

    return () => {
      window.removeEventListener("beforeunload", handleBeforeUnload);
      window.removeEventListener("pagehide", handleBeforeUnload);
    };
  }, []); // No dependencies - we check localStorage directly

  // Login - redirect to Google OAuth
  const login = useCallback(() => {
    if (!googleClientId) {
      console.error("Google Client ID not configured");
      alert("Google 登入尚未設定。請聯繫管理員。");
      return;
    }

    // Build Google OAuth URL
    const redirectUri = `${window.location.origin}/api/auth/callback/google`;
    const scope = "openid email profile";
    
    const params = new URLSearchParams({
      client_id: googleClientId,
      redirect_uri: redirectUri,
      response_type: "code",
      scope: scope,
      access_type: "offline",
      prompt: "consent",
    });

    window.location.href = `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`;
  }, [googleClientId]);

  // Logout - clear auth and all local data
  const logout = useCallback(async () => {
    // Clear auth token
    localStorage.removeItem(TOKEN_KEY);
    setToken(null);
    setUser(null);
    
    // Clear all local data
    clearApiSettings();
    await clearAllReports();
    
    console.log("Logged out and cleared all local data");
  }, []);

  // Restore cloud data to local storage
  const restoreCloudData = useCallback(async (authToken: string) => {
    try {
      // Temporarily set token for API calls
      localStorage.setItem(TOKEN_KEY, authToken);
      
      // Fetch and restore cloud settings
      const cloudSettings = await getCloudSettings();
      if (cloudSettings) {
        await saveApiSettingsAsync(cloudSettings);
        console.log("Restored API settings from cloud");
      }
      
      // Fetch and restore cloud reports
      const cloudReports = await getCloudReports();
      if (cloudReports && cloudReports.length > 0) {
        // Clear existing local reports first
        await clearAllReports();
        
        // Save each cloud report to local IndexedDB
        for (const report of cloudReports) {
          await saveReport(
            report.ticker,
            report.market_type,
            report.analysis_date,
            report.result,
            (report as any).task_id
          );
        }
        console.log(`Restored ${cloudReports.length} reports from cloud`);
      }
    } catch (error) {
      console.error("Failed to restore cloud data:", error);
    }
  }, []);

  // Set auth from callback (after OAuth redirect)
  const setAuthFromCallback = useCallback(async (newToken: string) => {
    const userData = parseToken(newToken);
    if (userData) {
      // First restore cloud data, then set the auth state
      await restoreCloudData(newToken);
      
      localStorage.setItem(TOKEN_KEY, newToken);
      setToken(newToken);
      setUser(userData);
      
      console.log("Login complete, cloud data restored");
    }
  }, [parseToken, restoreCloudData]);

  const value: AuthContextType = {
    user,
    token,
    isLoading,
    isAuthenticated: !!user,
    login,
    logout,
    setAuthFromCallback,
  };

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

/**
 * Hook to use auth context
 */
export function useAuth(): AuthContextType {
  const context = useContext(AuthContext);
  if (context === undefined) {
    throw new Error("useAuth must be used within an AuthProvider");
  }
  return context;
}

/**
 * Get auth token for API requests
 */
export function getAuthToken(): string | null {
  if (typeof window === "undefined") return null;
  return localStorage.getItem(TOKEN_KEY);
}

/**
 * Get auth headers for API requests
 */
export function getAuthHeaders(): Record<string, string> {
  const token = getAuthToken();
  if (token) {
    return { Authorization: `Bearer ${token}` };
  }
  return {};
}
