<?php

namespace HaoZiTeam\AIPost\Service\Settings\Traits;

use HaoZiTeam\AIPost\Service\Features\Logger;

defined('ABSPATH') || exit;

trait TraitLicense
{
    private function normalize_host(string $host): string
    {
        $host = strtolower(trim($host));
        $host = preg_replace('/^www\./', '', $host);
        return (string)$host;
    }

    /**
     * 运行时组装授权端地址（混淆存储，防止简单搜索替换绕过授权）
     * @param string $path 追加路径，例如 'getAuthInfo/'
     * @return string 完整 URL
     */
    private function _auth_base(string $path = ''): string
    {
        $scheme = base64_decode('aHR0cHM6Ly8=');
        $host   = implode('', array_map('chr', [97,112,105,46]))
                . implode('', array_map('chr', [115,117,113,105,97,110,119,101,98]))
                . base64_decode('LmNu');
        $base   = base64_decode('L3Byb2QtYXBpL3BsdWdpbi9hdXRoLw==');
        return $scheme . $host . $base . $path;
    }

    private function verify_license_binding(string $cardNum, string $cardPwd): array
    {
        $cardNum = trim($cardNum);
        $cardPwd = trim($cardPwd);
        if ($cardNum === '' || $cardPwd === '') {
            return ['ok' => false, 'message' => '请先填写卡号与卡密'];
        }

        $hostname = isset($_SERVER['SERVER_NAME']) ? trim((string)$_SERVER['SERVER_NAME']) : '';
        if ($hostname === '') {
            $h = parse_url((string)get_option('home'), PHP_URL_HOST);
            $hostname = is_string($h) ? trim($h) : '';
        }
        if ($hostname === '') {
            $hostname = 'localhost';
        }
        $serverIp = @gethostbyname($hostname);
        if (!is_string($serverIp) || $serverIp === '') {
            $serverIp = '127.0.0.1';
        }

        $url = $this->_auth_base() . rawurlencode($cardNum) . '/' . rawurlencode($cardPwd);

        $res = \wp_remote_get($url, [
            'timeout' => 12,
            'redirection' => 2,
            'sslverify' => true,
            'headers' => [
                'X-Forwarded-For' => $serverIp,
                'Host-Name' => $hostname,
            ],
        ]);
        if (\is_wp_error($res)) {
            return ['ok' => false, 'message' => '绑定校验请求失败：' . $res->get_error_message()];
        }

        $code = (int) \wp_remote_retrieve_response_code($res);
        $body = (string) \wp_remote_retrieve_body($res);
        $json = json_decode($body, true);
        if (!is_array($json)) {
            return ['ok' => false, 'message' => '绑定校验响应解析失败（HTTP ' . $code . '）'];
        }
        $apiCode = isset($json['code']) ? (int)$json['code'] : 0;
        $msg = isset($json['msg']) ? (string)$json['msg'] : '';
        if ($apiCode === 500) {
            if ($msg === '') { $msg = '设备认证失败：该卡密已被其他站点绑定或校验不通过'; }
            return ['ok' => false, 'message' => $msg];
        }
        if ($apiCode !== 200) {
            if ($msg === '') { $msg = '绑定校验失败'; }
            return ['ok' => false, 'message' => $msg];
        }
        return ['ok' => true, 'message' => $msg];
    }

    private function extract_bound_host(array $data): string
    {
        $raw = $this->pick_first_string($data, [
            'bindDomain', 'bindHost', 'bindUrl', 'bindSite', 'bindWebsite',
            'domain', 'host', 'site', 'siteUrl', 'website', 'url',
            'authDomain', 'authHost', 'authUrl', 'authSite',
        ]);
        $raw = trim($raw);
        if ($raw === '') { return ''; }
        if (strpos($raw, '://') !== false) {
            $u = @parse_url($raw);
            if (is_array($u) && !empty($u['host'])) {
                return (string)$u['host'];
            }
        }
        $raw = preg_replace('/^https?:\/\//i', '', $raw);
        $raw = preg_replace('/\/.*$/', '', $raw);
        return (string)$raw;
    }

    private function get_license_info(array $opts): array
    {
        $cardNum = isset($opts['cardNum']) ? trim((string)$opts['cardNum']) : '';
        $cardPwd = isset($opts['cardPwd']) ? trim((string)$opts['cardPwd']) : '';
        if ($cardNum === '' || $cardPwd === '') {
            return ['ok' => false, 'message' => '请先填写卡号与卡密', 'data' => null];
        }

        $url = $this->_auth_base('getAuthInfo/') . rawurlencode($cardNum) . '/' . rawurlencode($cardPwd);

        $res = \wp_remote_get($url, [
            'timeout' => 12,
            'redirection' => 2,
            'sslverify' => true,
        ]);

        if (\is_wp_error($res)) {
            return ['ok' => false, 'message' => '请求失败：' . $res->get_error_message(), 'data' => null];
        }

        $code = (int) \wp_remote_retrieve_response_code($res);
        $body = (string) \wp_remote_retrieve_body($res);
        $json = json_decode($body, true);
        if (!is_array($json) || !$this->_validate_auth_response($json)) {
            return ['ok' => false, 'message' => '响应解析失败（HTTP ' . $code . '）', 'data' => null];
        }

        $apiCode = isset($json['code']) ? (int)$json['code'] : 0;
        $msg = isset($json['msg']) ? (string)$json['msg'] : '';
        $data = (isset($json['data']) && is_array($json['data'])) ? $json['data'] : null;

        if ($apiCode === 500) {
            return ['ok' => false, 'message' => ($msg !== '' ? $msg : '校验失败'), 'data' => $data];
        }

        if ($apiCode !== 200 || !is_array($data)) {
            return ['ok' => false, 'message' => ($msg !== '' ? $msg : '校验失败'), 'data' => $data];
        }

        $category = $this->pick_first_string($data, ['category', 'cardType', 'type']);
        if ($category === '') {
            $reason = '授权信息异常：未返回卡密类型';
            $plainMsg = trim((string)$msg);
            if ($plainMsg !== '' && !preg_match('/^操作成功$/u', $plainMsg)) {
                $reason = $plainMsg;
            }
            return ['ok' => false, 'message' => $reason, 'data' => $data];
        }

        $createTimeRaw = $this->pick_first_string($data, ['createTime', 'startTime', 'activeTime', 'activationTime', 'beginTime']);
        $endTimeRaw = $this->pick_first_string($data, ['endTime', 'expireTime', 'expirationTime', 'expiryTime', 'dueTime']);
        $createTime = $this->normalize_time_string($createTimeRaw);
        $endTime = $this->normalize_time_string($endTimeRaw);
        $createTs = $createTime !== '' ? strtotime($createTime) : false;
        $endTs = $endTime !== '' ? strtotime($endTime) : false;

        // 未激活卡密：允许通过
        if ($createTs === false || $endTs === false || $endTs <= 0) {
            $data['__aipost_status'] = 'unactivated';
            return ['ok' => true, 'message' => $msg, 'data' => $data];
        }

        $data['__aipost_status'] = 'activated';
        return ['ok' => true, 'message' => $msg, 'data' => $data];
    }

    private function pick_first_string(array $arr, array $keys): string
    {
        foreach ($keys as $k) {
            if (isset($arr[$k]) && $arr[$k] !== null && $arr[$k] !== '') {
                return (string)$arr[$k];
            }
        }
        return '';
    }

    private function normalize_time_string(string $raw): string
    {
        $raw = trim($raw);
        if ($raw === '') { return ''; }
        if (preg_match('/^\d+$/', $raw)) {
            $n = (int)$raw;
            if ($n > 1000000000000) {
                $n = (int)floor($n / 1000);
            }
            if ($n > 0) {
                $fmt = function_exists('wp_date') ? wp_date('Y-m-d H:i:s', $n) : date('Y-m-d H:i:s', $n);
                return (string)$fmt;
            }
        }

        $ts = strtotime($raw);
        if ($ts !== false) {
            $fmt = function_exists('wp_date') ? wp_date('Y-m-d H:i:s', $ts) : date('Y-m-d H:i:s', $ts);
            return (string)$fmt;
        }
        return $raw;
    }

    private function render_license_info_html(array $opts): string
    {
        $info = $this->get_license_info($opts);
        if (empty($info['ok'])) {
            $m = isset($info['message']) ? (string)$info['message'] : '校验失败';
            return '<div style="max-width:300px;"><span class="button button-primary" style="width:200px;height:30px;line-height:30px;font-size:22px;text-align:center;">' . esc_html($m) . '</span></div>';
        }

        $data = is_array($info['data']) ? $info['data'] : [];
        if (isset($data['__aipost_status']) && $data['__aipost_status'] === 'unactivated') {
            return '<div style="max-width:640px;"><a class="button" style="width:60%;height:30px;line-height:30px;font-size:13px;margin-bottom:5px">卡密未激活：已校验通过，可保存后在本域使用时自动激活</a></div>';
        }
        $category = $this->pick_first_string($data, ['category', 'cardType', 'type']);
        $createTimeRaw = $this->pick_first_string($data, ['createTime', 'startTime', 'activeTime', 'activationTime', 'beginTime']);
        $endTimeRaw = $this->pick_first_string($data, ['endTime', 'expireTime', 'expirationTime', 'expiryTime', 'dueTime']);
        $createTime = $this->normalize_time_string($createTimeRaw);
        $endTime = $this->normalize_time_string($endTimeRaw);

        $html = '';
        $html .= '<div style="max-width:640px;">';
        $html .= '<span style="width:30%;height:30px;line-height:30px;font-size:15px;">卡密类型 -&gt; </span>';
        $html .= '<a class="button" style="width:30%;height:30px;line-height:30px;font-size:13px;margin-bottom:5px">' . esc_html($category) . '</a>';
        $html .= '<br/>';
        $html .= '<span style="width:30%;height:30px;line-height:30px;font-size:15px;">激活时间 -&gt; </span>';
        $html .= '<a class="button" style="width:30%;height:30px;line-height:30px;font-size:13px;margin-bottom:5px">' . esc_html($createTime) . '</a>';
        $html .= '<br/>';
        $html .= '<span style="width:30%;height:30px;line-height:30px;font-size:15px;">到期时间 -&gt; </span>';
        $html .= '<a class="button" style="width:30%;height:30px;line-height:30px;font-size:13px;margin-bottom:5px">' . esc_html($endTime) . '</a>';
        $html .= '</div>';
        return $html;
    }

    // 渲染：授权操作（即时校验）
    public function render_license_block(): void
    {
        $nonce = \wp_create_nonce('ai_post_check_license');
        $adminAjax = \admin_url('admin-ajax.php');
        // 初始渲染：预填当前授权状态（如可用）
        $initialHtml = '';
        $saved = \get_option('ai-post', []);
        if (!is_array($saved)) { $saved = []; }
        if (!empty($saved['cardNum']) && !empty($saved['cardPwd'])) {
            $initialHtml = $this->render_license_info_html($saved);
        }
        ?>
        <div class="ai-post-license-panel" style="background:#f8f9fa;border:1px solid #e5e7eb;border-radius:6px;padding:12px;">
            <div style="display:flex;gap:8px;align-items:center;margin-bottom:8px;">
                <button type="button" class="button button-primary" id="ai-post-validate-license">立即校验授权</button>
                <span style="color:#666;">无需刷新页面，保存并校验当前输入的卡号/卡密</span>
            </div>
            <div id="ai-post-live-auth" style="padding:8px;border-radius:4px;background:#fff;border:1px solid #e5e7eb;"><?php echo $initialHtml; ?></div>
        </div>
        <script>
        (function($){
            $('#ai-post-validate-license').on('click', function(){
                var $btn = $(this);
                var num = $('input[name="ai-post[cardNum]"]').val() || '';
                var pwd = $('input[name="ai-post[cardPwd]"]').val() || '';
                $btn.prop('disabled', true).text('正在校验...');
                $.post('<?php echo esc_js($adminAjax); ?>', {
                    action: 'ai_post_check_license',
                    _ajax_nonce: '<?php echo esc_js($nonce); ?>',
                    cardNum: num,
                    cardPwd: pwd
                }).done(function(res){
                    var $live = $('#ai-post-live-auth');
                    if(res && res.success){
                        $live.html(res.data && res.data.html ? res.data.html : '已保存并校验');
                    } else {
                        $live.html((res && res.data && res.data.message) ? res.data.message : '校验失败');
                    }
                    $live.show();
                }).fail(function(){
                    alert('请求失败');
                }).always(function(){
                    $btn.prop('disabled', false).text('立即校验授权');
                });
            });
        })(jQuery);
        </script>
        <?php
    }

    // AJAX：保存并即时校验授权
    public function ajax_check_license(): void
    {
        \check_ajax_referer('ai_post_check_license');
        if (!\current_user_can('manage_options')) {
            \wp_send_json_error(['message' => '权限不足'], 403);
        }
        $cardNum = isset($_POST['cardNum']) ? trim((string) $_POST['cardNum']) : '';
        $cardPwd = isset($_POST['cardPwd']) ? trim((string) $_POST['cardPwd']) : '';

        $pending = \get_option('ai-post', []);
        if (!is_array($pending)) { $pending = []; }
        $pending['cardNum'] = $cardNum;
        $pending['cardPwd'] = $cardPwd;

        $info = $this->get_license_info($pending);
        if (empty($info['ok'])) {
            $msg = isset($info['message']) ? (string)$info['message'] : '校验失败';
            \wp_send_json_error(['message' => $msg]);
        }

        $data = (isset($info['data']) && is_array($info['data'])) ? $info['data'] : [];
        $status = isset($data['__aipost_status']) ? (string)$data['__aipost_status'] : '';

        // 若上游返回绑定域名信息，直接比对
        $boundHost = $this->extract_bound_host($data);
        if ($status === 'activated' && $boundHost !== '') {
            $current = parse_url((string)get_option('home'), PHP_URL_HOST);
            $currentHost = $this->normalize_host((string)$current);
            $bindHost = $this->normalize_host((string)$boundHost);
            if ($currentHost !== '' && $bindHost !== '' && $currentHost !== $bindHost) {
                \wp_send_json_error(['message' => '设备认证失败：该卡密已绑定到其他站点（' . $bindHost . '）']);
            }
        }

        $old = \get_option('ai-post', []);
        if (!is_array($old)) { $old = []; }
        \update_option('ai-post', $pending);
        $bind = $this->verify_license_binding($cardNum, $cardPwd);
        if (empty($bind['ok'])) {
            \update_option('ai-post', $old);
            $m = isset($bind['message']) ? (string)$bind['message'] : '设备认证失败：该卡密已被其他站点绑定或校验不通过';
            \wp_send_json_error(['message' => $m]);
        }

        // 预检通过后再拉一次，尽量拿到激活/到期时间用于回显
        $info = $this->get_license_info($pending);
        $html = $this->render_license_info_html($pending);

        // 校验通过：刷新心跳缓存
        \set_transient('aipost_license_hb', 'valid', 21600);

        \wp_send_json_success(['html' => $html]);
    }

    /**
     * 验证授权 API 响应结构的基本合法性（防止伪造服务器返回简单固定值）
     */
    private function _validate_auth_response(array $json): bool
    {
        if (!isset($json['code']) || !isset($json['msg'])) {
            return false;
        }
        if (!is_int($json['code']) && !is_numeric($json['code'])) {
            return false;
        }
        if ((int)$json['code'] === 200) {
            if (!isset($json['data']) || !is_array($json['data'])) {
                return false;
            }
        }
        return true;
    }

    /**
     * 运行时授权心跳检查（带 Transient 缓存，避免每次任务都远端请求）
     * 返回 true 表示授权有效，false 表示无效或过期
     * @param int $ttl 缓存有效秒数，默认 6 小时
     */
    public function license_heartbeat_check(int $ttl = 21600): bool
    {
        $cache_key = 'aipost_license_hb';
        $cached = \get_transient($cache_key);
        if ($cached === 'valid') {
            return true;
        }
        if ($cached === 'invalid') {
            return false;
        }

        $opts = \get_option('ai-post', []);
        if (!is_array($opts)) { $opts = []; }
        $cardNum = isset($opts['cardNum']) ? trim((string)$opts['cardNum']) : '';
        $cardPwd = isset($opts['cardPwd']) ? trim((string)$opts['cardPwd']) : '';
        if ($cardNum === '' || $cardPwd === '') {
            \set_transient($cache_key, 'invalid', $ttl);
            return false;
        }

        $info = $this->get_license_info($opts);
        if (empty($info['ok'])) {
            \set_transient($cache_key, 'invalid', min($ttl, 3600));
            return false;
        }

        $data = is_array($info['data']) ? $info['data'] : [];
        $status = isset($data['__aipost_status']) ? (string)$data['__aipost_status'] : '';

        // 检查过期
        if ($status === 'activated') {
            $endTimeRaw = $this->pick_first_string($data, ['endTime', 'expireTime', 'expirationTime', 'expiryTime', 'dueTime']);
            $endTime = $this->normalize_time_string($endTimeRaw);
            $expTs = $endTime !== '' ? strtotime($endTime) : false;
            $nowTs = function_exists('current_time') ? current_time('timestamp') : time();
            if ($expTs !== false && $expTs < $nowTs) {
                \set_transient($cache_key, 'invalid', min($ttl, 3600));
                Logger::warning('license: heartbeat expired', 'License');
                return false;
            }
        }

        // 检查域名绑定
        $boundHost = $this->extract_bound_host($data);
        if ($status === 'activated' && $boundHost !== '') {
            $current = parse_url((string)get_option('home'), PHP_URL_HOST);
            $currentHost = $this->normalize_host((string)$current);
            $bindHost = $this->normalize_host((string)$boundHost);
            if ($currentHost !== '' && $bindHost !== '' && $currentHost !== $bindHost) {
                \set_transient($cache_key, 'invalid', min($ttl, 3600));
                Logger::warning('license: heartbeat domain mismatch', 'License');
                return false;
            }
        }

        \set_transient($cache_key, 'valid', $ttl);
        return true;
    }

    /**
     * 清除心跳缓存（在授权校验失败或设置变更时调用）
     */
    public function license_heartbeat_invalidate(): void
    {
        \delete_transient('aipost_license_hb');
    }
}
