<?php

namespace App\Services;

use App\Models\User;
use Illuminate\Support\Facades\Log;

class GeofencingService
{
    /**
     * Default work location coordinates (you can make this configurable)
     * These should be set to your actual office/work location
     */
    private static $workLocations = [
        [
            'name' => 'Main Office',
            'latitude' => 28.6139,  // Delhi, India coordinates - Update with actual office coordinates
            'longitude' => 77.2090, // Delhi, India coordinates - Update with actual office coordinates
            'radius' => 500, // meters - Increased radius for testing
        ],
        // Add more work locations as needed
        // [
        //     'name' => 'Branch Office',
        //     'latitude' => 19.0760,  // Mumbai coordinates
        //     'longitude' => 72.8777, // Mumbai coordinates
        //     'radius' => 300,
        // ],
    ];

    /**
     * Validate if the given coordinates are within acceptable work locations
     *
     * @param float $latitude
     * @param float $longitude
     * @param User|null $user
     * @return array
     */
    public static function validateLocation($latitude, $longitude, $user = null)
    {
        try {
            if (!$latitude || !$longitude) {
                return [
                    'valid' => false,
                    'reason' => 'Location coordinates not provided',
                    'distance' => null,
                    'nearest_location' => null
                ];
            }

            $nearestLocation = null;
            $shortestDistance = PHP_FLOAT_MAX;
            $isValid = false;

            foreach (self::$workLocations as $location) {
                $distance = self::calculateDistance(
                    $latitude, 
                    $longitude, 
                    $location['latitude'], 
                    $location['longitude']
                );

                if ($distance < $shortestDistance) {
                    $shortestDistance = $distance;
                    $nearestLocation = $location;
                }

                if ($distance <= $location['radius']) {
                    $isValid = true;
                }
            }

            return [
                'valid' => $isValid,
                'reason' => $isValid ? 'Within acceptable work location' : 'Outside acceptable work locations',
                'distance' => round($shortestDistance, 2),
                'nearest_location' => $nearestLocation,
                'all_distances' => self::getAllDistances($latitude, $longitude)
            ];

        } catch (\Exception $e) {
            Log::error('Geofencing validation error: ' . $e->getMessage());
            return [
                'valid' => false,
                'reason' => 'Error validating location',
                'distance' => null,
                'nearest_location' => null
            ];
        }
    }

    /**
     * Calculate distance between two coordinates using Haversine formula
     *
     * @param float $lat1
     * @param float $lon1
     * @param float $lat2
     * @param float $lon2
     * @return float Distance in meters
     */
    private static function calculateDistance($lat1, $lon1, $lat2, $lon2)
    {
        $earthRadius = 6371000; // Earth's radius in meters

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

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

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

        return $earthRadius * $c;
    }

    /**
     * Get distances to all work locations
     *
     * @param float $latitude
     * @param float $longitude
     * @return array
     */
    private static function getAllDistances($latitude, $longitude)
    {
        $distances = [];
        
        foreach (self::$workLocations as $location) {
            $distance = self::calculateDistance(
                $latitude, 
                $longitude, 
                $location['latitude'], 
                $location['longitude']
            );
            
            $distances[] = [
                'location' => $location['name'],
                'distance' => round($distance, 2),
                'within_range' => $distance <= $location['radius'],
                'radius' => $location['radius']
            ];
        }
        
        return $distances;
    }

    /**
     * Get work locations configuration
     *
     * @return array
     */
    public static function getWorkLocations()
    {
        return self::$workLocations;
    }

    /**
     * Add a new work location
     *
     * @param string $name
     * @param float $latitude
     * @param float $longitude
     * @param int $radius
     * @return void
     */
    public static function addWorkLocation($name, $latitude, $longitude, $radius = 100)
    {
        self::$workLocations[] = [
            'name' => $name,
            'latitude' => $latitude,
            'longitude' => $longitude,
            'radius' => $radius
        ];
    }

    /**
     * Check if location validation should be enforced for a user
     *
     * @param User|null $user
     * @return bool
     */
    public static function shouldEnforceValidation($user = null)
    {
        // Location validation is disabled - allow attendance from anywhere
        // Location data will still be captured and logged for admin viewing
        // This allows sales/marketing staff to mark attendance from client locations
        return false;
    }

    /**
     * Get a human-readable validation message
     *
     * @param array $validation
     * @return string
     */
    public static function getValidationMessage($validation)
    {
        if ($validation['valid']) {
            return "Location verified: You are within the acceptable work area.";
        }

        $message = "Location validation failed: You appear to be outside the acceptable work area.";
        
        if ($validation['nearest_location'] && $validation['distance']) {
            $message .= " You are {$validation['distance']}m away from {$validation['nearest_location']['name']}.";
        }

        return $message;
    }

    /**
     * Log location validation attempt
     *
     * @param array $validation
     * @param User|null $user
     * @param array $context
     * @return void
     */
    public static function logValidationAttempt($validation, $user = null, $context = [])
    {
        $logData = [
            'user_id' => $user ? $user->id : null,
            'user_name' => $user ? $user->name : 'Unknown',
            'validation_result' => $validation,
            'context' => $context,
            'timestamp' => now()->toISOString()
        ];

        if ($validation['valid']) {
            Log::info('Location validation successful', $logData);
        } else {
            Log::warning('Location validation failed', $logData);
        }
    }
}