<?php

namespace App\Core\Service;


use App;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Exception;
use App\Exceptions\ApiErrorException;
use App\Core\Repository\IpNation\IpNationRepository;
use GuzzleHttp\Client;

class FindCountryCodeService
{
    private $ipNationRepository;

    public function __construct(
        Client $restClient,
        IpNationRepository $ipNationRepository
    )
    {
        $this->restClient = $restClient;
        $this->ipNationRepository = $ipNationRepository;
    }

    public function findCountryWithIpAddress($ip)
    {

        $response = ['status' => false, 'message' => ''];

        $ipPoolCache = [];
        $ipPoolCacheKey = 'ipPoolCacheKey';

        if(Cache::has($ipPoolCacheKey)) {
            $ipPoolCache = Cache::get($ipPoolCacheKey);
        }

        if(isset($ipPoolCache[$ip])) {
            $response = [
                'status' => true,
                'data' => [
                    'code' => mb_strtolower($ipPoolCache[$ip]),
                    'source' => 'cache'
                ]
            ];

            return output($response);
        }

        try {

            $request = $this->restClient->get('http://ip-api.com/json/' . $ip, ['timeout' => 2]);

            $getResponseBody = $request->getBody();
            $getResponse = $getResponseBody->getContents();

            if (empty($getResponse)) {
                throw new ApiErrorException('Empty JSON response');
            }

            $getResponse = json_decode($getResponse, 1);

            if ($getResponse['status'] != 'success') {
                throw new ApiErrorException('Error');
            }

            if (isset($getResponse['message'])) {
                throw new ApiErrorException($getResponse['message']);
            }


            if(in_array($getResponse['countryCode'],['GB'])) {
                $getResponse['countryCode'] = 'UK';
            }

            $response = [
                'status' => true,
                'data' => [
                    'code' => mb_strtolower($getResponse['countryCode']),
                    'source' => 'ip-api.com'
                ]
            ];

        } catch (ApiErrorException $e) {

            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);

            $ip = ip2long($ip);

            $requestData = [
                'criteria' => [
                    ['field' => 'ip', 'condition' => '<', 'value' => $ip]
                ],
                'orderBy' => [["field" => "ip", "value" => "DESC"]],
                'with' => ['country'],
                'firstRow' => true
            ];

            $ipResult = $this->ipNationRepository->findByCriteria($requestData);

            $response = [
                'status' => true,
                'data' => !empty($ipResult['country']) ? $ipResult['country'] : []
            ];

        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        if($response['status'] && isset($response['data']['code']) && !empty($response['data']['code'])) {
            $ipPoolCache[$ip] = $response['data']['code'];
            Cache::put($ipPoolCacheKey, $ipPoolCache, 24 * 60 * 60);//10 Min, 60 * 10 = 600 TTL
        }

        return output($response);
    }

}
