<?php
require_once __DIR__ . '/../helpers/auth.php';
require_role(['admin', 'staff']);

$pdo = db();
$title = 'Live Map - IMS';

function h(?string $value): string
{
    return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
}

$preselectedId = (int)($_GET['delivery_id'] ?? $_GET['id'] ?? 0);

$deliveries = $pdo->query("\n    SELECT\n        d.id,\n        d.delivery_code,\n        d.status,\n        c.name AS customer_name,\n        u.full_name AS driver_name,\n        COALESCE(track.point_count, 0) AS point_count,\n        track.last_recorded_at\n    FROM deliveries d\n    LEFT JOIN customers c ON c.id = d.customer_id\n    LEFT JOIN users u ON u.id = d.assigned_driver_id\n    LEFT JOIN (\n        SELECT delivery_id, COUNT(*) AS point_count, MAX(recorded_at) AS last_recorded_at\n        FROM delivery_locations\n        GROUP BY delivery_id\n    ) track ON track.delivery_id = d.id\n    ORDER BY\n      CASE d.status\n        WHEN 'IN_TRANSIT' THEN 1\n        WHEN 'PICKED_UP' THEN 2\n        WHEN 'ASSIGNED' THEN 3\n        WHEN 'PENDING' THEN 4\n        WHEN 'DELIVERED' THEN 5\n        WHEN 'CANCELLED' THEN 6\n        ELSE 7\n      END,\n      COALESCE(d.scheduled_at, d.created_at) DESC,\n      d.id DESC\n    LIMIT 200\n")->fetchAll(PDO::FETCH_ASSOC);

$stats = [
    'tracked' => 0,
    'moving' => 0,
    'delivered' => 0,
    'with_points' => 0,
];
foreach ($deliveries as $delivery) {
    if ((int)$delivery['point_count'] > 0) {
        $stats['with_points']++;
    }
    if (in_array((string)$delivery['status'], ['PICKED_UP', 'IN_TRANSIT'], true)) {
        $stats['moving']++;
    }
    if ((string)$delivery['status'] === 'DELIVERED') {
        $stats['delivered']++;
    }
    if ($delivery['last_recorded_at'] !== null && strtotime((string)$delivery['last_recorded_at']) >= (time() - 900)) {
        $stats['tracked']++;
    }
}

require_once __DIR__ . '/../templates/header.php';
require_once __DIR__ . '/../templates/sidebar.php';
?>

<main class="col-12 col-lg-10 app-content">
  <div class="page-head">
    <div>
      <div class="page-kicker">Live tracking</div>
      <h1 class="page-title">Delivery map monitor</h1>
      <p class="page-subtitle">Watch the pickup point, dropoff point, most recent driver position, and the latest trail for any delivery with tracking enabled.</p>
    </div>
    <div class="d-flex gap-2 flex-wrap">
      <a class="btn btn-outline-secondary" id="detailLink" href="deliveries.php">Open delivery details</a>
      <a class="btn btn-dark" href="deliveries.php">Manage deliveries</a>
    </div>
  </div>

  <div class="row g-3 mb-3">
    <div class="col-12 col-md-6 col-xl-3">
      <div class="stat-card">
        <div class="stat-label">Live now</div>
        <div class="stat-value"><?= (int)$stats['tracked'] ?></div>
        <div class="stat-sub">Routes with a fresh GPS point in the last 15 minutes</div>
      </div>
    </div>
    <div class="col-12 col-md-6 col-xl-3">
      <div class="stat-card">
        <div class="stat-label">Active routes</div>
        <div class="stat-value"><?= (int)$stats['moving'] ?></div>
        <div class="stat-sub">Picked up or in transit</div>
      </div>
    </div>
    <div class="col-12 col-md-6 col-xl-3">
      <div class="stat-card">
        <div class="stat-label">With GPS history</div>
        <div class="stat-value"><?= (int)$stats['with_points'] ?></div>
        <div class="stat-sub">Deliveries with at least one saved point</div>
      </div>
    </div>
    <div class="col-12 col-md-6 col-xl-3">
      <div class="stat-card">
        <div class="stat-label">Delivered</div>
        <div class="stat-value"><?= (int)$stats['delivered'] ?></div>
        <div class="stat-sub">Completed deliveries on record</div>
      </div>
    </div>
  </div>

  <div class="row g-3">
    <div class="col-12 col-xl-4">
      <div class="card h-100">
        <div class="card-body p-4">
          <h5 class="mb-3">Choose delivery</h5>
          <select id="delivery_id" class="form-select mb-3">
            <option value="0">Select a delivery</option>
            <?php foreach ($deliveries as $delivery): ?>
              <option value="<?= (int)$delivery['id'] ?>" <?= $preselectedId === (int)$delivery['id'] ? 'selected' : '' ?>>
                <?= h($delivery['delivery_code']) ?> · <?= h((string)$delivery['status']) ?>
              </option>
            <?php endforeach; ?>
          </select>

          <div class="soft-panel mb-3">
            <div class="fw-semibold mb-2">Route snapshot</div>
            <div class="metric-inline"><span>Code</span><strong id="infoCode">-</strong></div>
            <div class="metric-inline"><span>Status</span><strong id="infoStatus">-</strong></div>
            <div class="metric-inline"><span>Driver</span><strong id="infoDriver">-</strong></div>
            <div class="metric-inline"><span>Pickup</span><strong id="infoPickup">-</strong></div>
            <div class="metric-inline"><span>Dropoff</span><strong id="infoDropoff">-</strong></div>
          </div>

          <div class="soft-panel mb-3">
            <div class="fw-semibold mb-2">Last GPS point</div>
            <div class="metric-inline"><span>Recorded</span><strong id="lastTime">-</strong></div>
            <div class="metric-inline"><span>Coordinates</span><strong id="lastCoords">-</strong></div>
            <div class="metric-inline"><span>Accuracy</span><strong id="lastMeta">-</strong></div>
          </div>

          <div class="soft-panel">
            <div class="fw-semibold mb-2">Route metrics</div>
            <div class="metric-inline"><span>Saved points</span><strong id="pointCount">0</strong></div>
            <div class="metric-inline"><span>Next stop</span><strong id="nextStop">-</strong></div>
            <div class="metric-inline"><span>Distance</span><strong id="distanceToNext">-</strong></div>
          </div>
        </div>
      </div>
    </div>

    <div class="col-12 col-xl-8">
      <div class="card map-panel h-100">
        <div class="card-body p-4">
          <div class="d-flex flex-wrap justify-content-between align-items-start gap-2 mb-3">
            <div>
              <h5 class="mb-1">Live route map</h5>
              <div class="text-muted small">Automatically refreshes every 5 seconds.</div>
            </div>
            <div class="form-check form-switch">
              <input class="form-check-input" type="checkbox" id="followDriver" checked>
              <label class="form-check-label" for="followDriver">Follow driver</label>
            </div>
          </div>
          <div id="map" class="map-canvas" style="min-height: 520px;"></div>
        </div>
      </div>
    </div>
  </div>
</main>

<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
const deliverySelect = document.getElementById('delivery_id');
const detailLink = document.getElementById('detailLink');
const infoCode = document.getElementById('infoCode');
const infoStatus = document.getElementById('infoStatus');
const infoDriver = document.getElementById('infoDriver');
const infoPickup = document.getElementById('infoPickup');
const infoDropoff = document.getElementById('infoDropoff');
const lastTime = document.getElementById('lastTime');
const lastCoords = document.getElementById('lastCoords');
const lastMeta = document.getElementById('lastMeta');
const pointCount = document.getElementById('pointCount');
const nextStop = document.getElementById('nextStop');
const distanceToNext = document.getElementById('distanceToNext');
const followDriver = document.getElementById('followDriver');

const map = L.map('map').setView([13.941, 121.615], 12);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  maxZoom: 19,
  attribution: '&copy; OpenStreetMap contributors'
}).addTo(map);

let pickupMarker = null;
let dropoffMarker = null;
let driverMarker = null;
let trailLine = null;
let firstFitDone = false;
let refreshTimer = null;

function ensureMarker(existing, lat, lng, label) {
  if (lat === null || lng === null || Number.isNaN(Number(lat)) || Number.isNaN(Number(lng))) return existing;
  const latlng = [Number(lat), Number(lng)];
  if (!existing) {
    existing = L.marker(latlng).addTo(map).bindPopup(label);
  } else {
    existing.setLatLng(latlng);
  }
  return existing;
}

function haversineMeters(a, b) {
  const R = 6371000;
  const toRad = (value) => value * Math.PI / 180;
  const dLat = toRad(b[0] - a[0]);
  const dLng = toRad(b[1] - a[1]);
  const lat1 = toRad(a[0]);
  const lat2 = toRad(b[0]);
  const sinDLat = Math.sin(dLat / 2);
  const sinDLng = Math.sin(dLng / 2);
  const h = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLng * sinDLng;
  return 2 * R * Math.atan2(Math.sqrt(h), Math.sqrt(1 - h));
}

function formatDistance(value) {
  if (!Number.isFinite(value)) return '-';
  if (value < 1000) return `${Math.round(value)} m`;
  return `${(value / 1000).toFixed(2)} km`;
}

async function fetchJson(url) {
  const response = await fetch(url, { headers: { 'Accept': 'application/json' } });
  const text = await response.text();
  try {
    return JSON.parse(text);
  } catch (error) {
    throw new Error(text.substring(0, 180) || 'Invalid JSON response');
  }
}

function selectedDeliveryId() {
  return Number(deliverySelect.value || 0);
}

function resetInfo() {
  infoCode.textContent = '-';
  infoStatus.textContent = '-';
  infoDriver.textContent = '-';
  infoPickup.textContent = '-';
  infoDropoff.textContent = '-';
  lastTime.textContent = '-';
  lastCoords.textContent = '-';
  lastMeta.textContent = '-';
  pointCount.textContent = '0';
  nextStop.textContent = '-';
  distanceToNext.textContent = '-';
  detailLink.href = 'deliveries.php';
}

async function refreshMap() {
  const deliveryId = selectedDeliveryId();
  if (!deliveryId) {
    resetInfo();
    return;
  }

  try {
    const [latest, points] = await Promise.all([
      fetchJson(`location_latest.php?delivery_id=${encodeURIComponent(deliveryId)}`),
      fetchJson(`location_points.php?delivery_id=${encodeURIComponent(deliveryId)}&limit=200`)
    ]);

    if (!latest.ok) {
      throw new Error(latest.error || 'Unable to load delivery');
    }

    detailLink.href = `delivery_view.php?id=${encodeURIComponent(deliveryId)}`;
    infoCode.textContent = latest.delivery.delivery_code || '-';
    infoStatus.textContent = latest.delivery.status || '-';
    infoDriver.textContent = latest.delivery.driver_name || 'Unassigned';
    infoPickup.textContent = latest.delivery.pickup_address || '-';
    infoDropoff.textContent = latest.delivery.dropoff_address || '-';

    if (latest.delivery.pickup_lat !== null && latest.delivery.pickup_lng !== null) {
      pickupMarker = ensureMarker(pickupMarker, latest.delivery.pickup_lat, latest.delivery.pickup_lng, 'Pickup');
    } else if (pickupMarker) {
      map.removeLayer(pickupMarker);
      pickupMarker = null;
    }
    if (latest.delivery.dropoff_lat !== null && latest.delivery.dropoff_lng !== null) {
      dropoffMarker = ensureMarker(dropoffMarker, latest.delivery.dropoff_lat, latest.delivery.dropoff_lng, 'Dropoff');
    } else if (dropoffMarker) {
      map.removeLayer(dropoffMarker);
      dropoffMarker = null;
    }

    pointCount.textContent = String((latest.route_stats && latest.route_stats.point_count) || 0);

    let nextCoordinates = null;
    if (latest.delivery.status === 'PICKED_UP' || latest.delivery.status === 'IN_TRANSIT') {
      nextStop.textContent = 'Dropoff';
      if (latest.delivery.dropoff_lat !== null && latest.delivery.dropoff_lng !== null) {
        nextCoordinates = [Number(latest.delivery.dropoff_lat), Number(latest.delivery.dropoff_lng)];
      }
    } else if (latest.delivery.status === 'DELIVERED') {
      nextStop.textContent = 'Complete';
    } else {
      nextStop.textContent = 'Pickup';
      if (latest.delivery.pickup_lat !== null && latest.delivery.pickup_lng !== null) {
        nextCoordinates = [Number(latest.delivery.pickup_lat), Number(latest.delivery.pickup_lng)];
      }
    }

    if (latest.latest) {
      driverMarker = ensureMarker(driverMarker, latest.latest.lat, latest.latest.lng, 'Driver');
      lastTime.textContent = latest.latest.recorded_at || '-';
      lastCoords.textContent = `${Number(latest.latest.lat).toFixed(6)}, ${Number(latest.latest.lng).toFixed(6)}`;
      const accuracy = latest.latest.accuracy_m !== null ? `${Math.round(latest.latest.accuracy_m)} m` : '-';
      const speed = latest.latest.speed_mps !== null ? `${Number(latest.latest.speed_mps).toFixed(1)} m/s` : '-';
      lastMeta.textContent = `${accuracy} · ${speed}`;
      if (nextCoordinates) {
        distanceToNext.textContent = formatDistance(haversineMeters([Number(latest.latest.lat), Number(latest.latest.lng)], nextCoordinates));
      } else {
        distanceToNext.textContent = '-';
      }
      if (followDriver.checked && driverMarker) {
        map.setView(driverMarker.getLatLng(), Math.max(map.getZoom(), 15));
      }
    } else {
      if (driverMarker) {
        map.removeLayer(driverMarker);
        driverMarker = null;
      }
      lastTime.textContent = 'No GPS yet';
      lastCoords.textContent = '-';
      lastMeta.textContent = '-';
      distanceToNext.textContent = '-';
    }

    if (points.ok && Array.isArray(points.points) && points.points.length > 1) {
      const polylinePoints = points.points.map((point) => [Number(point.lat), Number(point.lng)]);
      if (!trailLine) {
        trailLine = L.polyline(polylinePoints).addTo(map);
      } else {
        trailLine.setLatLngs(polylinePoints);
      }
    } else if (trailLine) {
      trailLine.setLatLngs([]);
    }

    if (!firstFitDone) {
      const bounds = [];
      if (pickupMarker) bounds.push(pickupMarker.getLatLng());
      if (dropoffMarker) bounds.push(dropoffMarker.getLatLng());
      if (driverMarker) bounds.push(driverMarker.getLatLng());
      if (bounds.length >= 2) {
        map.fitBounds(L.latLngBounds(bounds), { padding: [30, 30] });
        firstFitDone = true;
      } else if (bounds.length === 1) {
        map.setView(bounds[0], 15);
        firstFitDone = true;
      }
    }
  } catch (error) {
    lastTime.textContent = error.message;
  }
}

deliverySelect.addEventListener('change', () => {
  firstFitDone = false;
  if (pickupMarker) { map.removeLayer(pickupMarker); pickupMarker = null; }
  if (dropoffMarker) { map.removeLayer(dropoffMarker); dropoffMarker = null; }
  if (driverMarker) { map.removeLayer(driverMarker); driverMarker = null; }
  if (trailLine) { trailLine.setLatLngs([]); }
  refreshMap();
  if (refreshTimer !== null) {
    window.clearInterval(refreshTimer);
  }
  refreshTimer = window.setInterval(refreshMap, 5000);
});

if (selectedDeliveryId()) {
  refreshMap();
  refreshTimer = window.setInterval(refreshMap, 5000);
}
</script>

<?php require_once __DIR__ . '/../templates/footer.php'; ?>
