<?php

declare(strict_types=1);

namespace App\Services;

use App\Repositories\PedidoTrackingRepository;
use Pusher\Pusher;

/**
 * Persiste la ubicación GPS del repartidor y la emite en tiempo real
 * al canal del pedido vía Soketi (protocolo compatible Pusher).
 */
class TrackingService
{
    private Pusher $pusher;
    private PedidoTrackingRepository $repository;

    public function __construct(PedidoTrackingRepository $repository, ?Pusher $pusher = null)
    {
        $this->repository = $repository;
        $this->pusher = $pusher ?? new Pusher(
            $_ENV['SOKETI_APP_KEY'] ?? '',
            $_ENV['SOKETI_APP_SECRET'] ?? '',
            $_ENV['SOKETI_APP_ID'] ?? '',
            [
                'host' => $_ENV['SOKETI_HOST'] ?? '127.0.0.1',
                'port' => (int) ($_ENV['SOKETI_PORT'] ?? 6001),
                'scheme' => $_ENV['SOKETI_SCHEME'] ?? 'http',
                'useTLS' => ($_ENV['SOKETI_SCHEME'] ?? 'http') === 'https',
            ]
        );
    }

    public function registrarUbicacion(int $pedidoId, int $repartidorId, float $lat, float $lng, ?float $rumbo = null, ?float $velocidad = null): void
    {
        $this->repository->guardar($pedidoId, $repartidorId, $lat, $lng, $rumbo, $velocidad);

        $this->emitir("pedido.{$pedidoId}", 'ubicacion.actualizada', [
            'pedido_id' => $pedidoId,
            'repartidor_id' => $repartidorId,
            'lat' => $lat,
            'lng' => $lng,
            'rumbo' => $rumbo,
            'velocidad' => $velocidad,
            'timestamp' => time(),
        ]);
    }

    public function emitirCambioEstado(int $pedidoId, string $estadoAnterior, string $estadoNuevo): void
    {
        $this->emitir("pedido.{$pedidoId}", 'estado.cambiado', [
            'pedido_id' => $pedidoId,
            'estado_anterior' => $estadoAnterior,
            'estado_nuevo' => $estadoNuevo,
            'timestamp' => time(),
        ]);
    }

    /**
     * Soketi es un canal de notificación en tiempo real, no la fuente de verdad
     * (esa es MySQL). Si está caído o inalcanzable, no debe tumbar el flujo del pedido.
     */
    private function emitir(string $canal, string $evento, array $payload): void
    {
        try {
            $this->pusher->trigger($canal, $evento, $payload);
        } catch (\Throwable $e) {
            error_log("TrackingService: fallo al emitir evento '{$evento}' en '{$canal}': " . $e->getMessage());
        }
    }
}
