<?php
declare(strict_types=1);

require_once __DIR__ . '/_bootstrap.php';
admin_require_login();
?>
<!doctype html>
<html lang="pt-BR">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Bulo Admin - Tempo real</title>
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
  <link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.css">
  <link rel="stylesheet" href="assets/admin.css?v=20260626-1">
</head>
<body>
  <?php admin_sidebar('tempo_real'); ?>

  <main class="page">
    <section class="panel live-panel">
      <div class="panel-header live-header">
        <div>
          <h1>Tempo real</h1>
          <p>Motoristas online no mapa e corridas abertas acompanhadas automaticamente.</p>
        </div>
        <div class="live-updated" id="liveUpdated">Carregando...</div>
      </div>
      <div class="panel-body">
        <div class="live-map-shell">
          <div id="tempoRealMap" class="live-map"></div>
          <div class="live-map-note">
            <span class="live-dot"></span>
            Motoristas online com localização recebida pelo app.
          </div>
        </div>
      </div>
    </section>

    <section class="dashboard-grid live-stats">
      <div class="stat-card stat-blue">
        <div>
          <strong id="totalMotoristasOnline">0</strong>
          <span>Motoristas online</span>
          <small>Com posicao atual no painel</small>
        </div>
      </div>
      <div class="stat-card stat-orange">
        <div>
          <strong id="totalChamadas">0</strong>
          <span>Chamadas abertas</span>
          <small>Corridas aguardando aceite</small>
        </div>
      </div>
      <div class="stat-card stat-green">
        <div>
          <strong id="totalEmCurso">0</strong>
          <span>Em andamento</span>
          <small>Aceitas ou em viagem</small>
        </div>
      </div>
    </section>

    <section class="panel">
      <div class="panel-header">
        <h1>Corridas ocorrendo agora</h1>
        <p>Lista sem corridas finalizadas ou canceladas.</p>
      </div>
      <div class="panel-body">
        <div class="table-wrap">
          <table>
            <thead>
              <tr>
                <th>ID</th>
                <th>Status</th>
                <th>Passageiro</th>
                <th>Motorista</th>
                <th>Valor</th>
                <th>Pagamento</th>
                <th>Criada em</th>
              </tr>
            </thead>
            <tbody id="corridasTempoReal">
              <tr><td colspan="7">Carregando corridas...</td></tr>
            </tbody>
          </table>
        </div>
      </div>
    </section>
  </main>

  <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
  <script src="https://unpkg.com/leaflet.markercluster@1.5.3/dist/leaflet.markercluster.js"></script>
  <script>
    const map = L.map('tempoRealMap', { zoomControl: true }).setView([-31.7669, -52.3420], 13);
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      maxZoom: 19,
      attribution: '&copy; OpenStreetMap'
    }).addTo(map);

    const driverLayer = typeof L.markerClusterGroup === 'function'
      ? L.markerClusterGroup({
          chunkedLoading: true,
          showCoverageOnHover: false,
          spiderfyOnMaxZoom: true,
          disableClusteringAtZoom: 16,
          maxClusterRadius: (zoom) => zoom < 12 ? 72 : 54,
          iconCreateFunction: (cluster) => {
            const count = cluster.getChildCount();
            const size = count < 10 ? 'small' : (count < 50 ? 'medium' : 'large');
            return L.divIcon({
              html: `<div><strong>${count}</strong><span>motoristas</span></div>`,
              className: `driver-cluster driver-cluster-${size}`,
              iconSize: L.point(size === 'large' ? 76 : (size === 'medium' ? 66 : 56), size === 'large' ? 76 : (size === 'medium' ? 66 : 56))
            });
          }
        }).addTo(map)
      : L.layerGroup().addTo(map);
    const rideLayer = L.layerGroup().addTo(map);
    const dynamicLayer = L.layerGroup().addTo(map);
    let firstFit = true;
    let lastMotoristas = [];
    let ultimaAtualizacaoDinamica = 0;
    const intervaloDinamicaMs = 120000;

    const money = new Intl.NumberFormat('pt-BR', {
      style: 'currency',
      currency: 'BRL'
    });

    function escapeHtml(value) {
      return String(value ?? '')
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#039;');
    }

    function idadeLocalizacao(segundos) {
      if (segundos === null || segundos === undefined) return 'sem horario';
      if (segundos < 60) return 'agora';
      const minutos = Math.floor(segundos / 60);
      if (minutos < 60) return `${minutos} min atras`;
      const horas = Math.floor(minutos / 60);
      return `${horas} h atras`;
    }

    function driverMarkerScale() {
      const zoom = map.getZoom();
      if (zoom <= 4) return 0.32;
      if (zoom <= 6) return 0.42;
      if (zoom <= 8) return 0.52;
      if (zoom <= 10) return 0.64;
      if (zoom <= 12) return 0.78;
      if (zoom <= 14) return 0.9;
      return 1;
    }

    function carIcon(rumo) {
      const scale = driverMarkerScale();
      return L.divIcon({
        className: 'driver-car-icon',
        iconSize: [42, 42],
        iconAnchor: [21, 21],
        popupAnchor: [0, -18],
        html: `
          <div class="driver-car-marker" style="--car-rotation:${Number(rumo || 0)}deg;--car-scale:${scale};">
            <span class="car-window"></span>
            <span class="car-wheel wheel-left"></span>
            <span class="car-wheel wheel-right"></span>
          </div>
        `
      });
    }

    function renderMotoristas(motoristas, bounds) {
      lastMotoristas = motoristas;
      driverLayer.clearLayers();

      motoristas.forEach((motorista) => {
        const pos = [motorista.lat, motorista.lng];
        bounds.push(pos);
        const veiculo = motorista.veiculo || {};
        const veiculoTexto = [veiculo.marca, veiculo.modelo, veiculo.ano_modelo, veiculo.cor, veiculo.placa]
          .filter(Boolean)
          .join(' ');
        const tooltip = `
          <div class="driver-tooltip-card">
            <strong>${escapeHtml(motorista.nome)}</strong>
            <span>Nota ${Number(motorista.nota_media || 0).toFixed(2)} (${motorista.total_avaliacoes || 0})</span>
            <span>${escapeHtml(veiculoTexto || 'Veículo não informado')}</span>
            <span>${escapeHtml(motorista.celular || '')}</span>
            <small>Atualizado: ${idadeLocalizacao(motorista.localizacao_idade_segundos)}</small>
          </div>
        `;
        L.marker(pos, { icon: carIcon(motorista.rumo) })
          .bindTooltip(tooltip, {
            sticky: true,
            direction: 'top',
            opacity: 0.98,
            className: 'driver-tooltip'
          })
          .addTo(driverLayer);
      });
    }

    function renderCorridasMapa(corridas, bounds) {
      rideLayer.clearLayers();

      corridas.forEach((corrida) => {
        const origemOk = corrida.origem_lat !== null && corrida.origem_lng !== null;
        const destinoOk = corrida.destino_lat !== null && corrida.destino_lng !== null;
        if (!origemOk) return;

        const origem = [corrida.origem_lat, corrida.origem_lng];
        bounds.push(origem);
        L.circleMarker(origem, {
          radius: 8,
          color: '#ff9138',
          weight: 3,
          fillColor: '#ffffff',
          fillOpacity: 1
        }).bindTooltip(`#${corrida.id} - ${escapeHtml(corrida.passageiro_nome || 'Passageiro')}`).addTo(rideLayer);

        if (destinoOk) {
          const destino = [corrida.destino_lat, corrida.destino_lng];
          bounds.push(destino);
          L.circleMarker(destino, {
            radius: 7,
            color: '#08a957',
            weight: 3,
            fillColor: '#ffffff',
            fillOpacity: 1
          }).addTo(rideLayer);
          L.polyline([origem, destino], {
            color: '#1683f7',
            weight: 4,
            opacity: 0.55,
            dashArray: '8 8'
          }).addTo(rideLayer);
        }
      });
    }

    function dynamicColor(multiplier) {
      if (multiplier >= 1.75) return '#ef4444';
      if (multiplier >= 1.40) return '#f97316';
      return '#facc15';
    }

    function nomeCategoria(categoria) {
      if (categoria === 'plus') return 'Plus';
      if (categoria === 'pro') return 'Pro';
      return 'Economica';
    }

    function renderDinamicas(celulas, bounds) {
      dynamicLayer.clearLayers();

      celulas.forEach((celula) => {
        if (!Array.isArray(celula.poligono) || celula.poligono.length < 3) return;
        const multiplicador = Number(celula.multiplicador || 1);
        if (multiplicador <= 1) return;

        const pontos = celula.poligono.map((ponto) => [Number(ponto.lat), Number(ponto.lng)]);
        pontos.forEach((ponto) => bounds.push(ponto));
        const color = dynamicColor(multiplicador);
        const polygon = L.polygon(pontos, {
          color,
          weight: 2,
          fillColor: color,
          fillOpacity: 0.26,
          dashArray: '6 5'
        }).addTo(dynamicLayer);

        const centro = celula.centro && Number.isFinite(Number(celula.centro.lat)) && Number.isFinite(Number(celula.centro.lng))
          ? [Number(celula.centro.lat), Number(celula.centro.lng)]
          : polygon.getBounds().getCenter();
        L.marker(centro, {
          interactive: false,
          icon: L.divIcon({
            className: 'dynamic-center-label',
            html: `<span style="--dynamic-color:${color};">${multiplicador.toFixed(1)}x</span>`,
            iconSize: [72, 34],
            iconAnchor: [36, 17]
          })
        }).addTo(dynamicLayer);

        polygon.bindTooltip(`
          <div class="dynamic-tooltip-card">
            <strong>${escapeHtml(celula.regiao || 'Regiao')} - ${nomeCategoria(celula.categoria)}</strong>
            <span>${multiplicador.toFixed(2)}x</span>
            <small>${escapeHtml(celula.demanda)} chamada(s) / ${escapeHtml(celula.motoristas)} motorista(s)</small>
            <small>Janela: ${escapeHtml(celula.janela_minutos || 12)} min</small>
          </div>
        `, {
          sticky: true,
          direction: 'top',
          opacity: 0.98,
          className: 'driver-tooltip'
        });
      });
    }

    function statusClass(status) {
      if (status === 'em_andamento' || status === 'aceita') return 'badge-ok';
      return 'badge-warn';
    }

    function renderTabela(corridas) {
      const tbody = document.getElementById('corridasTempoReal');
      if (!corridas.length) {
        tbody.innerHTML = '<tr><td colspan="7">Nenhuma corrida ativa no momento.</td></tr>';
        return;
      }

      tbody.innerHTML = corridas.map((corrida) => `
        <tr>
          <td>#${escapeHtml(corrida.id)}</td>
          <td><span class="badge ${statusClass(corrida.status)}">${escapeHtml(corrida.status)}</span></td>
          <td>${escapeHtml(corrida.passageiro_nome || '--')}<br><small>${escapeHtml(corrida.passageiro_celular || '')}</small></td>
          <td>${escapeHtml(corrida.motorista_nome || 'Aguardando aceite')}<br><small>${escapeHtml(corrida.motorista_celular || '')}</small></td>
          <td>${corrida.valor === null ? '--' : money.format(corrida.valor)}</td>
          <td>${escapeHtml(corrida.forma_pagamento || '--')}</td>
          <td>${escapeHtml(corrida.criada_em || '--')}</td>
        </tr>
      `).join('');
    }

    function renderResumo(data) {
      const corridas = data.corridas || [];
      const chamadas = corridas.filter((c) => c.status === 'pendente').length;
      const emCurso = corridas.filter((c) => c.status === 'aceita' || c.status === 'em_andamento').length;

      document.getElementById('totalMotoristasOnline').textContent = String((data.motoristas || []).length);
      document.getElementById('totalChamadas').textContent = String(chamadas);
      document.getElementById('totalEmCurso').textContent = String(emCurso);
      document.getElementById('liveUpdated').textContent = `Atualizado em ${data.atualizado_em || '--'}`;
    }

    async function carregarTempoReal(forcarDinamica = false) {
      try {
        const agora = Date.now();
        const atualizarDinamica = forcarDinamica || (agora - ultimaAtualizacaoDinamica >= intervaloDinamicaMs);
        const response = await fetch(`tempo_real_dados.php?incluir_dinamicas=${atualizarDinamica ? '1' : '0'}`, { cache: 'no-store' });
        if (response.status === 401) {
          window.location.href = 'login.php';
          return;
        }
        const data = await response.json();
        if (!data.success) throw new Error(data.message || 'Erro ao carregar tempo real.');

        const bounds = [];
        if (data.dinamicas_atualizadas) {
          renderDinamicas(data.dinamicas || [], bounds);
          ultimaAtualizacaoDinamica = agora;
        }
        renderMotoristas(data.motoristas || [], bounds);
        renderCorridasMapa(data.corridas || [], bounds);
        renderTabela(data.corridas || []);
        renderResumo(data);

        if (bounds.length > 0) {
          const latLngBounds = L.latLngBounds(bounds);
          if (firstFit) {
            map.fitBounds(latLngBounds.pad(0.2), { maxZoom: 15 });
            firstFit = false;
          }
        } else if (data.map_center && firstFit) {
          map.setView([data.map_center.lat, data.map_center.lng], data.map_center.zoom || 13);
          firstFit = false;
        }
      } catch (error) {
        document.getElementById('liveUpdated').textContent = 'Falha ao atualizar';
      }
    }

    map.on('zoomend', () => {
      renderMotoristas(lastMotoristas, []);
    });

    carregarTempoReal(true);
    setInterval(() => {
      if (!document.hidden) {
        carregarTempoReal();
      }
    }, 15000);
    document.addEventListener('visibilitychange', () => {
      if (!document.hidden) {
        carregarTempoReal(true);
      }
    });
  </script>
</body>
</html>
