import AsyncStorage from '@react-native-async-storage/async-storage';
import CryptoJS from 'crypto-js';
import { createContext, useContext, useEffect, useState } from 'react';
import { API_CONFIG, API_ENDPOINTS, buildApiUrl } from '../config/api';
import { AuthContextType, AuthProviderProps, LoginResponse, User, UserData } from '../types';
// Contexto
const AuthContext = createContext<AuthContextType | undefined>(undefined);

// Chaves para AsyncStorage
const STORAGE_KEYS = {
  TOKEN: '@cruiseLovers:token',
  USER: '@cruiseLovers:user',
} as const;

// Provider

export function AuthProvider({ children }: AuthProviderProps) {
  const [user, setUser] = useState<User | null>(null);
  const [token, setToken] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [userData, setUserData] = useState<UserData | null>(null);
  // Carregar dados salvos ao iniciar
  useEffect(() => {
    loadStoredAuth();
  }, []);

  const loadStoredAuth = async () => {
    try {
      const [storedToken, storedUser] = await Promise.all([
        AsyncStorage.getItem(STORAGE_KEYS.TOKEN),
        AsyncStorage.getItem(STORAGE_KEYS.USER),
      ]);

      if (storedToken && storedUser) {
        setToken(storedToken);
        setUser(JSON.parse(storedUser));
      }
    } catch (err) {
      console.error('Erro ao carregar autenticação:', err);
    } finally {
      setIsLoading(false);
    }
  };

  const login = async (email: string, password: string) => {
    try {
      setIsLoading(true);
      setError(null);

      const url = buildApiUrl(API_ENDPOINTS.USER_LOGIN);
      
      // Encriptar password com MD5
      const encryptedPassword = CryptoJS.MD5(password).toString();
      
      // Criar FormData com os dados de login
      const formData = new FormData();
      formData.append('email', email);
      formData.append('password', encryptedPassword);
      
      const response = await fetch(url, {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          // Não definir Content-Type - o React Native define automaticamente para multipart/form-data
        },
        body: formData,
      });

      const data: LoginResponse = await response.json();

      if (!response.ok || data.status !== 200) {
        // A API retorna status 401 com mensagem quando não existe utilizador
        throw new Error(data.message || 'Erro ao fazer login');
      }

      // Se a resposta for bem-sucedida, Guardar token e user
      if (data.token) {
        setToken(data.token);
        await AsyncStorage.setItem(STORAGE_KEYS.TOKEN, data.token);
      }

      if (data.user) {
        setUser(data.user);
        await AsyncStorage.setItem(STORAGE_KEYS.USER, JSON.stringify(data.user));
      } else {
        // Se não vier user na resposta, criar um objeto básico com email
        setUser(userData);
        await AsyncStorage.setItem(STORAGE_KEYS.USER, JSON.stringify(userData));
      }
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Erro desconhecido ao fazer login';
      setError(errorMessage);
      throw err;
    } finally {
      setIsLoading(false);
    }
  };

  const updateProfile = async (nome?: string, apelido?: string, oldPassword?: string, newPassword?: string) => {
    try {
      setIsLoading(true);
      setError(null);

      if (!token) {
        throw new Error('Não autenticado');
      }

      const url = buildApiUrl(API_ENDPOINTS.UPDATE_PROFILE);
      // Criar FormData com os dados de atualização
      const formData = new FormData();

      formData.append('token', token);

      if (nome) {
        formData.append('nome', nome);
      }
      if (apelido) {
        formData.append('apelido', apelido);
      }
      if (newPassword) {
        const encryptedNewPassword = CryptoJS.MD5(newPassword).toString();
        formData.append('password', encryptedNewPassword);
        if (oldPassword) {
          const encryptedOldPassword = CryptoJS.MD5(oldPassword).toString();
          formData.append('old_password', encryptedOldPassword);
        }
      }

      
      const response = await fetch(url, {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
        },
        body: formData,
      });

      const data: LoginResponse = await response.json();

      if (!response.ok || data.status !== 200) {
        throw new Error(data.message || 'Erro ao atualizar perfil');
      }

      // Atualizar dados do utilizador se vierem na resposta
      if (data.user) {
        setUser(data.user);
        await AsyncStorage.setItem(STORAGE_KEYS.USER, JSON.stringify(data.user));
      } else if (nome || apelido) {
        const updatedUser = { ...user, nome: nome ?? user?.nome, apelido: apelido ?? user?.apelido };
        setUser(updatedUser as User);
        await AsyncStorage.setItem(STORAGE_KEYS.USER, JSON.stringify(updatedUser));
      }
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Erro desconhecido ao atualizar perfil';
      setError(errorMessage);
      throw err;
    } finally {
      setIsLoading(false);
    }
  };

  const logout = async () => {
    try {
      setIsLoading(true);
      
      // Opcional: chamar endpoint de logout na API
      if (token) {
        try {
          const url = buildApiUrl(API_ENDPOINTS.USER_LOGOUT);
          await fetch(url, {
            method: 'POST',
            headers: {
              ...API_CONFIG.DEFAULT_HEADERS,
              Authorization: `Bearer ${token}`,
            },
          });
        } catch (err) {
          console.error('Erro ao fazer logout na API:', err);
          // Continuar mesmo se falhar
        }
      }

      // Limpar estado local
      setUser(null);
      setToken(null);
      setError(null);

      // Limpar AsyncStorage
      await Promise.all([
        AsyncStorage.removeItem(STORAGE_KEYS.TOKEN),
        AsyncStorage.removeItem(STORAGE_KEYS.USER),
      ]);
    } catch (err) {
      console.error('Erro ao fazer logout:', err);
    } finally {
      setIsLoading(false);
    }
  };

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

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

// Hook para usar o contexto
export function useAuth() {
  const context = useContext(AuthContext);
  if (context === undefined) {
    throw new Error('useAuth deve ser usado dentro de um AuthProvider');
  }
  return context;
}
