'use client';

import React from 'react';
import { usePathname } from 'next/navigation';
import { useEffect, useState, createContext, useContext, useCallback } from 'react';

const HOME_URL = process.env.NEXT_PUBLIC_HOME_URL || '';
const ACCOUNT_BASE_URL = process.env.NEXT_PUBLIC_ACCOUNT_API_BASE_URL;
const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || '';

// user cache
let userCache: User | null = null;
let userCacheTime = 0;
const CACHE_DURATION = 60 * 60 * 1000; // 1 hour

interface User {
  id: number;
  openid: string;
  username: string;
  avatar_url: string;
  is_staff: boolean;
}

// Authentication context type
interface AuthContextType {
  user: User | null;
  isLoading: boolean;
  isAuthenticated: boolean;
  login: () => Promise<void>;
  logout: () => Promise<void>;
  checkAuth: () => Promise<boolean>;
  error: string | null;
}

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

// Authentication provider component
export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [user, setUser] = useState<User | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const pathname = usePathname();

  const fetchUser = useCallback(async () => {
    const now = Date.now();
    if (userCache && now - userCacheTime < CACHE_DURATION) {
      setUser(userCache);
      setIsLoading(false);
      return userCache;
    }

    try {
      const response = await fetch(`${API_BASE_URL}/api/partner/me`);
      const data = await response.json();
      if (response.ok) {
        const userData = data.data as User;
        setUser(userData);
        userCache = userData;
        userCacheTime = now;
        return userData;
      } else {
        setUser(null);
        userCache = null;
        userCacheTime = 0;
        return null;
      }
    } catch (error) {
      setUser(null);
      userCache = null;
      userCacheTime = 0;
      return null;
    } finally {
      setIsLoading(false);
    }
  }, []);

  // Check authentication status
  const checkAuth = useCallback(async (): Promise<boolean> => {
    try {
      setError(null);
      const userData = await fetchUser();
      return !!userData;
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Authentication check failed';
      console.error(errorMessage);
      setError(errorMessage);
      return false;
    }
  }, [fetchUser]);

  // Login function
  const login = useCallback(async () => {
    window.location.href = `${ACCOUNT_BASE_URL}/login?redirect_to=${encodeURIComponent(HOME_URL + '/dashboard')}`;
  }, []);

  const logout = useCallback(async () => {
    window.location.href = `${ACCOUNT_BASE_URL}/logout?redirect_to=${encodeURIComponent(HOME_URL)}`;
  }, []);

  // Check route permissions
  useEffect(() => {
    const checkRouteAuth = async () => {
      if (user) return;

      const isAuthenticated = await checkAuth();
      if (!isAuthenticated && pathname !== '/') {
        // Clear browser history to prevent back button access
        if (typeof window !== 'undefined') {
          // Replace current history entry to prevent back navigation
          window.history.replaceState(null, '', window.location.href);
          
          // Also clear any cached authentication data
          userCache = null;
          userCacheTime = 0;
        }
        login();
      }
    };

    checkRouteAuth();
  }, [pathname, checkAuth, user, login]);

  const value = {
    user,
    isLoading,
    isAuthenticated: !!user,
    login,
    logout,
    checkAuth,
    error,
  };

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

// Hook for using authentication context
export function useAuth() {
  const context = useContext(AuthContext);
  if (context === undefined) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
}

// get login url
export function getLoginUrl(redirectPath: string = '/dashboard') {
  const homeUrl = process.env.NEXT_PUBLIC_HOME_URL || '';
  const accountBaseUrl = process.env.NEXT_PUBLIC_ACCOUNT_API_BASE_URL;
  return `${accountBaseUrl}/login?redirect_to=${encodeURIComponent(homeUrl + redirectPath)}`;
}
