import { createContext, ReactNode, useCallback, useContext, useEffect, useState } from 'react';
import { login as apiLogin, signup as apiSignup } from '@/lib/api-client';

export type UserRole = 'admin' | 'user' | 'content_manager' | 'viewer';

export interface User {
  id: string;
  email: string;
  name: string;
  role: UserRole;
  permissions?: string[]; // Optional: for future granular permissions from backend
}

interface AuthContextType {
  user: User | null;
  login: (email: string, password: string) => Promise<void>;
  signup: (email: string, password: string, name: string, role: UserRole) => Promise<void>;
  logout: () => void;
  isLoading: boolean;
  isAuthenticated: boolean;
  validateToken: () => Promise<boolean>;
  refreshUser: () => Promise<void>;
}

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

export const useAuth = () => {
  const context = useContext(AuthContext);
  if (context === undefined) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
};

interface AuthProviderProps {
  children: ReactNode;
}

/**
 * Extract basic user info from token payload (for UI purposes only)
 * SECURITY NOTE: This does NOT validate the token - validation happens server-side only
 * This data should NEVER be trusted for security decisions
 */
function extractUserFromToken(token: string): User | null {
  try {
    // Only extract basic info for UI - never trust this data for security decisions
    const payload = JSON.parse(atob(token.split('.')[1]));
      return {
        id: payload.sub || payload.id || '1',
        email: payload.email || 'user@tuganyak.dev',
        name: payload.name || payload.firstName || 'User',
        role: (payload.role || 'user') as UserRole,
        permissions: payload.permissions,
      };
  } catch {
    return null;
  }
}

/**
 * Validate token by making an authenticated API call to the backend
 * This is the ONLY secure way to validate a JWT token
 */
async function validateTokenServerSide(token: string): Promise<User | null> {
  try {
    // Make an authenticated request to validate the token
    // Using a lightweight endpoint to check token validity
    const isProduction = import.meta.env.PROD;
    const baseUrl = import.meta.env.VITE_API_BASE_URL || (isProduction ? 'https://api.bugulma.city' : '');
    const response = await fetch(`${baseUrl}/api/v1/auth/me`, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
      // Add timeout to prevent hanging requests
      signal: AbortSignal.timeout(5000),
    });

    if (response.ok) {
      const userData = await response.json();
      return {
        id: userData.id || userData.user_id,
        email: userData.email,
        name: userData.name || userData.username || 'User',
        role: (userData.role || 'user') as UserRole,
        permissions: userData.permissions,
      };
    }

    return null;
  } catch (error) {
    console.warn('Token validation failed:', error);
    return null;
  }
}

export const AuthProvider = ({ children }: AuthProviderProps) => {
  const [user, setUser] = useState<User | null>(null);
  const [isLoading, setIsLoading] = useState(true);

  // Secure token validation function
  const validateToken = useCallback(async (): Promise<boolean> => {
    const token = localStorage.getItem('auth_token');
    if (!token) {
      setUser(null);
      return false;
    }

    try {
      // Validate token server-side (secure approach)
      const validatedUser = await validateTokenServerSide(token);
      if (validatedUser) {
        setUser(validatedUser);
        return true;
      } else {
        // Token invalid, clean up
        localStorage.removeItem('auth_token');
        setUser(null);
        return false;
      }
    } catch (error) {
      console.warn('Token validation error:', error);
      // On validation error, assume token is invalid for security
      localStorage.removeItem('auth_token');
      setUser(null);
      return false;
    }
  }, []);

  useEffect(() => {
    // Initialize authentication state
    const initializeAuth = async () => {
      const token = localStorage.getItem('auth_token');
      if (token) {
        // Validate token server-side instead of trusting client-side decoding
        await validateToken();
      }
      setIsLoading(false);
    };

    initializeAuth();
  }, [validateToken]);

  const login = async (email: string, password: string) => {
    setIsLoading(true);
    try {
      const data = await apiLogin(email, password);

      // Validate the returned token immediately for security
      if (data.token) {
        const validatedUser = await validateTokenServerSide(data.token);
        if (validatedUser) {
          setUser(validatedUser);
          // Only store token after successful server-side validation
          localStorage.setItem('auth_token', data.token);
        } else {
          throw new Error('Invalid token received from server');
        }
      } else {
        throw new Error('No token received from server');
      }
    } catch (error) {
      setUser(null);
      throw error;
    } finally {
      setIsLoading(false);
    }
  };

  const signup = async (email: string, password: string, name: string, role: UserRole) => {
    setIsLoading(true);
    try {
      const data = await apiSignup(email, password, name, role);

      // Validate the returned token immediately for security
      if (data.token) {
        const validatedUser = await validateTokenServerSide(data.token);
        if (validatedUser) {
          setUser(validatedUser);
          // Only store token after successful server-side validation
          localStorage.setItem('auth_token', data.token);
        } else {
          throw new Error('Invalid token received from server');
        }
      } else {
        throw new Error('No token received from server');
      }
    } catch (error) {
      setUser(null);
      throw error;
    } finally {
      setIsLoading(false);
    }
  };

  const logout = useCallback(() => {
    setUser(null);
    localStorage.removeItem('auth_token');
    // Clear any other auth-related storage
    sessionStorage.clear();
  }, []);

  const refreshUser = useCallback(async () => {
    await validateToken();
  }, [validateToken]);

  const value: AuthContextType = {
    user,
    login,
    signup,
    logout,
    isLoading,
    isAuthenticated: !!user,
    validateToken,
    refreshUser,
  };

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