<?php $title = 'Mapa de Clientes'; ?>

<div class="card">
    <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
        <h1>Mapa de Clientes</h1>
        <div style="display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap;">
            <a href="/clientes" class="btn btn-secondary">Voltar</a>
            <button id="loadBtn" class="btn">Carregar Endereços</button>
            <button id="geolocateBtn" class="btn btn-secondary" title="Centralizar no meu local">📍 Minha Localização</button>
            <input id="searchName" class="input" placeholder="Buscar por nome/identificação" style="min-width: 220px;" />
            <select id="typeFilter" class="input" style="min-width: 160px;">
                <option value="">Todos os tipos</option>
                <option value="PJ">Pessoa Jurídica</option>
                <option value="PF">Pessoa Física</option>
            </select>
            <label style="display:flex; align-items:center; gap:0.25rem; font-size:0.9rem; color:#555;">
                <input type="checkbox" id="visibleArea" /> Filtrar pela área visível
            </label>
            <button id="applyFiltersBtn" class="btn btn-secondary">Aplicar Filtros</button>
        </div>
    </div>
    <style>
      /* Garantir layout correto do Leaflet mesmo sem CSS externo */
      #map { height: 520px; }
      .leaflet-container { position: relative; overflow: hidden; }
      .leaflet-container img { max-width: none !important; }
      .leaflet-container .leaflet-tile { max-width: none !important; }
      /* Fallback essencial do CSS do Leaflet: posicionamento absoluto das camadas e tiles */
      .leaflet-pane,
      .leaflet-tile,
      .leaflet-marker-icon,
      .leaflet-shadow,
      .leaflet-zoom-box,
      .leaflet-image-layer,
      .leaflet-layer { position: absolute; left: 0; top: 0; }
      .leaflet-map-pane,
      .leaflet-tile-pane,
      .leaflet-overlay-pane,
      .leaflet-shadow-pane,
      .leaflet-marker-pane,
      .leaflet-tooltip-pane,
      .leaflet-popup-pane { position: absolute; left: 0; top: 0; }
      .leaflet-map-pane { transform-origin: 0 0; }
      .leaflet-tile { width: 256px; height: 256px; user-select: none; }
      .leaflet-marker-icon, .leaflet-shadow { display: block; }
    </style>
    <div id="map" style="height: 520px; border-radius: 8px; border: 1px solid #e0e0e0;"></div>
    <div id="status" style="margin-top: 0.75rem; font-size: 0.9rem; color: #555;"></div>
    <details id="geoDetails" style="margin-top: 0.5rem;">
        <summary>Detalhes de geocodificação</summary>
        <div id="failList" style="padding: 0.5rem; font-size: 0.9rem; color: #555;"></div>
    </details>
</div>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5rqVQH3jBs=" crossorigin="anonymous" />
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin="anonymous"></script>
<script>
  // Fallback para Leaflet caso CDN principal falhe
  (function() {
    var sources = [
      { css: 'https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css', js: 'https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.js' },
      { css: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.css', js: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.js' },
      { css: '/assets/leaflet/leaflet.css', js: '/assets/leaflet/leaflet.js' }
    ];
    function inject(src) {
      var css = document.createElement('link');
      css.rel = 'stylesheet';
      css.href = src.css;
      css.crossOrigin = 'anonymous';
      document.head.appendChild(css);
      var js = document.createElement('script');
      js.src = src.js;
      js.crossOrigin = 'anonymous';
      document.head.appendChild(js);
    }
    var idx = 0;
    function tryNext() {
      if (window.L) return;
      if (idx >= sources.length) return;
      inject(sources[idx++]);
      setTimeout(function(){ if (!window.L) tryNext(); }, 900);
    }
    setTimeout(function(){ if (!window.L) tryNext(); }, 600);
  })();
</script>

<script>
    var map, markersLayer, allClients = [], failures = [];
    document.addEventListener('DOMContentLoaded', () => {
        const statusEl = document.getElementById('status');
        try {
            if (!window.L) throw new Error('Leaflet não carregou. Verifique sua conexão com a internet.');
            map = L.map('map').setView([-14.2350, -51.9253], 4); // Brasil
            L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                attribution: '&copy; OpenStreetMap contributors'
            }).addTo(map);
            markersLayer = L.layerGroup().addTo(map);

            // Corrigir ícone padrão bloqueado por ORB/CDN, usando ícone inline SVG
            (function() {
                const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28"><circle cx="14" cy="14" r="10" fill="#3f82ff" stroke="#ffffff" stroke-width="3"/></svg>';
                const DefaultIcon = L.icon({
                    iconUrl: 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg),
                    iconSize: [28, 28],
                    iconAnchor: [14, 14],
                    popupAnchor: [0, -14],
                    className: 'ge-default-marker'
                });
                L.Marker.prototype.options.icon = DefaultIcon;
            })();

            // Garantir cálculo correto do tamanho após renderização
            setTimeout(() => { try { map.invalidateSize(); } catch(_){} }, 300);

            document.getElementById('loadBtn').addEventListener('click', loadAndPlotClients);
            document.getElementById('geolocateBtn').addEventListener('click', geolocateUser);
            document.getElementById('applyFiltersBtn').addEventListener('click', () => plotClients(applyFilters()));
            document.getElementById('searchName').addEventListener('keyup', (e) => { if (e.key === 'Enter') plotClients(applyFilters()); });
            map.on('moveend', () => { const cb = document.getElementById('visibleArea'); if (cb.checked) plotClients(applyFilters()); });
        } catch (err) {
            statusEl.textContent = 'Erro ao inicializar o mapa: ' + (err?.message || 'Falha desconhecida ao carregar Leaflet');
        }
    });

    async function loadAndPlotClients() {
        const statusEl = document.getElementById('status');
        statusEl.textContent = 'Buscando clientes com endereço...';
        try {
            const resp = await apiRequest('/api/clientes/with-address');
            if (!resp || !resp.ok) { throw new Error('Falha ao carregar clientes'); }
            const payload = await resp.json();
            allClients = payload.data || [];
            statusEl.textContent = `Encontrados ${allClients.length} clientes. Geocodificando endereços...`;
            failures = [];
            renderFailures();
            await plotClients(applyFilters());
        } catch (err) {
            statusEl.textContent = 'Erro: ' + (err?.message || 'Falha desconhecida');
        }
    }

    function buildAddress(c) {
        const parts = [];
        if (c.logradouro) parts.push(c.logradouro);
        if (c.numero) parts.push(String(c.numero));
        if (c.bairro) parts.push(c.bairro);
        if (c.cidade) parts.push(c.cidade);
        if (c.estado) parts.push(c.estado);
        if (c.cep) parts.push(String(c.cep));
        return parts.join(', ');
    }
    async function geocodeClient(c) {
        // Usa proxy do backend para respeitar política de uso do Nominatim e evitar bloqueios do navegador
        const q = buildAddress(c);
        if (!q) return null;
        try {
            const qs = new URLSearchParams({
                logradouro: c.logradouro || '',
                numero: c.numero != null ? String(c.numero) : '',
                bairro: c.bairro || '',
                cidade: c.cidade || '',
                estado: c.estado || '',
                cep: (c.cep || '').toString()
            });
            const resp = await apiRequest(`/api/clientes/geocode?${qs.toString()}`);
            if (!resp || !resp.ok) return null;
            const data = await resp.json();
            if (!data || !data.ok) return null;
            return { lat: parseFloat(data.lat), lon: parseFloat(data.lon) };
        } catch (err) { return null; }
    }

    async function plotClients(clients) {
        markersLayer.clearLayers();
        const bounds = [];
        const statusEl = document.getElementById('status');
        let processed = 0;
        let plotted = 0;
        
        for (const c of clients) {
            let geo = null;
            if (c.latitude != null && c.longitude != null) {
                geo = { lat: parseFloat(c.latitude), lon: parseFloat(c.longitude) };
            } else {
                const addr = buildAddress(c);
                if (!addr) { 
                    failures.push({ client: c, reason: 'incomplete_address', missing: diagnoseAddress(c) });
                    processed++; 
                    statusEl.textContent = `Processados ${processed}/${clients.length} - Plotados: ${plotted}`; 
                    continue; 
                }
                // Nominatim tem limites — faça com atraso pequeno para reduzir rate-limit
                try {
                    geo = await geocodeClient(c);
                } catch (err) {
                    console.warn('Erro ao geocodificar:', addr, err);
                }
                if (!geo) {
                    failures.push({ client: c, reason: 'geocode_failed', address: addr });
                }
            }
            
            if (geo) {
                const addrLabel = buildAddress(c);
                const clientName = c.nome_fantasia || c.razao_social || 'Cliente';
                const clientType = c.tipo === 'PJ' ? 'Pessoa Jurídica' : 'Pessoa Física';
                const clientDoc = c.tipo === 'PJ' ? (c.cnpj || '') : (c.cpf || '');
                
                const popupContent = `
                    <div style="min-width: 200px;">
                        <h4 style="margin: 0 0 8px 0; color: #333;">${clientName}</h4>
                        <p style="margin: 4px 0; font-size: 0.9em; color: #666;">
                            <strong>Tipo:</strong> ${clientType}<br>
                            ${clientDoc ? `<strong>Documento:</strong> ${clientDoc}<br>` : ''}
                            <strong>Endereço:</strong> ${addrLabel}
                        </p>
                        <div style="margin-top: 8px;">
                            <a href="/clientes/${c.id}" class="btn btn-sm" style="font-size: 0.8em; padding: 4px 8px;">Ver Detalhes</a>
                        </div>
                    </div>
                `;
                
                const marker = L.marker([geo.lat, geo.lon]).bindPopup(popupContent);
                markersLayer.addLayer(marker);
                bounds.push([geo.lat, geo.lon]);
                plotted++;
            }
            
            processed++;
            statusEl.textContent = `Processados ${processed}/${clients.length} - Plotados: ${plotted}`;
            
            // Delay menor para endereços já geocodificados
            if (!c.latitude || !c.longitude) {
                await new Promise(r => setTimeout(r, 1000));
            }
        }
        
        renderFailures();
        if (bounds.length) {
            map.fitBounds(bounds, { padding: [30, 30] });
            statusEl.textContent = `Concluído! ${plotted} clientes plotados de ${clients.length} processados. Falhas: ${failures.length}.`;
        } else {
            statusEl.textContent = `Nenhum endereço foi geocodificado com sucesso. Falhas: ${failures.length}.`;
        }
    }

    function applyFilters() {
        const name = (document.getElementById('searchName').value || '').toLowerCase();
        const type = document.getElementById('typeFilter').value;
        const area = document.getElementById('visibleArea').checked;

        let list = allClients.slice();
        if (name) {
            list = list.filter(c => {
                const target = `${c.nome_fantasia || ''} ${c.razao_social || ''} ${c.nome || ''} ${c.cnpj || ''} ${c.cpf || ''}`.toLowerCase();
                return target.includes(name);
            });
        }
        if (type) {
            list = list.filter(c => (c.tipo || '').toUpperCase() === type.toUpperCase());
        }
        if (area) {
            const b = map.getBounds();
            list = list.filter(c => {
                const lat = c.latitude ?? c.lat;
                const lon = c.longitude ?? c.lng ?? c.lon;
                if (lat == null || lon == null) return false;
                return b.contains([parseFloat(lat), parseFloat(lon)]);
            });
        }
        return list;
    }

    function geolocateUser() {
        const statusEl = document.getElementById('status');
        const geoBtn = document.getElementById('geolocateBtn');
        
        if (!navigator.geolocation) {
            statusEl.textContent = 'Geolocalização não é suportada pelo seu navegador.';
            return;
        }
        
        geoBtn.disabled = true;
        geoBtn.textContent = '📍 Localizando...';
        statusEl.textContent = 'Obtendo sua localização...';
        
        navigator.geolocation.getCurrentPosition(
            (position) => {
                const { latitude, longitude } = position.coords;
                
                // Centraliza o mapa na localização do usuário
                map.setView([latitude, longitude], 12);
                
                // Adiciona um marcador especial para a localização do usuário
                const userMarker = L.marker([latitude, longitude], {
                    icon: L.divIcon({
                        className: 'user-location-marker',
                        html: '<div style="background: #007bff; color: white; border-radius: 50%; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; font-size: 12px; border: 2px solid white; box-shadow: 0 2px 4px rgba(0,0,0,0.3);">📍</div>',
                        iconSize: [20, 20],
                        iconAnchor: [10, 10]
                    })
                }).bindPopup('<b>Sua Localização</b><br>Você está aqui!');
                
                markersLayer.addLayer(userMarker);
                
                statusEl.textContent = 'Localização encontrada! Mapa centralizado na sua posição.';
                geoBtn.disabled = false;
                geoBtn.textContent = '📍 Minha Localização';
            },
            (error) => {
                let errorMsg = 'Erro ao obter localização: ';
                switch(error.code) {
                    case error.PERMISSION_DENIED:
                        errorMsg += 'Permissão negada pelo usuário.';
                        break;
                    case error.POSITION_UNAVAILABLE:
                        errorMsg += 'Localização indisponível.';
                        break;
                    case error.TIMEOUT:
                        errorMsg += 'Tempo limite excedido.';
                        break;
                    default:
                        errorMsg += 'Erro desconhecido.';
                        break;
                }
                statusEl.textContent = errorMsg;
                geoBtn.disabled = false;
                geoBtn.textContent = '📍 Minha Localização';
            },
            {
                enableHighAccuracy: true,
                timeout: 10000,
                maximumAge: 300000 // 5 minutos
            }
        );
    }

    // Carrega automaticamente os clientes ao abrir a página
    window.addEventListener('load', () => {
        setTimeout(loadAndPlotClients, 500);
    });
</script>
<script>
    function diagnoseAddress(c) {
        const missing = [];
        if (!c.logradouro) missing.push('logradouro');
        if (!c.numero) missing.push('número');
        if (!c.bairro) missing.push('bairro');
        if (!c.cidade) missing.push('cidade');
        if (!c.estado) missing.push('UF');
        const cepDigits = (c.cep || '').toString().replace(/\D/g,'');
        if (!cepDigits) missing.push('CEP');
        return missing;
    }

    function renderFailures() {
        const listEl = document.getElementById('failList');
        const detailsEl = document.getElementById('geoDetails');
        const count = failures.length;
        detailsEl.firstElementChild.textContent = `Detalhes de geocodificação (${count} falha${count === 1 ? '' : 's'})`;
        if (!count) { listEl.innerHTML = '<em>Nenhuma falha.</em>'; return; }
        const rows = failures.map(f => {
            const nome = f.client.nome_fantasia || f.client.razao_social || `Cliente #${f.client.id}`;
            if (f.reason === 'incomplete_address') {
                return `• ${nome}: endereço incompleto — faltando ${f.missing.join(', ')}.`;
            }
            if (f.reason === 'geocode_failed') {
                return `• ${nome}: não foi possível geocodificar "${f.address}".`;
            }
            return `• ${nome}: falha desconhecida.`;
        });
        listEl.innerHTML = rows.join('<br>');
    }
</script>