<?php

namespace App\Http\Controllers;

use App\Models\Visit;
use App\Models\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;

class GPSTrackerController extends Controller
{
    public function trackVisit(Visit $visit)
    {
        $this->authorize('view', $visit);
        
        $visit->load(['client', 'employee']);
        
        return view('visits.gps-tracker', compact('visit'));
    }

    public function updateLocation(Request $request, Visit $visit)
    {
        $this->authorize('update', $visit);
        
        $request->validate([
            'latitude' => 'required|numeric|between:-90,90',
            'longitude' => 'required|numeric|between:-180,180',
            'accuracy' => 'nullable|numeric',
            'altitude' => 'nullable|numeric',
            'speed' => 'nullable|numeric',
            'heading' => 'nullable|numeric|between:0,360',
        ]);

        // Store location history
        $locationData = [
            'latitude' => $request->latitude,
            'longitude' => $request->longitude,
            'accuracy' => $request->accuracy,
            'altitude' => $request->altitude,
            'speed' => $request->speed,
            'heading' => $request->heading,
            'timestamp' => now(),
        ];

        $locationHistory = $visit->location_history ?? [];
        $locationHistory[] = $locationData;
        
        // Keep only last 100 locations
        if (count($locationHistory) > 100) {
            $locationHistory = array_slice($locationHistory, -100);
        }

        $visit->update([
            'location_history' => $locationHistory,
            'last_location_update' => now(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Location updated',
            'location' => $locationData,
        ]);
    }

    public function getVisitLocation(Visit $visit)
    {
        $this->authorize('view', $visit);
        
        $lastLocation = null;
        if ($visit->location_history && count($visit->location_history) > 0) {
            $lastLocation = end($visit->location_history);
        }

        return response()->json([
            'visit' => [
                'id' => $visit->id,
                'status' => $visit->status,
                'started_at' => $visit->started_at,
                'completed_at' => $visit->completed_at,
                'client_location' => [
                    'latitude' => $visit->latitude,
                    'longitude' => $visit->longitude,
                    'address' => $visit->client->address,
                ],
            ],
            'current_location' => $lastLocation,
            'location_history' => $visit->location_history ?? [],
        ]);
    }

    public function getRouteHistory(Visit $visit)
    {
        $this->authorize('view', $visit);
        
        $locations = $visit->location_history ?? [];
        
        // Calculate distance to client
        $distance = null;
        if (!empty($locations)) {
            $lastLocation = end($locations);
            $distance = $this->calculateDistance(
                $lastLocation['latitude'],
                $lastLocation['longitude'],
                $visit->latitude,
                $visit->longitude
            );
        }

        return response()->json([
            'route' => $locations,
            'client_location' => [
                'latitude' => $visit->latitude,
                'longitude' => $visit->longitude,
                'name' => $visit->client->name,
            ],
            'distance_to_client' => $distance,
            'visit_status' => $visit->status,
        ]);
    }

    public function calculateProximity(Request $request, Visit $visit)
    {
        $this->authorize('update', $visit);
        
        $request->validate([
            'latitude' => 'required|numeric',
            'longitude' => 'required|numeric',
        ]);

        $distance = $this->calculateDistance(
            $request->latitude,
            $request->longitude,
            $visit->latitude,
            $visit->longitude
        );

        $isWithinRange = $distance <= 0.1; // 100 meters range

        return response()->json([
            'distance' => round($distance * 1000, 2), // Convert to meters
            'is_within_range' => $isWithinRange,
            'range_limit' => 100, // meters
            'client_name' => $visit->client->name,
        ]);
    }

    public function autoCompleteVisit(Request $request, Visit $visit)
    {
        $this->authorize('update', $visit);
        
        $request->validate([
            'latitude' => 'required|numeric',
            'longitude' => 'required|numeric',
            'notes' => 'nullable|string',
        ]);

        $distance = $this->calculateDistance(
            $request->latitude,
            $request->longitude,
            $visit->latitude,
            $visit->longitude
        );

        // Auto-complete if within 50 meters
        if ($distance <= 0.05 && $visit->status == 'in_progress') {
            $visit->update([
                'status' => 'completed',
                'completed_at' => now(),
                'employee_notes' => $request->notes . " (Auto-completed within " . round($distance * 1000) . "m)",
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Visit auto-completed successfully',
                'distance' => round($distance * 1000, 2),
            ]);
        }

        return response()->json([
            'success' => false,
            'message' => 'Not close enough to auto-complete',
            'distance' => round($distance * 1000, 2),
            'required_distance' => 50,
        ]);
    }

    public function activeVisitsMap()
    {
        $user = Auth::user();
        
        if ($user->hasRole('admin')) {
            $visits = Visit::where('status', 'in_progress')
                ->with(['employee', 'client'])
                ->get();
        } elseif ($user->hasRole('supervisor')) {
            $employeeIds = $user->subordinates()->pluck('id');
            $visits = Visit::where('status', 'in_progress')
                ->whereIn('employee_id', $employeeIds)
                ->with(['employee', 'client'])
                ->get();
        } else {
            $visits = Visit::where('status', 'in_progress')
                ->where('employee_id', $user->id)
                ->with(['client'])
                ->get();
        }

        return view('visits.active-map', compact('visits'));
    }

    public function getActiveVisits()
    {
        $user = Auth::user();
        
        if ($user->hasRole('admin')) {
            $visits = Visit::where('status', 'in_progress')
                ->with(['employee', 'client'])
                ->get();
        } elseif ($user->hasRole('supervisor')) {
            $employeeIds = $user->subordinates()->pluck('id');
            $visits = Visit::where('status', 'in_progress')
                ->whereIn('employee_id', $employeeIds)
                ->with(['employee', 'client'])
                ->get();
        } else {
            $visits = Visit::where('status', 'in_progress')
                ->where('employee_id', $user->id)
                ->with(['client'])
                ->get();
        }

        $visitsData = $visits->map(function($visit) {
            $lastLocation = null;
            if ($visit->location_history && count($visit->location_history) > 0) {
                $lastLocation = end($visit->location_history);
            }

            return [
                'id' => $visit->id,
                'client_name' => $visit->client->name,
                'employee_name' => $visit->employee->name,
                'started_at' => $visit->started_at->format('H:i'),
                'client_location' => [
                    'latitude' => $visit->latitude,
                    'longitude' => $visit->longitude,
                ],
                'current_location' => $lastLocation,
                'status' => $visit->status,
            ];
        });

        return response()->json($visitsData);
    }

    private function calculateDistance($lat1, $lon1, $lat2, $lon2)
    {
        $earthRadius = 6371; // kilometers

        $lat1 = deg2rad($lat1);
        $lon1 = deg2rad($lon1);
        $lat2 = deg2rad($lat2);
        $lon2 = deg2rad($lon2);

        $latDelta = $lat2 - $lat1;
        $lonDelta = $lon2 - $lon1;

        $angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
            cos($lat1) * cos($lat2) * pow(sin($lonDelta / 2), 2)));

        return $angle * $earthRadius;
    }
}