'use client';

import { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import { apiClient, ApiResponse } from '../lib/api';
import { useRouter } from 'next/navigation';

/**
 * Represents the authenticated user structure
 */
interface User {
  id: string | number;
  email: string;
  name: string;
  avatar?: string;
  phone?: string;
  contractor_company?: string;
}

type ProviderLoginResponse = ApiResponse<{
  data: {
    provider: {
      id: number;
      name: string;
      email: string;
      phone?: string;
      contractor_company?: string;
    };
    token: string;
  };
}>;

/**
 * Defines the available methods and properties exposed by the Auth Context
 */
interface AuthContextType {
  user: User | null;
  login: (email: string, password: string) => Promise<boolean>;
  logout: () => void;
  isLoading: boolean;
  // Compatibility with existing UI components
  data: { user: User | null } | null;
  status: 'loading' | 'authenticated' | 'unauthenticated';
}

// Create a new authentication context
const AuthContext = createContext<AuthContextType | undefined>(undefined);

// Token validity duration (4 hours)
const TOKEN_EXPIRATION_MS = 4 * 60 * 60 * 1000;

/**
 * AuthProvider component
 * ----------------------
 * Manages authentication state, session validation, and token expiration logic.
 * Exposes login/logout methods and provides the current user to child components.
 */
export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<User | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const router = useRouter();

  /**
   * Check for existing session on mount
   * -----------------------------------
   * - Reads token, user data, and timestamp from localStorage
   * - Validates if the token is still within the 30-minute limit
   * - Automatically logs out if expired
   * - Schedules an auto-logout timer for the remaining time
   */
  useEffect(() => {
    const checkSession = () => {
      try {
        const token = localStorage.getItem('accessToken');
        const savedUser = localStorage.getItem('auth-user');
        const authTime = localStorage.getItem('authTime');

        // If all required session data exists
        if (token && savedUser && authTime) {
          const elapsed = Date.now() - Number(authTime);

          if (elapsed > TOKEN_EXPIRATION_MS) {
            // Token expired — force logout
            console.warn('Session expired due to timeout');
            logout();
          } else {
            // Token still valid — restore user state
            apiClient.setTokens(token);
            setUser(JSON.parse(savedUser));

            // Schedule auto logout for remaining time
            const remainingTime = TOKEN_EXPIRATION_MS - elapsed;
            setTimeout(() => {
              console.warn('Auto-logout due to session timeout');
              logout();
            }, remainingTime);
          }
        } else {
          // No valid session found — clear and redirect
          logout();
        }
      } catch (error) {
        console.error('Session verification failed:', error);
        logout();
      } finally {
        setIsLoading(false);
      }
    };

    checkSession();
  }, []);

  /**
   * Login function
   * --------------
   * Authenticates the user using email and password.
   * On success:
   *  - Saves token and user info in localStorage
   *  - Records the login timestamp
   *  - Sets up auto logout after 30 minutes
   */
  const login = async (email: string, password: string): Promise<boolean> => {
    setIsLoading(true);
    try {
      // Call the backend signin API
      const response = await apiClient.post('contractor/login', { email, password }, { requireAuth: false });
      const { token, provider } = (response as ProviderLoginResponse).data.data;

      if (token) {
        // Construct user object
        const user: User = {
          id: provider.id,
          email: provider.email,
          name: provider.name,
          phone: provider.phone,
          contractor_company: provider.contractor_company,
          avatar: '/media/avatars/blank.png',
        };

        // Save user and token data in both state and localStorage
        setUser(user);
        localStorage.setItem('auth-user', JSON.stringify(user));
        localStorage.setItem('accessToken', token);
        localStorage.setItem('authTime', Date.now().toString());
        apiClient.setTokens(token);

        // Schedule auto logout after token expiration time
        setTimeout(() => logout(), TOKEN_EXPIRATION_MS);

        return true;
      }

      return false;
    } catch (error) {
      console.error('Login failed:', error);
      return false;
    } finally {
      setIsLoading(false);
    }
  };

  /**
   * Logout function
   * ---------------
   * Clears user session, removes token and timestamp from storage,
   * and redirects the user to the login page.
   */
  const logout = () => {
    setUser(null);
    localStorage.removeItem('auth-user');
    localStorage.removeItem('accessToken');
    localStorage.removeItem('authTime');
    apiClient.clearTokens();
    router.push('/signin');
  };

  /**
   * Compatibility properties for existing UI components
   */
  const data = user ? { user } : null;
  const status = isLoading ? 'loading' : user ? 'authenticated' : 'unauthenticated';

  return (
    <AuthContext.Provider value={{ user, login, logout, isLoading, data, status }}>
      {children}
    </AuthContext.Provider>
  );
}

/**
 * useAuth hook
 * ------------
 * Provides access to the authentication context.
 * Throws an error if used outside of <AuthProvider>.
 */
export function useAuth() {
  const context = useContext(AuthContext);
  if (!context) throw new Error('useAuth must be used within an AuthProvider');
  return context;
}

/**
 * useSession hook (NextAuth Compatibility)
 * ----------------------------------------
 * Returns data and status for components expecting NextAuth-style session state.
 */
export function useSession() {
  const { data, status } = useAuth();
  return { data, status };
}

/**
 * signIn function (Standalone)
 * ----------------------------
 * Used for compatibility with legacy or server-side calls.
 * Performs login and stores session data manually.
 */
export async function signIn(options?: Record<string, unknown>) {
  try {
    const email = options?.email as string;
    const password = options?.password as string;
    if (!email || !password) throw new Error('Email and password are required');

    const response = await apiClient.post('contractor/login', { email, password }, { requireAuth: false });
    const { token, provider } = (response as ProviderLoginResponse).data.data;

    if (token) {
      const user: User = {
        id: provider.id,
        email: provider.email,
        name: provider.name,
        phone: provider.phone,
        contractor_company: provider.contractor_company,
        avatar: '/media/avatars/blank.png',
      };

      // Save token and user to storage
      localStorage.setItem('auth-user', JSON.stringify(user));
      localStorage.setItem('accessToken', token);
      localStorage.setItem('authTime', Date.now().toString());
      apiClient.setTokens(token);

      // Reload app to apply updated auth state
      window.location.href = '/public-profile/profiles/default';
      return true;
    }

    return false;
  } catch (e) {
    console.error('Sign in error:', e);
    return false;
  }
}

/**
 * signOut function (Standalone)
 * -----------------------------
 * Calls the logout API endpoint, clears all session data,
 * and navigates back to the login page.
 */
export async function signOut() {
  try {
    // Call logout API endpoint
    await apiClient.post('contractor/logout', {}, { requireAuth: true });
  } catch (error) {
    console.error('Logout API call failed:', error);
  } finally {
    // Always clear local data and redirect, even if API call fails
    localStorage.removeItem('auth-user');
    localStorage.removeItem('accessToken');
    localStorage.removeItem('authTime');
    apiClient.clearTokens();
    window.location.href = '/signin';
  }
}