import { useState, useEffect } from 'react';
import { authService } from '@/services/authService';
import {
  setTokenForModule,
  clearAllTokens,
  setUserForModule,
  getCurrentModuleUser,
  getModuleFromPath,
  clearModuleToken,
  clearUserForModule,
  getUserForModule,
  clearAllUsers,
  getAuthenticatedUserModules,
  getSetoresForModule
} from '@/utils/tokenManager';
import { isBlocked, recordLoginAttempt, clearAllAttempts } from '@/utils/rateLimiter';
import { AuditEventType, logSecurityEvent } from '@/utils/securityAudit';
import { generateCSRFToken, setCSRFToken, sanitizeUserData } from '@/utils/tokenSecurity';

/**
 * Hook de autenticação para a aplicação com persistência.
 * Integra com o authService para autenticação real ou mock.
 */
export const useAuth = () => {
  // Inicializa com usuário do módulo atual (baseado na URL)
  const [user, setUser] = useState(() => {
    // 1. Tenta obter usuário específico do módulo (ex: integra_user_prafrot)
    const currentModule = getModuleFromPath();
    if (currentModule) {
      const moduleUser = localStorage.getItem(`integra_user_${currentModule}`);
      if (moduleUser) {
        try {
          return JSON.parse(moduleUser);
        } catch (e) {}
      }
    }

    // 2. Fallback para função utilitária
    const moduleUserUtil = getCurrentModuleUser();
    if (moduleUserUtil) return moduleUserUtil;
    
    // Fallback para usuário global
    const savedUser = localStorage.getItem('integra_user');
    const userObj = savedUser ? JSON.parse(savedUser) : null;
    
    // Retorna o usuário tal como está no storage, sem mesclagem agressiva de setores legados
    return userObj;
  });
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  
  // Atualiza usuário quando a rota muda (módulo diferente)
  useEffect(() => {
    const updateUserForCurrentModule = () => {
      const moduleUser = getCurrentModuleUser();
      if (moduleUser && moduleUser.email !== user?.email) {
        setUser(moduleUser);
      }
    };
    
    updateUserForCurrentModule();
    // Escuta mudanças na URL
    const handleLocationChange = () => {
      updateUserForCurrentModule();
    };
    window.addEventListener('popstate', handleLocationChange);
    
    return () => {
      window.removeEventListener('popstate', handleLocationChange);
    };
  }, [user?.email]);

  /**
   * Realiza o login para um ambiente específico.
   * @param {Object} credentials - Email e senha.
   * @param {string} environment - Identificador do ambiente (ex: 'fleet', 'financeiro').
   */
  const login = async ({ email, password }, environment = 'global') => {
    setLoading(true);
    setError(null);
    
    try {
      // SEGURANÇA: Verifica rate limiting antes de tentar login
      const blockStatus = isBlocked(email);
      if (blockStatus.blocked) {
        const minutesLeft = Math.ceil((blockStatus.blockedUntil - Date.now()) / 60000);
        const errorMsg = `Muitas tentativas de login falhadas. Tente novamente em ${minutesLeft} minuto(s).`;
        setError(errorMsg);
        setLoading(false);
        logSecurityEvent(AuditEventType.RATE_LIMIT_EXCEEDED, { email, environment });
        return false;
      }
      
      // Determina qual serviço de autenticação usar com base no ambiente
      let authResponse;
      if (environment === 'auth_oestepan') {
        authResponse = await authService.loginOestePan(email, password);
      } else if (environment === 'fleet' || environment === 'prafrot' || environment === 'autolab' || environment === 'rh') {
        authResponse = await authService.loginMonitoramento(email, password);
      } else {
        authResponse = await authService.authenticatePralog(email, password);
      }

      // Backend agora retorna { token, tokens: {...}, setores: {...}, setoresList: [...], user }
      const { token, tokens = {}, setores = {}, setoresList = [], user: userData } = authResponse;
      
      // SEGURANÇA: Gera e armazena token CSRF
      const csrfToken = generateCSRFToken();
      setCSRFToken(csrfToken);
      
      // Armazena tokens por módulo usando tokenManager (agora é async)
      // Se houver tokens por módulo na resposta, usa eles
      if (Object.keys(tokens).length > 0) {
        await Promise.all(
          Object.keys(tokens).map(async (module) => {
            const moduleToken = tokens[module];
            const moduleSetor = setores[module] || setoresList[0];
            // Armazena token para o módulo e seus setores
            await setTokenForModule(module, moduleToken, moduleSetor);
          })
        );
      } else {
        // Armazena token para todos os setores retornados
        // Permite que o usuário tenha múltiplos tokens (um para cada setor)
        if (setoresList.length > 0) {
          // Armazena o mesmo token para cada setor retornado
          await setTokenForModule(environment, token, setoresList);
        } else {
          // Fallback: se não houver setores, armazena para o ambiente atual
          await setTokenForModule(environment, token, null);
        }
      }
      
      // SEGURANÇA: Registra login bem-sucedido e limpa tentativas
      recordLoginAttempt(email, true);
      logSecurityEvent(AuditEventType.LOGIN_SUCCESS, { 
        email: email.substring(0, 2) + '***@' + email.split('@')[1],
        environment 
      });
      
      // Mantém compatibilidade: token global (O tokenManager já gerencia isso)
      localStorage.setItem('x-access-token', token);
      
      // Cria dados do usuário para este módulo específico
      const moduleUser = {
        id: userData?.id || null,
        name: userData?.name || email.split('@')[0],
        email: userData?.email || email,
        role: userData?.role || 'user',
        permissions: userData?.permissions || [],
        setores: setoresList, // Adiciona lista global de setores
        authorizedEnvironments: {}
      };

      // Adiciona os ambientes autorizados baseado nos setores retornados
      const authorizedEnvironments = { ...moduleUser.authorizedEnvironments };
      
      // Adiciona ambiente atual
      authorizedEnvironments[environment] = true;
      
      // Adiciona outros ambientes baseado nos setores retornados
      if (setoresList.length > 0) {
        setoresList.forEach(setor => {
          // Mapeia setor para módulo e marca como autorizado
          const module = Object.keys(setores).find(m => setores[m] === setor);
          if (module) {
            authorizedEnvironments[module] = true;
          }
        });
      }

      const updatedUser = {
        ...moduleUser,
        authorizedEnvironments,
        setores: setoresList // Use ONLY sectors from the server response
      };

      // Se for o mesmo usuário, mantém os ambientes anteriores
      if (user && user.email === updatedUser.email) {
        updatedUser.authorizedEnvironments = {
          ...(user.authorizedEnvironments || {}),
          ...authorizedEnvironments
        };
      }

      // SEGURANÇA: Sanitiza os dados do usuário antes de armazenar (remove senhas, etc.)
      const sanitizedUser = sanitizeUserData(updatedUser);
      
      // Armazena e atualiza estado (o tokenManager já faz o merge global)
      setUserForModule(environment, sanitizedUser);
      setUser(sanitizedUser);
      
      // (O merge global agora é feito dentro do setUserForModule no tokenManager)
      setLoading(false);
      return true;
      
    } catch (err) {
      const msg = err.response?.data?.message || err.message || 'Erro ao realizar login. Tente novamente.';
      setError(msg);
      setLoading(false);
      return false;
    }
  };

  const logout = async (module = null, clearAll = false) => {
    // Se clearAll for true, limpa tudo (comportamento radical)
    if (clearAll) {
      localStorage.clear();
      // SEGURANÇA: Limpa também o sessionStorage
      sessionStorage.clear();
      setUser(null);
      await clearAllTokens();
      clearAllUsers();
      clearAllAttempts();
      return;
    }

    // SEGURANÇA: Registra evento de logout
    const currentModule = module || getModuleFromPath();
    logSecurityEvent(AuditEventType.LOGOUT, { 
      module: currentModule,
      clearAll 
    });
    
    // Se módulo especificado, limpa apenas esse módulo
    if (module) {
      await clearModuleToken(module);
      clearUserForModule(module);
      
      // Se for o módulo atual, limpa estado local
      const currentModulePath = getModuleFromPath();
      if (currentModulePath === module) {
        setUser(null);
      }
    } else {
      // Se não especificado, detecta o módulo atual automaticamente
      const detectedModule = getModuleFromPath();
      if (detectedModule) {
        // Limpa apenas o módulo atual
        await clearModuleToken(detectedModule);
        clearUserForModule(detectedModule);
        
        // Verifica se ainda existem outros módulos autenticados
        const remainingModules = await getAuthenticatedUserModules();
        if (remainingModules.length === 0) {
          // Se não sobrar ninguém, limpa global
          localStorage.removeItem('x-access-token');
          localStorage.removeItem('integra_user');
          localStorage.removeItem('integra_setores');
          setUser(null);
        } else {
          // Se sobrar alguém, apenas atualiza o usuário para refletir quem sobrou
          const nextModule = remainingModules[0];
          const nextUser = getUserForModule(nextModule);
          setUser(nextUser);
        }
      } else {
        // Se não conseguir detectar módulo e não for clearAll, limpa o token global por precaução
        localStorage.removeItem('x-access-token');
        setUser(null);
      }
    }

    // SEGURANÇA: Limpa dados temporários de formulário (PII) ao deslogar
    sessionStorage.removeItem('info');
  };

  /**
   * Verifica se o usuário está autorizado para um ambiente específico.
   * Verifica primeiro o usuário do módulo específico, depois o global.
   */
  const isAuthorized = (environment) => {
    // Se não for passado ambiente, verifica apenas se está logado
    if (!environment || environment === 'global') {
      return !!user || !!getCurrentModuleUser();
    }
    
    // Tenta obter usuário do módulo específico
    const moduleUser = getUserForModule(environment);
    
    // Se houver usuário do módulo, verifica autorização
    if (moduleUser) {
      return !!moduleUser.authorizedEnvironments?.[environment];
    }
    
    // Fallback: verifica usuário atual (pode ser de outro módulo)
    if (user) {
      return !!user.authorizedEnvironments?.[environment];
    }
    
    return false;
  };

  return { user, loading, error, login, logout, isAuthorized };
};
