<?php

namespace XHTheme\AIToolbox;

defined('ABSPATH') || exit;

final class XHDashboardRemoteState
{
    private static $instance = null;

    const REST_ROUTE = 'dashboard-state';
    const SYNC_OPTION = 'xhtheme_aitoolbox_dashboard_remote_synced_at';
    const AUTO_REFRESH_TTL = 300;

    public static function getInstance()
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    private function __construct()
    {
        add_action('rest_api_init', [$this, 'register_rest_routes']);
    }

    public function register_rest_routes()
    {
        register_rest_route(XHTHEME_AI_TOOLBOX_RESTNAME, '/' . self::REST_ROUTE, [
            'methods' => 'POST',
            'callback' => [$this, 'rest_dashboard_state'],
            'permission_callback' => function () {
                return current_user_can('edit_posts');
            },
        ]);
    }

    public function get_bootstrap_payload()
    {
        if ($this->should_refresh_for_new_day()) {
            $this->refresh_remote_state(true);
        }

        return $this->build_payload();
    }

    public function rest_dashboard_state($request)
    {
        $force_refresh = filter_var($request->get_param('force'), FILTER_VALIDATE_BOOLEAN);
        $should_refresh = $force_refresh || $this->should_refresh_for_dashboard();
        $refreshed = false;

        if ($should_refresh) {
            $refreshed = $this->refresh_remote_state(true);
            if (!$refreshed && $force_refresh) {
                return rest_ensure_response([
                    'success' => false,
                    'cached' => true,
                    'refreshed' => false,
                    'message' => __('Failed to fetch the latest data from the cloud. Please try again later.', 'xhtheme-ai-toolbox'),
                    'data' => $this->build_payload(),
                ]);
            }
        }

        return rest_ensure_response([
            'success' => true,
            'cached' => !$refreshed,
            'refreshed' => $refreshed,
            'ttl' => self::AUTO_REFRESH_TTL,
            'lastSyncedAt' => $this->get_last_synced_at(),
            'message' => $refreshed
                ? __('Cloud data has been synced.', 'xhtheme-ai-toolbox')
                : __('Current cached data has been returned.', 'xhtheme-ai-toolbox'),
            'data' => $this->build_payload(),
        ]);
    }

    public function get_last_synced_at()
    {
        return (int) get_option(self::SYNC_OPTION, 0);
    }

    private function should_refresh_for_dashboard()
    {
        if (!$this->has_api_token()) {
            return false;
        }

        if ($this->should_refresh_for_new_day()) {
            return true;
        }

        $last_synced_at = $this->get_last_synced_at();
        if (empty($last_synced_at)) {
            return true;
        }

        return (time() - $last_synced_at) >= self::AUTO_REFRESH_TTL;
    }

    private function should_refresh_for_new_day()
    {
        if (!$this->has_api_token()) {
            return false;
        }

        $quota = XHThemeAi::getInstance()->userData('quota');
        if (!is_array($quota) || empty($quota['date'])) {
            return true;
        }

        $today_beijing = wp_date('Y-m-d', null, new \DateTimeZone('Asia/Shanghai'));
        return $quota['date'] !== $today_beijing;
    }

    private function has_api_token()
    {
        return (bool) xh_option('appId', '');
    }

    private function refresh_remote_state($bypass_api_guard = false)
    {
        if (!$this->has_api_token()) {
            return false;
        }

        $ai_instance = XHThemeAi::getInstance();

        if ($bypass_api_guard) {
            delete_transient('xhtheme_aitoolbox_apicheck');
        }

        $models = $ai_instance->fetchRemoteModelList();
        $ai_instance->resetRuntimeCache();

        if (!is_array($models)) {
            return false;
        }

        update_option(self::SYNC_OPTION, time(), false);
        return true;
    }

    private function build_payload()
    {
        $ai_instance = XHThemeAi::getInstance();
        $ai_instance->resetRuntimeCache();

        $user_quota = $this->format_quota_date($ai_instance->userData('quota'));

        return [
            'userQuota' => $user_quota,
            'modelList' => $ai_instance->chatLists('localize'),
            'modelVersion' => $ai_instance->getVersion(),
            'updateTime' => $ai_instance->getModelTime(),
            'dashboardMessages' => $this->get_localized_dashboard_messages($ai_instance->getDashboardMessages()),
        ];
    }

    private function get_localized_dashboard_messages($messages)
    {
        if (!is_array($messages) || empty($messages)) {
            return [];
        }

        $locale = function_exists('get_user_locale') ? get_user_locale(get_current_user_id()) : get_locale();
        $language_key = (strpos($locale, 'zh_') === 0 || strpos($locale, 'zh-') === 0) ? 'zh_CN' : 'en_US';
        $fallback_key = $language_key === 'zh_CN' ? 'en_US' : 'zh_CN';

        $localized_messages = isset($messages[$language_key]) && is_array($messages[$language_key])
            ? $messages[$language_key]
            : [];

        if (empty($localized_messages) && isset($messages[$fallback_key]) && is_array($messages[$fallback_key])) {
            $localized_messages = $messages[$fallback_key];
        }

        if (empty($localized_messages)) {
            return [];
        }

        return array_values(array_filter(array_map([$this, 'sanitize_dashboard_message'], $localized_messages)));
    }

    private function sanitize_dashboard_message($message)
    {
        if (!is_array($message)) {
            return null;
        }

        $id = isset($message['id']) ? sanitize_key($message['id']) : '';
        $title = isset($message['title']) ? sanitize_text_field($message['title']) : '';
        $description = isset($message['description']) ? sanitize_textarea_field($message['description']) : '';

        if ($title === '' && $description === '') {
            return null;
        }

        $sanitized = [
            'id' => $id !== '' ? $id : md5($title . $description),
            'type' => isset($message['type']) ? sanitize_key($message['type']) : 'notice',
            'tone' => isset($message['tone']) ? sanitize_key($message['tone']) : 'blue',
            'color' => isset($message['color']) ? sanitize_key($message['color']) : '',
            'icon' => isset($message['icon']) ? sanitize_key($message['icon']) : 'info',
            'label' => isset($message['label']) ? sanitize_text_field($message['label']) : '',
            'title' => $title,
            'description' => $description,
        ];

        if (!empty($message['action']) && is_array($message['action'])) {
            $action = [
                'type' => isset($message['action']['type']) ? sanitize_key($message['action']['type']) : '',
                'label' => isset($message['action']['label']) ? sanitize_text_field($message['action']['label']) : '',
                'target' => isset($message['action']['target']) ? sanitize_key($message['action']['target']) : '',
                'id' => isset($message['action']['id']) ? sanitize_key($message['action']['id']) : '',
            ];
            if (!empty($message['action']['url']) && is_string($message['action']['url'])) {
                $action['url'] = esc_url_raw($message['action']['url']);
            }
            if (!empty($message['action']['path']) && is_string($message['action']['path'])) {
                $path = sanitize_text_field($message['action']['path']);
                if (preg_match('/^[a-z][a-z0-9+.-]*:/i', $path) && !preg_match('/^https?:\/\//i', $path)) {
                    $path = '';
                }
                $action['path'] = $path;
            }
            if ($action['type'] !== '' && $action['label'] !== '') {
                $sanitized['action'] = $action;
            }
        }

        return $sanitized;
    }

    private function format_quota_date($user_quota)
    {
        if (!is_array($user_quota) || empty($user_quota['date'])) {
            return $user_quota;
        }

        $timestamp = strtotime($user_quota['date']);
        if (!$timestamp) {
            return $user_quota;
        }

        $locale = get_locale();
        if (strpos($locale, 'zh_') === 0 || strpos($locale, 'zh-') === 0) {
            $user_quota['date'] = date('Y.m.d', $timestamp);
        } else {
            $user_quota['date'] = date('M j', $timestamp);
        }

        return $user_quota;
    }
}
