import React, { createContext, useContext, useState, useEffect } from 'react';
import { apiClient } from '@/services/adminApi';

interface User {
  id: string;
  email: string;
  name: string;
  type: 'tourist' | 'business';
  role?: 'tourist' | 'taxi' | 'guide' | 'restaurant' | 'hotel' | 'politur' | 'admin' | 'super_admin';
  avatar: string;
  location: { lat: number; lng: number };
  preferences: { language: string };
  wallet?: { balance: number; currency: string };
  profile?: {
    phone: string;
    address: string;
    joinedDate: string;
    permissions: string[];
  };
}

interface AuthContextType {
  user: User | null;
  isLoading: boolean;
  login: (email: string, password: string) => Promise<void>;
  register: (userData: any) => Promise<void>;
  logout: () => void;
  isAuthenticated: boolean;
}

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

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

  useEffect(() => {
    const init = async () => {
      try {
        const storedToken = localStorage.getItem('karibeo-token');
        const storedUser = localStorage.getItem('karibeo-user');
        if (storedUser) {
          try {
            const parsed = JSON.parse(storedUser);
            const roleNum = parsed?.role_id ?? parsed?.roleId ?? parsed?.role?.id;
            const roleStr = typeof parsed?.role === 'string' ? parsed.role : undefined;
            const ROLE_MAP: Record<number, string> = { 1: 'super_admin', 2: 'admin', 3: 'taxi', 4: 'tourist', 5: 'guide', 6: 'hotel' };
            const normalizedRole = (roleStr?.toLowerCase?.()) || (roleNum ? ROLE_MAP[Number(roleNum)] : undefined);
            const normalizedUser = normalizedRole ? { ...parsed, role: normalizedRole } : parsed;
            setUser(normalizedUser);
            if (normalizedRole && normalizedRole !== parsed?.role) {
              localStorage.setItem('karibeo-user', JSON.stringify(normalizedUser));
            }
          } catch {
            setUser(JSON.parse(storedUser));
          }
        } else if (storedToken) {
          // Avoid calling /auth/profile which returns 401 in this environment
          // We'll rely on stored user until profile endpoint is accessible
          console.warn('Token found but no cached user; skipping /auth/profile on init');
        }
      } catch (e) {
        // Don't aggressively clear token; just reset user
        setUser(null);
      } finally {
        setIsLoading(false);
      }
    };
    init();
  }, []);

  const login = async (email: string, password: string) => {
    setIsLoading(true);
    try {
      console.log('Login attempt with:', { email, password: '***' });
      
      // Mock users for testing
      const mockUsers = {
        'superadmin@karibeo.com': {
          id: '1',
          email: 'superadmin@karibeo.com',
          name: 'Super Admin',
          role: 'super_admin' as const,
          type: 'business' as const,
          avatar: '/api/placeholder/40/40',
          location: { lat: 18.4861, lng: -69.9312 },
          preferences: { language: 'es' },
          wallet: { balance: 0, currency: 'USD' },
          profile: {
            phone: '+1-809-555-0001',
            address: 'Santo Domingo, República Dominicana',
            joinedDate: '2023-01-01',
            permissions: ['all']
          }
        },
        'admin@karibeo.com': {
          id: '2',
          email: 'admin@karibeo.com',
          name: 'Admin User',
          role: 'admin' as const,
          type: 'business' as const,
          avatar: '/api/placeholder/40/40',
          location: { lat: 18.4861, lng: -69.9312 },
          preferences: { language: 'es' },
          wallet: { balance: 0, currency: 'USD' },
          profile: {
            phone: '+1-809-555-0002',
            address: 'Santiago, República Dominicana',
            joinedDate: '2023-02-01',
            permissions: ['user_management', 'content_management']
          }
        },
        'user@karibeo.com': {
          id: '3',
          email: 'user@karibeo.com',
          name: 'Regular User',
          role: 'tourist' as const,
          type: 'tourist' as const,
          avatar: '/api/placeholder/40/40',
          location: { lat: 18.4861, lng: -69.9312 },
          preferences: { language: 'es' },
          wallet: { balance: 150.50, currency: 'USD' },
          profile: {
            phone: '+1-809-555-0003',
            address: 'Punta Cana, República Dominicana',
            joinedDate: '2023-03-01',
            permissions: ['booking', 'reviews']
          }
        }
      };

      // Check if it's a mock user
      const mockUser = mockUsers[email as keyof typeof mockUsers];
      if (mockUser && password === '123456') {
        console.log('🎯 Mock login successful for:', email, 'with role:', mockUser.role);
        const token = `mock-token-${Date.now()}`;
        localStorage.setItem('karibeo-token', token);
        localStorage.setItem('karibeo_token', token);
        localStorage.setItem('karibeo-user', JSON.stringify(mockUser));
        setUser(mockUser);
        setIsLoading(false);
        return;
      }

      const loginData = { email: email.trim(), password: password.trim() };
      console.log('Sending login data (form first):', { email: loginData.email, password: '***' });

      let loginRes: any;
      // Try application/x-www-form-urlencoded first (some backends validate this path)
      try {
        loginRes = await apiClient.postForm('/auth/login', {
          email: loginData.email,
          password: loginData.password,
        });
      } catch (firstErr: any) {
        console.warn('Form login failed, retrying as JSON:', firstErr?.message);
        loginRes = await apiClient.post('/auth/login', loginData);
      }

      console.log('Login response:', loginRes);
      const token = loginRes?.token || loginRes?.accessToken || loginRes?.access_token;
      const refresh = loginRes?.refreshToken || loginRes?.refresh_token;
      if (!token) {
        throw new Error('Credenciales inválidas');
      }
      localStorage.setItem('karibeo-token', token);
      localStorage.setItem('karibeo_token', token);
      if (refresh) {
        localStorage.setItem('karibeo-refresh', refresh);
        localStorage.setItem('karibeo_refresh', refresh);
      }

      let userData = (loginRes && (loginRes.user || loginRes.profile || null)) as any;

      // Try to enrich with /auth/profile (post-login, should be authorized)
      try {
        const profile = await apiClient.get('/auth/profile') as any;
        const profileUser = (profile && (profile.user || profile)) as any;
        if (profileUser) {
          userData = { ...(userData || {}), ...profileUser };
        }
      } catch (e: any) {
        console.warn('Skipping /auth/profile after login:', e?.message);
      }

      if (userData) {
        // Enhanced role detection and normalization
        let normalizedRole = '';
        
        // Try role.name first (most reliable)
        if (userData?.role?.name) {
          const roleRaw = userData.role.name.toString().trim();
          const roleName = roleRaw.toLowerCase();
          console.log('🔍 Raw role.name from API:', userData.role.name, '-> normalized?', roleName);
          if (roleName.includes('super') && roleName.includes('admin')) {
            normalizedRole = 'super_admin';
          } else if (roleName.includes('admin')) {
            normalizedRole = 'admin';
          } else if (roleName.includes('taxi')) {
            normalizedRole = 'taxi';
          } else if (roleName.includes('guide')) {
            normalizedRole = 'guide';
          } else if (roleName.includes('hotel')) {
            normalizedRole = 'hotel';
          } else if (roleName.includes('tourist')) {
            normalizedRole = 'tourist';
          }
        }

        // Fallback to roleId mapping
        if (!normalizedRole && userData?.roleId) {
          const ROLE_MAP: Record<number, string> = { 1: 'super_admin', 2: 'admin', 3: 'taxi', 4: 'tourist', 5: 'guide', 6: 'hotel', 7: 'restaurant', 8: 'business', 9: 'staff' };
          normalizedRole = ROLE_MAP[Number(userData.roleId)] || '';
          console.log('🔍 Using roleId fallback:', userData.roleId, '-> mapped to:', normalizedRole);
        }

        // Fallback to JWT token role
        if (!normalizedRole) {
          try {
            const payload = JSON.parse(atob(String(token).split('.')[1]));
            const tokenRole = payload?.role;
            if (tokenRole) {
              const tokenRoleNorm = tokenRole.toString().trim().toLowerCase();
              console.log('🔍 JWT token role:', tokenRole, '-> normalized:', tokenRoleNorm);
              if (tokenRoleNorm.includes('super') && tokenRoleNorm.includes('admin')) {
                normalizedRole = 'super_admin';
              } else if (tokenRoleNorm.includes('admin')) {
                normalizedRole = 'admin';
              }
            }
          } catch (e) {
            console.warn('Failed to parse JWT token:', e);
          }
        }

        const finalUser = { ...userData, role: normalizedRole };
        console.log('🎯 Final user with normalized role:', { email: finalUser.email, role: finalUser.role, roleId: finalUser.roleId });
        
        setUser(finalUser);
        localStorage.setItem('karibeo-user', JSON.stringify(finalUser));
      } else {
        // If backend doesn't return user, skip extra call and set minimal user from token
        setUser({
          id: '',
          email,
          name: email.split('@')[0],
          type: 'tourist',
          avatar: '',
          location: { lat: 0, lng: 0 },
          preferences: { language: 'es' },
        } as any);
      }
    } catch (error: any) {
      console.error('Login error:', error);
      localStorage.removeItem('karibeo-token');
      localStorage.removeItem('karibeo-user');
      setUser(null);
      throw new Error(error?.message || 'No se pudo iniciar sesión');
    } finally {
      setIsLoading(false);
    }
  };

  const register = async (userData: any) => {
    setIsLoading(true);
    try {
      const res = await apiClient.post('/auth/register', userData) as any;
      const token = res?.token || res?.accessToken || res?.access_token;
      const refresh = res?.refreshToken || res?.refresh_token;
      if (token) { 
        localStorage.setItem('karibeo-token', token);
        localStorage.setItem('karibeo_token', token);
      }
      if (refresh) {
        localStorage.setItem('karibeo-refresh', refresh);
        localStorage.setItem('karibeo_refresh', refresh);
      }

      const profile = await apiClient.get('/auth/profile') as any;
      const newUser = (profile && (profile.user || profile)) as any;

      setUser(newUser);
      localStorage.setItem('karibeo-user', JSON.stringify(newUser));
    } catch (error: any) {
      localStorage.removeItem('karibeo-token');
      localStorage.removeItem('karibeo-user');
      setUser(null);
      throw new Error(error?.message || 'No se pudo registrar');
    } finally {
      setIsLoading(false);
    }
  };

  const logout = () => {
    setUser(null);
    localStorage.removeItem('karibeo-user');
    localStorage.removeItem('karibeo-token');
    localStorage.removeItem('karibeo_token');
    localStorage.removeItem('karibeo-refresh');
    localStorage.removeItem('karibeo_refresh');
  };

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

export const useAuth = () => {
  const context = useContext(AuthContext);
  if (context === undefined) {
    // Soft fallback to avoid app crash; helps while provider is being hot-reloaded
    console.warn('useAuth used outside AuthProvider. Using safe fallback.');
    return {
      user: null,
      isLoading: false,
      login: async () => { throw new Error('AuthProvider no inicializado'); },
      register: async () => { throw new Error('AuthProvider no inicializado'); },
      logout: () => {},
      isAuthenticated: false,
    } as AuthContextType;
  }
  return context;
};