<?php

declare(strict_types=1);

namespace App\Repositories;

use PDO;

class ZonaRepository
{
    private PDO $db;

    public function __construct(PDO $db)
    {
        $this->db = $db;
    }

    public function todas(): array
    {
        $stmt = $this->db->query('SELECT * FROM zonas ORDER BY nombre');

        return $stmt->fetchAll();
    }

    public function buscarPorId(int $id): ?array
    {
        $stmt = $this->db->prepare('SELECT * FROM zonas WHERE id = :id');
        $stmt->execute(['id' => $id]);
        $zona = $stmt->fetch();

        return $zona ?: null;
    }

    /**
     * Busca la zona de cobertura cuyo centro está más cerca de la coordenada dada
     * y dentro de su radio_km. Cálculo aproximado con fórmula haversine en SQL.
     */
    public function buscarPorCoordenada(float $lat, float $lng): ?array
    {
        $sql = "SELECT *,
                (6371 * ACOS(
                    COS(RADIANS(:lat1)) * COS(RADIANS(centro_lat)) *
                    COS(RADIANS(centro_lng) - RADIANS(:lng)) +
                    SIN(RADIANS(:lat2)) * SIN(RADIANS(centro_lat))
                )) AS distancia_centro_km
                FROM zonas
                HAVING distancia_centro_km <= radio_km
                ORDER BY distancia_centro_km ASC
                LIMIT 1";

        $stmt = $this->db->prepare($sql);
        $stmt->execute(['lat1' => $lat, 'lat2' => $lat, 'lng' => $lng]);
        $zona = $stmt->fetch();

        return $zona ?: null;
    }

    public function crear(array $datos): int
    {
        $stmt = $this->db->prepare(
            'INSERT INTO zonas (nombre, centro_lat, centro_lng, radio_km, tarifa_base, tarifa_por_km, recargo_hora_pico)
             VALUES (:nombre, :centro_lat, :centro_lng, :radio_km, :tarifa_base, :tarifa_por_km, :recargo_hora_pico)'
        );
        $stmt->execute($datos);

        return (int) $this->db->lastInsertId();
    }

    public function actualizar(int $id, array $datos): void
    {
        $datos['id'] = $id;
        $stmt = $this->db->prepare(
            'UPDATE zonas SET nombre = :nombre, centro_lat = :centro_lat, centro_lng = :centro_lng,
             radio_km = :radio_km, tarifa_base = :tarifa_base, tarifa_por_km = :tarifa_por_km,
             recargo_hora_pico = :recargo_hora_pico WHERE id = :id'
        );
        $stmt->execute($datos);
    }

    public function eliminar(int $id): void
    {
        $stmt = $this->db->prepare('DELETE FROM zonas WHERE id = :id');
        $stmt->execute(['id' => $id]);
    }
}
