<?php

namespace App\Util;
use App\Util\Helper;
use App\Helpers\{ArrayHelper};
use GuzzleHttp\Client;

class Locate
{
    public static function isValidLatitude($latitude)
    {
        $latitude = (float) $latitude;
        return is_numeric($latitude) && $latitude >= -90 && $latitude <= 90;
    }

    public static function isValidLongitude($longitude)
    {
        $longitude = (float) $longitude;
        return is_numeric($longitude) && $longitude >= -180 && $longitude <= 180;
    }

    // check if latitude and longitude is valid values
    public static function isValidLatLong($latitude, $longitude)
    {
        $latitude = (float) $latitude;
        $longitude = (float) $longitude;

        if (!empty($latitude) && !empty($longitude) && $latitude >= -90 && $latitude <= 90 && $longitude >= -180 && $longitude <= 180) {
            return true; // Valid latitude and longitude values.
        }

        return false; // Invalid latitude and longitude values.
    }

    public static function getCountry(string $countryCode, string $fetchBy = 'countryCode')
    {
        $data = file_get_contents(APPROOT . '/Helpers/data/countries.json');
        if (!$data) {
            return [];
        }
        $countryArray = json_decode($data, true);
        $countryData = $countryArray['countries']['country'];
        $result = ArrayHelper::findKeyValue($countryData, $fetchBy, $countryCode);
        return $result;
    }

    /**
     * Retrieves the user's IP address from the server variables.
     *
     * @return string The user's IP address.
     */
    public static function getUserIP()
    {
        $ip = '';

        if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } elseif (!empty($_SERVER['HTTP_X_FORWARDED'])) {
            $ip = $_SERVER['HTTP_X_FORWARDED'];
        } elseif (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP'])) {
            $ip = $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
        } elseif (!empty($_SERVER['HTTP_FORWARDED_FOR'])) {
            $ip = $_SERVER['HTTP_FORWARDED_FOR'];
        } elseif (!empty($_SERVER['HTTP_FORWARDED'])) {
            $ip = $_SERVER['HTTP_FORWARDED'];
        } elseif (!empty($_SERVER['REMOTE_ADDR'])) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }

        return $ip;
    }

    public static function getUserTimezone()
    {

        // If not, try to detect the timezone using the server's settings
        $timezone = date_default_timezone_get();

        // If the timezone is still not set, try to detect it using the user's IP address
        if (!$timezone) {
            $ip = $_SERVER['REMOTE_ADDR'];
            $json = file_get_contents('http://smart-ip.net/geoip-json/' . $ip);
            $ipData = json_decode($json, true);
            $timezone = $ipData['timezone'];
        }

        return $timezone;
    }

    public static function getUserDataByIP(?string $ip_address = '')
    {
        // API endpoint
        $client = new Client;
        $response = $client->request("GET", "http://ip-api.com/json/{$ip_address}");
        $responseArray = json_decode($response->getBody(), true);
        return $responseArray;
    }

    public static function calculateDistance($lat1, $lon1, $lat2, $lon2, $unit)
    {
        $lat1 = (float) $lat1;
        $lon1 = (float) $lon1;
        $lat2 = (float) $lat2;
        $lon2 = (float) $lon2;

        $theta = $lon1 - $lon2;
        $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
        $dist = acos($dist);
        $dist = rad2deg($dist);
        $miles = $dist * 60 * 1.1515;
        $unit = strtoupper($unit);

        switch ($unit) {
            case "K":
                return round($miles * 1.609344, 2);
            case "N":
                return round($miles * 0.8684, 2);
            default:
                return round($miles, 2);
        }
    }

    public static function haversineGreatCircleDistance($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000)
    {
        // convert from degrees to radians
        $latFrom = deg2rad($latitudeFrom);
        $lonFrom = deg2rad($longitudeFrom);
        $latTo = deg2rad($latitudeTo);
        $lonTo = deg2rad($longitudeTo);

        $latDelta = $latTo - $latFrom;
        $lonDelta = $lonTo - $lonFrom;

        $angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
            cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
        return $angle * $earthRadius;
    }

    public static function getTimezoneWithLatLong($latitudeTo, $longitudeTo, $earthRadius = 6371000, $threshold = 100000)
    {
        $timezones = timezone_identifiers_list();
        $getUserTimeZone = '';

        foreach ($timezones as $timezone) {
            $location = timezone_location_get(new \DateTimeZone($timezone));

            // convert from degrees to radians
            $latFrom = deg2rad($location['latitude']);
            $lonFrom = deg2rad($location['longitude']);

            $latTo = deg2rad($latitudeTo);
            $lonTo = deg2rad($longitudeTo);

            $latDelta = $latTo - $latFrom;
            $lonDelta = $lonTo - $lonFrom;

            $angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
                cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
            $distance = $angle * $earthRadius;

            if ($distance <= $threshold) {
                $getUserTimeZone = $timezone;
                // break;
            }
        }

        return $getUserTimeZone;
    }

    function getUserTimezoneByLatLong($latitude, $longitude)
    {
        $googleMapsKey = $_ENV['GOOGLE_MAPS_WEB_KEY'];
        $timestamp = time();
        $url = "https://maps.googleapis.com/maps/api/timezone/json?location={$latitude},{$longitude}&timestamp=$timestamp&key={$googleMapsKey}";

        $json = file_get_contents($url);
        $data = json_decode($json, true);
        $timezoneId = $data['timeZoneId'];
        $timezoneName = $data['timeZoneName'];
        return ['timezone' => $timezoneId, 'timezoneName' => $timezoneName];
    }
}
