<?php
/**
 * @package   Essentials YOOtheme Pro 2.2.16 build 0813.1608
 * @author    ZOOlanders https://www.zoolanders.com
 * @copyright Copyright (C) Joolanders, SL
 * @license   http://www.gnu.org/licenses/gpl.html GNU/GPL
 */

namespace ZOOlanders\YOOessentials\Condition\Rule\Geolocation;

use function YOOtheme\app;
use YOOtheme\Arr;
use ZOOlanders\YOOessentials\Condition\ConditionRule;
use ZOOlanders\YOOessentials\Api\MaxMind\GeoIp;
use ZOOlanders\YOOessentials\Util;

class GeolocationRule extends ConditionRule
{
    protected GeoIp $geoip;

    public function __construct(array $data)
    {
        $this->geoip = app(GeoIp::class);

        parent::__construct($data);
    }

    public function resolve($props, $node): bool
    {
        $continents = self::parseTextareaList($props->continents ?? '');
        $countries = self::parseTextareaList($props->countries ?? '');
        $cities = self::parseTextareaList($props->cities ?? '');
        $codes = self::parseTextareaList($props->codes ?? '');

        if (!$this->geoip->isReaderReady() || !array_filter(array_merge($countries, $continents, $cities, $codes))) {
            throw new \RuntimeException('Not Valid Evaluation Arguments');
        }

        $ip = Util\Ip::getIP();
        $result = [];

        if (($continents || $countries) && ($record = $this->geoip->getCountryRecord($ip))) {
            $continentData = $record->continent->jsonSerialize() ?? [];
            $continentData = array_filter([$continentData['code'] ?? null] + array_values($continentData['names'] ?? []));

            $countryData = $record->country->jsonSerialize() ?? [];
            $countryData = array_filter([$countryData['iso_code'] ?? null] + array_values($countryData['names'] ?? []));

            $result['continents'] = $this->resolveEntries($continents, $continentData);
            $result['countries'] = $this->resolveEntries($countries, $countryData);
        }

        if (($cities || $codes) && ($record = $this->geoip->getCityRecord($ip))) {
            $cityData = $record->city->jsonSerialize() ?? [];
            $cityData = array_filter([$cityData['name'] ?? null] + array_values($cityData['names'] ?? []));

            $codeData = [$record->postal->code];

            $result['cities'] = $this->resolveEntries($cities, $cityData);
            $result['codes'] = $this->resolveEntries($codes, $codeData);
        }

        return (bool) array_filter($result);
    }

    protected function resolveEntries(array $entries, array $data): bool
    {
        return Arr::some($entries, function ($entry) use ($data) {
            return in_array($entry, $data);
        });
    }
}
