/**
 * Função utilitária para obter informações do navegador
 * Sem usar APIs externas
 */

/**
 * Obtém o User-Agent do navegador
 */
export function getUserAgent(): string {
  if (typeof window === 'undefined' || !window.navigator) {
    return '';
  }
  return window.navigator.userAgent || '';
}

/**
 * Valida se uma string tem formato de IP válido
 */
function isValidIPFormat(ip: string): boolean {
  if (!ip || ip.length < 7) return false; // IP mínimo: "1.1.1.1" = 7 chars
  
  // Validar IPv4
  const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
  if (ipv4Regex.test(ip)) {
    const parts = ip.split('.');
    return parts.length === 4 && parts.every(part => {
      const num = parseInt(part, 10);
      return !isNaN(num) && num >= 0 && num <= 255;
    });
  }
  
  // Validar IPv6 básico (formato simplificado)
  const ipv6Regex = /^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$|^::[0-9a-fA-F]{0,4}(:[0-9a-fA-F]{0,4}){0,6}$|^[0-9a-fA-F]{0,4}::[0-9a-fA-F]{0,4}(:[0-9a-fA-F]{0,4}){0,5}$/;
  if (ipv6Regex.test(ip)) {
    return true;
  }
  
  return false;
}

/**
 * Verifica se um IP é local/privado
 */
function isLocalIP(ip: string): boolean {
  // IPs locais/privados
  return (
    ip.startsWith('127.') ||
    ip.startsWith('192.168.') ||
    ip.startsWith('10.') ||
    ip.startsWith('172.16.') ||
    ip.startsWith('172.17.') ||
    ip.startsWith('172.18.') ||
    ip.startsWith('172.19.') ||
    ip.startsWith('172.20.') ||
    ip.startsWith('172.21.') ||
    ip.startsWith('172.22.') ||
    ip.startsWith('172.23.') ||
    ip.startsWith('172.24.') ||
    ip.startsWith('172.25.') ||
    ip.startsWith('172.26.') ||
    ip.startsWith('172.27.') ||
    ip.startsWith('172.28.') ||
    ip.startsWith('172.29.') ||
    ip.startsWith('172.30.') ||
    ip.startsWith('172.31.') ||
    ip.startsWith('169.254.') || // Link-local
    ip === '::1' ||
    ip.startsWith('fe80:') // IPv6 link-local
  );
}

/**
 * Tenta obter o IP usando WebRTC
 * Prioriza IP público, mas retorna IP local se não encontrar
 * Esta função não usa API externa, mas pode falhar em alguns navegadores
 * Retorna undefined se não conseguir obter
 */
export async function getLocalIP(): Promise<string | undefined> {
  return new Promise((resolve) => {
    // Verificar se está em ambiente browser
    if (typeof window === 'undefined' || typeof RTCPeerConnection === 'undefined') {
      resolve(undefined);
      return;
    }

    try {
      const pc = new RTCPeerConnection({
        iceServers: []
      });

      let resolved = false;
      let foundIPs: string[] = [];
      let publicIP: string | undefined = undefined;
      let localIP: string | undefined = undefined;

      const timeout = setTimeout(() => {
        if (!resolved) {
          resolved = true;
          pc.close();
          // Priorizar IP público, mas retornar local se não houver
          resolve(publicIP || localIP || undefined);
        }
      }, 5000); // Aumentar timeout para 5 segundos

      pc.onicecandidate = (event) => {
        if (event.candidate && !resolved) {
          const candidate = event.candidate.candidate;
          
          // Regex mais rigorosa para IPv4 - deve ser um IP completo e válido
          // Formato: X.X.X.X onde X é 0-255
          const ipv4Match = candidate.match(/\b([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\b/);
          
          // Regex para IPv6 - mais específica
          const ipv6Match = candidate.match(/\b([0-9a-fA-F]{1,4}(?::[0-9a-fA-F]{1,4}){2,7}|::[0-9a-fA-F]{1,4}(?::[0-9a-fA-F]{1,4}){0,6}|[0-9a-fA-F]{1,4}::[0-9a-fA-F]{1,4}(?::[0-9a-fA-F]{1,4}){0,5})\b/);
          
          let ip: string | undefined = undefined;
          
          if (ipv4Match && ipv4Match[1]) {
            const candidateIP = ipv4Match[1];
            // Validar se cada octeto está entre 0-255
            const parts = candidateIP.split('.');
            if (parts.length === 4 && parts.every(part => {
              const num = parseInt(part, 10);
              return !isNaN(num) && num >= 0 && num <= 255;
            })) {
              ip = candidateIP;
            }
          } else if (ipv6Match && ipv6Match[1]) {
            // Validar formato básico de IPv6
            const candidateIP = ipv6Match[1];
            if (candidateIP.includes(':') && candidateIP.length >= 3) {
              ip = candidateIP;
            }
          }
          
          // Validar se o IP é válido antes de processar
          if (ip && isValidIPFormat(ip) && !foundIPs.includes(ip)) {
            foundIPs.push(ip);
            
            // Ignorar localhost
            if (ip.startsWith('127.') || ip === '::1') {
              return;
            }
            
            // Separar IPs públicos e locais
            if (isLocalIP(ip)) {
              if (!localIP) {
                localIP = ip;
              }
            } else {
              // IP público encontrado!
              if (!publicIP) {
                publicIP = ip;
                // Se encontrou IP público, podemos resolver mais cedo
                if (!resolved) {
                  resolved = true;
                  clearTimeout(timeout);
                  pc.close();
                  resolve(publicIP);
                }
              }
            }
          }
        } else if (event.candidate === null) {
          // No more candidates
          if (!resolved) {
            resolved = true;
            clearTimeout(timeout);
            pc.close();
            // Retornar IP público se encontrou, senão local
            resolve(publicIP || localIP || undefined);
          }
        }
      };

      // Criar um data channel para forçar a criação de candidatos
      pc.createDataChannel('');
      pc.createOffer()
        .then((offer) => pc.setLocalDescription(offer))
        .catch(() => {
          if (!resolved) {
            resolved = true;
            clearTimeout(timeout);
            pc.close();
            resolve(publicIP || localIP || undefined);
          }
        });
    } catch (error) {
      console.warn("Erro ao obter IP via WebRTC:", error);
      resolve(undefined);
    }
  });
}

/**
 * Obtém informações completas do navegador
 */
export interface BrowserInfo {
  userAgent: string;
  ipAddress?: string;
}

export async function getBrowserInfo(): Promise<BrowserInfo> {
  const userAgent = getUserAgent();
  const ipAddress = await getLocalIP();
  
  return {
    userAgent,
    ipAddress,
  };
}

