<?php
namespace EasyChat\Library;

class EasyTokensGiftProvisioner {
    const DEFAULT_GATEWAY_API = 'https://api.easychat24.ru/api/v1';
    const CHALLENGE_TTL_SECONDS = 600;

    public static function provisionWithModel($model_setting, array $params) {
        $getter = function($key, $default = '') use ($model_setting) {
            return (string)$model_setting->get($key, $default);
        };
        $setter = function($key, $value) use ($model_setting) {
            $model_setting->set($key, (string)$value);
        };

        return self::provision($getter, $setter, $params);
    }

    public static function provisionWithMysqli($conn, $prefix, array $params) {
        $getter = function($key, $default = '') use ($conn, $prefix) {
            $stmt = $conn->prepare("SELECT `value` FROM `{$prefix}settings` WHERE `key` = ? LIMIT 1");
            if (!$stmt) {
                return (string)$default;
            }
            $stmt->bind_param('s', $key);
            if (!$stmt->execute()) {
                $stmt->close();
                return (string)$default;
            }
            $stmt->bind_result($value);
            $found = $stmt->fetch();
            $stmt->close();
            return $found ? (string)$value : (string)$default;
        };
        $setter = function($key, $value) use ($conn, $prefix) {
            $stmt = $conn->prepare("INSERT INTO `{$prefix}settings` (`key`, `value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `value` = ?");
            if (!$stmt) {
                return;
            }
            $value = (string)$value;
            $stmt->bind_param('sss', $key, $value, $value);
            $stmt->execute();
            $stmt->close();
        };

        return self::provision($getter, $setter, $params);
    }

    public static function challengeSignature($install_id, $domain, $nonce, $install_secret) {
        return base64_encode(hash_hmac('sha256', 'easychat-gift-challenge|' . $install_id . '|' . $domain . '|' . $nonce, $install_secret, true));
    }

    public static function publicDomain($site_url) {
        $parts = parse_url((string)$site_url);
        if (!$parts || empty($parts['host'])) {
            return '';
        }
        $host = strtolower((string)$parts['host']);
        $host = preg_replace('/:\d+$/', '', $host);
        return is_string($host) ? trim($host, '.') : '';
    }

    public static function defaultGatewayApi() {
        return self::DEFAULT_GATEWAY_API;
    }

    private static function provision($getter, $setter, array $params) {
        if (!self::truthy(self::param($params, 'claim_easytokens_gift', '1'))) {
            return array('success' => true, 'status' => 'not_requested', 'message' => 'Подарочные токены не запрашивались.');
        }

        $admin_email = strtolower(trim(self::param($params, 'admin_email', '')));
        if ($admin_email === '') {
            $admin_email = strtolower(trim($getter('chat_easytokens_gift_email', '')));
        }
        if ($admin_email === '') {
            $admin_email = strtolower(trim($getter('chat_widget_email', '')));
        }
        if (!filter_var($admin_email, FILTER_VALIDATE_EMAIL)) {
            $setter('chat_easytokens_gift_status', 'retryable');
            $setter('chat_easytokens_gift_error', 'email_required');
            return array('success' => false, 'status' => 'retryable', 'code' => 'email_required', 'message' => 'Укажите email для подарочных AI-токенов.');
        }
        $setter('chat_easytokens_gift_email', $admin_email);

        $install_id = trim($getter('chat_install_id', ''));
        if ($install_id === '') {
            $install_id = 'inst_' . bin2hex(random_bytes(16));
            $setter('chat_install_id', $install_id);
        }
        $install_secret = trim($getter('chat_install_secret', ''));
        if ($install_secret === '') {
            $install_secret = 'instsec_' . bin2hex(random_bytes(32));
            $setter('chat_install_secret', $install_secret);
        }

        $gateway = CentralGatewayClient::normalizeBaseUrl($getter('chat_central_api', ''));
        if ($gateway === '') {
            $gateway = self::DEFAULT_GATEWAY_API;
            $setter('chat_central_api', $gateway);
        }

        $site_url = self::siteUrl(self::param($params, 'site_url', defined('HTTP_SERVER') ? HTTP_SERVER : ''));
        $domain = self::publicDomain($site_url);
        if ($site_url === '' || $domain === '') {
            $setter('chat_easytokens_gift_status', 'retryable');
            $setter('chat_easytokens_gift_error', 'domain_invalid');
            return array('success' => false, 'status' => 'retryable', 'code' => 'domain_invalid', 'message' => 'Не удалось определить публичный домен установки.');
        }

        $challenge_nonce = bin2hex(random_bytes(16));
        $setter('chat_easytokens_gift_challenge_nonce', $challenge_nonce);
        $setter('chat_easytokens_gift_challenge_expires', (string)(time() + self::CHALLENGE_TTL_SECONDS));
        $setter('chat_easytokens_gift_status', 'pending');
        $setter('chat_easytokens_gift_error', '');

        $payload = array(
            'product' => 'easychat',
            'edition' => self::param($params, 'edition', 'standalone'),
            'version' => self::param($params, 'version', defined('EASYCHAT_VERSION') ? EASYCHAT_VERSION : '1.0.0'),
            'domain' => $domain,
            'site_url' => $site_url,
            'admin_email' => $admin_email,
            'challenge_url' => rtrim($site_url, '/') . '/index.php?route=provisioning/challenge',
            'challenge_nonce' => $challenge_nonce,
        );
        $body = CentralGatewayClient::signedUnlicensedBody($install_secret, $install_id, $payload);
        $registry = (isset($params['registry']) && is_object($params['registry'])) ? $params['registry'] : null;
        $response = CentralGatewayClient::postJson(
            $gateway,
            '/api/v1/installations/easytokens-gift',
            $body,
            12,
            $registry
        );

        if (!empty($response['error']) || empty($response['response'])) {
            $setter('chat_easytokens_gift_status', 'retryable');
            $setter('chat_easytokens_gift_error', 'gateway_unreachable');
            return array('success' => false, 'status' => 'retryable', 'code' => 'gateway_unreachable', 'message' => 'Gateway временно недоступен. Подарок можно запросить позже в настройках.');
        }

        $decoded = json_decode((string)$response['response'], true);
        if (!is_array($decoded)) {
            $setter('chat_easytokens_gift_status', 'retryable');
            $setter('chat_easytokens_gift_error', 'gateway_bad_response');
            return array('success' => false, 'status' => 'retryable', 'code' => 'gateway_bad_response', 'message' => 'Gateway вернул некорректный ответ.');
        }

        $status = isset($decoded['status']) ? (string)$decoded['status'] : 'retryable';
        $code = isset($decoded['code']) ? (string)$decoded['code'] : '';
        if (!empty($decoded['success']) && !empty($decoded['api_token'])) {
            $credential_scope = strtolower(self::param($params, 'credential_scope', 'primary'));
            if ($credential_scope === 'support') {
                 
                 
                $setter('chat_easytokens_support_key', (string)$decoded['api_token']);
            } else {
                $setter('chat_ai_provider', 'easytokens');
                $setter('chat_ai_model', 'easylite');
                $setter('chat_ai_key', (string)$decoded['api_token']);
            }
            $setter('chat_easytokens_gift_status', 'issued');
            $setter('chat_easytokens_gift_error', '');
            $setter('chat_easytokens_gift_issued_at', date('c'));
            $setter('chat_easytokens_gift_tokens', (string)(isset($decoded['tokens']) ? (int)$decoded['tokens'] : 30000));
            return array(
                'success' => true,
                'status' => 'issued',
                'api_token' => (string)$decoded['api_token'],
                'tokens' => isset($decoded['tokens']) ? (int)$decoded['tokens'] : 30000,
                'message' => 'Подарочные AI-токены начислены.',
            );
        }

        if (!in_array($status, array('pending', 'retryable', 'already_issued', 'rejected', 'pending_review'), true)) {
            $status = ((int)$response['status'] >= 500) ? 'retryable' : 'rejected';
        }
        $setter('chat_easytokens_gift_status', $status);
        $setter('chat_easytokens_gift_error', $code !== '' ? $code : 'gift_failed');

        return array(
            'success' => false,
            'status' => $status,
            'code' => $code !== '' ? $code : 'gift_failed',
            'message' => isset($decoded['message']) ? (string)$decoded['message'] : 'Подарочные токены пока не выданы.',
        );
    }

    private static function truthy($value) {
        return in_array(strtolower(trim((string)$value)), array('1', 'true', 'yes', 'on'), true);
    }

    private static function param(array $params, $key, $default = '') {
        return isset($params[$key]) ? trim((string)$params[$key]) : (string)$default;
    }

    private static function siteUrl($value) {
        $url = trim((string)$value);
        if ($url === '') {
            return '';
        }
        $parts = parse_url($url);
        if (!$parts || empty($parts['scheme']) || empty($parts['host'])) {
            return '';
        }
        $path = isset($parts['path']) ? rtrim((string)$parts['path'], '/') : '';
        $port = isset($parts['port']) ? ':' . (int)$parts['port'] : '';
        return strtolower((string)$parts['scheme']) . '://' . strtolower((string)$parts['host']) . $port . $path . '/';
    }
}
