<?php
namespace EasyChat\Library\Http;

use EasyChat\Model\Setting;

class ProxyPolicy {
    public const SETTING_ROUTES = 'chat_proxy_routes_json';

    private const PROFILE_GROUPS = [
        'ai' => [
            'label' => 'Нейросети',
            'description' => 'OpenAI-compatible провайдеры, Gemini и служебные запросы EasyTokens.',
        ],
        'messengers' => [
            'label' => 'Мессенджеры',
            'description' => 'API Telegram, MAX, ВКонтакте, Авито, Wildberries и Ozon для webhook, отправки и синхронизации.',
        ],
        'media' => [
            'label' => 'Вложения',
            'description' => 'Скачивание изображений и медиа из внешних каналов на сервер EasyChat.',
        ],
        'platform' => [
            'label' => 'Сервисы EasyChat',
            'description' => 'Центральный gateway для push, проверки домена и подарочных токенов.',
        ],
        'data' => [
            'label' => 'Данные и геосервисы',
            'description' => 'Внешние справочники и enrichment API, например DaData.',
        ],
        'delivery' => [
            'label' => 'Доставка',
            'description' => 'Проверка статусов отправлений через API подключённых перевозчиков.',
        ],
    ];

    private const PROFILES = [
        'ai_openai' => [
            'group' => 'ai',
            'label' => 'OpenAI API',
            'description' => 'ChatGPT/OpenAI-compatible host из настроек ИИ.',
        ],
        'ai_gemini' => [
            'group' => 'ai',
            'label' => 'Google Gemini API',
            'description' => 'Ответы ИИ и embeddings через Google Gemini.',
        ],
        'ai_easytokens' => [
            'group' => 'ai',
            'label' => 'EasyTokens',
            'description' => 'НашаНейросеть, баланс, модели, пополнение и AI-запросы EasyTokens.',
        ],
        'messenger_telegram' => [
            'group' => 'messengers',
            'label' => 'Telegram',
            'description' => 'getMe, setWebhook, входящие и исходящие сообщения Telegram.',
        ],
        'messenger_max' => [
            'group' => 'messengers',
            'label' => 'MAX',
            'description' => 'Проверка бота, webhook и сообщения MAX.',
        ],
        'messenger_vk' => [
            'group' => 'messengers',
            'label' => 'ВКонтакте',
            'description' => 'Callback API, настройки сообщества и отправка сообщений VK.',
        ],
        'messenger_avito' => [
            'group' => 'messengers',
            'label' => 'Авито',
            'description' => 'OAuth, webhook и Messenger API Авито.',
        ],
        'messenger_youla' => [
            'group' => 'messengers',
            'label' => 'Юла',
            'description' => 'Partner API, сообщения и карточки товаров Юлы.',
        ],
        'messenger_wildberries' => [
            'group' => 'messengers',
            'label' => 'Wildberries',
            'description' => 'Чаты, вопросы, отзывы и возвраты продавца Wildberries.',
        ],
        'messenger_ozon' => [
            'group' => 'messengers',
            'label' => 'Ozon',
            'description' => 'Чаты, вопросы, отзывы, возвраты и push-настройки Ozon Seller.',
        ],
        'messenger_attachments' => [
            'group' => 'media',
            'label' => 'Вложения мессенджеров',
            'description' => 'Скачивание изображений из Telegram, MAX, VK и Авито.',
        ],
        'easychat_gateway' => [
            'group' => 'platform',
            'label' => 'EasyChat Gateway',
            'description' => 'FCM/WebPush gateway, проверка домена и trial-сервисы.',
        ],
        'dadata' => [
            'group' => 'data',
            'label' => 'DaData',
            'description' => 'Определение города посетителя по IP для операторской консоли.',
        ],
        'delivery_yandex' => [
            'group' => 'delivery',
            'label' => 'Яндекс Доставка',
            'description' => 'Получение статуса заявки Яндекс Доставки без изменения отправления.',
        ],
        'delivery_apiship' => [
            'group' => 'delivery',
            'label' => 'ApiShip',
            'description' => 'Получение статуса заказа ApiShip без изменения отправления.',
        ],
    ];

    private const TRUST_PROFILE_MAP = [
        'telegram' => 'messenger_telegram',
        'max' => 'messenger_max',
        'vk' => 'messenger_vk',
        'avito' => 'messenger_avito',
        'youla' => 'messenger_youla',
        'wildberries' => 'messenger_wildberries',
        'ozon' => 'messenger_ozon',
        'easytokens' => 'ai_easytokens',
        'openai' => 'ai_openai',
        'gemini' => 'ai_gemini',
        'easychat_gateway' => 'easychat_gateway',
        'dadata' => 'dadata',
        'yandex_delivery' => 'delivery_yandex',
        'apiship_tracking' => 'delivery_apiship',
    ];

     
    private $settings;

    public function __construct($source = []) {
        if ($source instanceof Setting) {
            $this->settings = $source->getAll();
        } elseif (is_object($source) && method_exists($source, 'get')) {
            $model_setting = new Setting($source);
            $this->settings = $model_setting->getAll();
        } elseif (is_array($source)) {
            $this->settings = $source;
        } else {
            $this->settings = [];
        }
    }

    public static function groups(): array {
        return self::PROFILE_GROUPS;
    }

    public static function profiles(): array {
        return self::PROFILES;
    }

    public static function defaultRoutes($enabled = true): array {
        $routes = [];
        foreach (self::PROFILES as $profile => $_meta) {
            $routes[$profile] = (bool)$enabled;
        }
        return $routes;
    }

    public static function normalizeProfile($profile): string {
        $profile = strtolower(trim((string)$profile));
        if (isset(self::PROFILES[$profile])) {
            return $profile;
        }
        return self::profileForTrustProfile($profile);
    }

    public static function profileForTrustProfile($trust_profile): string {
        $trust_profile = strtolower(trim((string)$trust_profile));
        return self::TRUST_PROFILE_MAP[$trust_profile] ?? '';
    }

    public static function normalizeRoutes($raw, $default_enabled = true): array {
        if (is_string($raw)) {
            $raw = trim($raw);
            if ($raw === '') {
                return self::defaultRoutes($default_enabled);
            }
            $decoded = json_decode($raw, true);
            $raw = is_array($decoded) ? $decoded : [];
        }

        if (!is_array($raw) || empty($raw)) {
            return self::defaultRoutes($default_enabled);
        }

        $routes = self::defaultRoutes(false);
        foreach (self::PROFILES as $profile => $_meta) {
            if (array_key_exists($profile, $raw)) {
                $routes[$profile] = self::truthy($raw[$profile]);
            }
        }
        return $routes;
    }

    public static function routesToJson(array $routes): string {
        return json_encode(self::normalizeRoutes($routes, false), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    }

    public function routes(): array {
        return self::normalizeRoutes($this->settings[self::SETTING_ROUTES] ?? '', true);
    }

    public function proxyForProfile($profile): ?array {
        $profile = self::normalizeProfile($profile);
        if ($profile === '' || !$this->masterEnabled()) {
            return null;
        }

        $routes = $this->routes();
        if (empty($routes[$profile])) {
            return null;
        }

        $proxy = $this->proxyConfig();
        return $proxy !== [] ? $proxy : null;
    }

    public function routeState($profile): array {
        $profile = self::normalizeProfile($profile);
        $routes = $this->routes();
        $selected = $profile !== '' && !empty($routes[$profile]);
        $master = $this->masterEnabled();
        $configured = $this->proxyConfig() !== [];

        if (!$selected) {
            $code = 'direct';
            $label = 'Напрямую';
            $class = 'bg-light text-secondary border';
            $icon = 'fa-random';
        } elseif (!$master) {
            $code = 'proxy_off';
            $label = 'Proxy выключен';
            $class = 'bg-light text-secondary border';
            $icon = 'fa-power-off';
        } elseif (!$configured) {
            $code = 'proxy_missing';
            $label = 'Нужен host/port';
            $class = 'bg-warning-subtle text-warning border border-warning-subtle';
            $icon = 'fa-exclamation-triangle';
        } else {
            $code = 'proxy';
            $label = 'Через proxy';
            $class = 'bg-success-subtle text-success border border-success-subtle';
            $icon = 'fa-shield';
        }

        return [
            'profile' => $profile,
            'selected' => $selected,
            'master_enabled' => $master,
            'proxy_configured' => $configured,
            'code' => $code,
            'label' => $label,
            'class' => $class,
            'icon' => $icon,
        ];
    }

    public function routeStates(): array {
        $states = [];
        foreach (self::PROFILES as $profile => $_meta) {
            $states[$profile] = $this->routeState($profile);
        }
        return $states;
    }

    public function masterEnabled(): bool {
        return (string)($this->settings['chat_proxy_status'] ?? '0') === '1';
    }

    private function proxyConfig(): array {
        $host = trim((string)($this->settings['chat_proxy_host'] ?? ''));
        $port = (int)($this->settings['chat_proxy_port'] ?? 0);
        if ($host === '' || $port < 1 || $port > 65535) {
            return [];
        }

        return [
            'ip' => $host,
            'port' => (string)$port,
            'login' => (string)($this->settings['chat_proxy_login'] ?? ''),
            'password' => (string)($this->settings['chat_proxy_password'] ?? ''),
        ];
    }

    private static function truthy($value): bool {
        if (is_bool($value)) {
            return $value;
        }
        if (is_int($value) || is_float($value)) {
            return (int)$value === 1;
        }
        $value = strtolower(trim((string)$value));
        return in_array($value, ['1', 'true', 'yes', 'on'], true);
    }
}
