<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\User;
use App\Models\Post;
use App\Models\Aderente;
use App\Services\ParagemService;
use Illuminate\Support\Facades\Auth;
use App\Events\PosicaoAtualizada;
use App\Events\ParagemProxima;
use App\Events\UserUpdated;

class GpsController extends Controller
{
    public function atualizarLocalizacao(Request $request, $postId)
    {
        $request->validate([
            'latitude' => 'required|numeric',
            'longitude' => 'required|numeric',
            'typeUser' => 'required|in:motorista,cliente',
        ]);

        $user = Auth::user();
        $typeUser = $request->input('typeUser');
        $latitude = $request->input('latitude');
        $longitude = $request->input('longitude');

        // 🔐 Atualiza token Firebase se necessário
        if ($request->filled('firebase_token') && $request->firebase_token !== $user->firebase_token) {
            $user->firebase_token = $request->firebase_token;
            $user->save();
            event(new UserUpdated($user));
        }

        // 📡 Verifica movimento relevante (>30m)
        if ($this->hasMovedSignificantly($user->latitude, $user->longitude, $latitude, $longitude)) {
            broadcast(new PosicaoAtualizada(
                $latitude,
                $longitude,
                $user->id,
                $typeUser
            ))->toOthers();
        }

        // 📍 Atualiza posição com granularidade semântica
        $user->latitude = $latitude;
        $user->longitude = $longitude;
        $user->save();

        // 🚐 Se for motorista, verifica paragens próximas
        if ($typeUser === 'motorista') {
            $post = Post::with('user')->findOrFail($postId);

            if ($user->id !== $post->user_id) {
                return response()->json([
                    'success' => false,
                    'message' => 'Não tens permissão para atualizar esta boleya.'
                ], 403);
            }

            $aderentes = Aderente::where('post_id', $post->id)
               ->where('status', Aderente::STATUS_ACEITO)
                ->get();

            $raioKm = 0.2;
            $service = new ParagemService();
            $notificouMotorista = false;

            foreach ($aderentes as $aderente) {
                $distancia = $service->haversine(
                    $latitude,
                    $longitude,
                    $aderente->paragem_lat,
                    $aderente->paragem_long
                );

                if ($distancia <= $raioKm) {
                    if (!$aderente->notificado_aderente) {
                        broadcast(new ParagemProxima($post->id, [
                            'paragem_lat' => $aderente->paragem_lat,
                            'paragem_long' => $aderente->paragem_long,
                            'cliente_id' => $aderente->cliente_id,
                        ], 'user'))->toOthers();

                        $aderente->update(['notificado_aderente' => true]);
                    }

                    if (!$user->notificado_motorista && !$notificouMotorista) {
                        broadcast(new ParagemProxima($post->id, [
                            'paragem_lat' => $aderente->paragem_lat,
                            'paragem_long' => $aderente->paragem_long,
                            'cliente_id' => $aderente->cliente_id,
                        ], 'drive'))->toOthers();

                        $user->update(['notificado_motorista' => true]);
                        $notificouMotorista = true;
                    }
                }
            }
        }

        return response()->json([
            'success' => true,
            'message' => 'Localização atualizada com sucesso.'
        ]);
    }

    private function hasMovedSignificantly(float $lat1, float $lng1, float $lat2, float $lng2): bool
    {
        return $this->haversine($lat1, $lng1, $lat2, $lng2) > 0.03; // ~30 metros
    }

    private function haversine(float $lat1, float $lon1, float $lat2, float $lon2): float
    {
        $earthRadius = 6371; // km

        $dLat = deg2rad($lat2 - $lat1);
        $dLon = deg2rad($lon2 - $lon1);

        $a = sin($dLat / 2) ** 2 +
             cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
             sin($dLon / 2) ** 2;

        $c = 2 * atan2(sqrt($a), sqrt(1 - $a));

        return $earthRadius * $c;
    }
}
