<?php
/**
 * Credit REST - REST API endpoints for credit system
 *
 * All REST endpoints in one file for simplicity.
 * Handles balance queries, credit usage, registration, and troubleshooting.
 *
 * @package AIPT\Core\CreditSystem
 */

namespace AIPT\Core\CreditSystem;

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Credit REST Controller
 */
class CreditRest
{
    private const NAMESPACE = 'aipt/v2/credit';

    /**
     * Register REST routes
     */
    public function register(): void
    {
        add_action('rest_api_init', [$this, 'registerRoutes']);
    }

    /**
     * Register all routes
     */
    public function registerRoutes(): void
    {

        register_rest_route(self::NAMESPACE, '/balance', [
            'methods' => 'GET',
            'callback' => [$this, 'getBalance'],
            'permission_callback' => [$this, 'check_permissions']
        ]);

        register_rest_route(self::NAMESPACE, '/check', [
            'methods' => 'GET',
            'callback' => [$this, 'checkCredits'],
            'permission_callback' => [$this, 'check_permissions'],
            'args' => [
                'action_type' => [
                    'required' => false,
                    'type' => 'string',
                    'default' => 'description',
                    'sanitize_callback' => 'sanitize_text_field'
                ],
                'quantity' => [
                    'required' => false,
                    'type' => 'integer',
                    'default' => 1,
                    'sanitize_callback' => 'absint'
                ]
            ]
        ]);

        register_rest_route(self::NAMESPACE, '/use', [
            'methods' => 'POST',
            'callback' => [$this, 'useCredits'],
            'permission_callback' => [$this, 'check_permissions_write'],
            'args' => [
                'action_type' => [
                    'required' => true,
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_text_field'
                ],
                'quantity' => [
                    'required' => false,
                    'type' => 'integer',
                    'default' => 1,
                    'sanitize_callback' => 'absint'
                ]
            ]
        ]);

        register_rest_route(self::NAMESPACE, '/refresh', [
            'methods' => 'POST',
            'callback' => [$this, 'forceRefresh'],
            'permission_callback' => [$this, 'check_permissions_write']
        ]);

        register_rest_route(self::NAMESPACE, '/register', [
            'methods' => 'POST',
            'callback' => [$this, 'registerSite'],
            'permission_callback' => [$this, 'check_permissions_admin']
        ]);

        register_rest_route(self::NAMESPACE, '/troubleshoot', [
            'methods' => 'POST',
            'callback' => [$this, 'troubleshoot'],
            'permission_callback' => [$this, 'check_permissions_admin'],
            'args' => [
                'action' => [
                    'required' => true,
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_text_field'
                ]
            ]
        ]);

        register_rest_route(self::NAMESPACE, '/status', [
            'methods' => 'GET',
            'callback' => [$this, 'getStatus'],
            'permission_callback' => [$this, 'check_permissions']
        ]);

        register_rest_route(self::NAMESPACE, '/clear-cache', [
            'methods' => 'POST',
            'callback' => [$this, 'clearCache'],
            'permission_callback' => [$this, 'check_permissions_admin']
        ]);

        register_rest_route(self::NAMESPACE, '/accept-terms', [
            'methods' => 'POST',
            'callback' => [$this, 'acceptTerms'],
            'permission_callback' => [$this, 'check_permissions_admin']
        ]);

        register_rest_route(self::NAMESPACE, '/decline', [
            'methods' => 'POST',
            'callback' => [$this, 'declineTerms'],
            'permission_callback' => [$this, 'check_permissions_admin']
        ]);

        register_rest_route(self::NAMESPACE, '/usage-summary', [
            'methods' => 'GET',
            'callback' => [$this, 'getUsageSummary'],
            'permission_callback' => [$this, 'check_permissions']
        ]);

        register_rest_route(self::NAMESPACE, '/troubleshoot-flag', [
            'methods' => 'GET',
            'callback' => [$this, 'checkTroubleshootFlag'],
            'permission_callback' => [$this, 'check_permissions']
        ]);

        register_rest_route(self::NAMESPACE, '/clear-troubleshoot-flag', [
            'methods' => 'POST',
            'callback' => [$this, 'clearTroubleshootFlag'],
            'permission_callback' => [$this, 'check_permissions_admin']
        ]);
    }

    /**
     * Get current balance
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function getBalance(\WP_REST_Request $request): \WP_REST_Response
    {
        $manager = CreditManager::getInstance();
        $force = $request->get_param('force') === 'true';

        return $this->success([
            'current_balance' => $manager->getBalance($force),
            'credit_costs' => $this->formatCosts($manager->getCosts())
        ]);
    }

    /**
     * Check if action is allowed
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function checkCredits(\WP_REST_Request $request): \WP_REST_Response
    {
        $action = $request->get_param('action_type');
        $quantity = $request->get_param('quantity');

        $result = CreditManager::getInstance()->check($action, $quantity);

        return $this->success([
            'allowed' => $result->allowed,
            'cost' => $result->cost,
            'remaining' => $result->remaining
        ]);
    }

    /**
     * Use credits for action
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function useCredits(\WP_REST_Request $request): \WP_REST_Response
    {
        $action = $request->get_param('action_type');
        $quantity = $request->get_param('quantity');
        $details = $request->get_param('details') ?? [];

        $manager = CreditManager::getInstance();
        $success = $manager->use($action, $quantity, $details);

        if (!$success) {
            return $this->error('Insufficient optimization requests', 403, 'insufficient_optimization_requests');
        }

        return $this->success([
            'used' => true,
            'current_balance' => $manager->getBalance()
        ]);
    }

    /**
     * Force refresh from API
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function forceRefresh(\WP_REST_Request $request): \WP_REST_Response
    {
        $manager = CreditManager::getInstance();
        $balance = $manager->sync();

        return $this->success([
            'current_balance' => $balance,
            'credit_costs' => $this->formatCosts($manager->getCosts())
        ]);
    }

    /**
     * Register site with remote API
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function registerSite(\WP_REST_Request $request): \WP_REST_Response
    {
        $data = [
            'site_url' => get_site_url(),
            'site_name' => get_bloginfo('name'),
            'admin_email' => get_option('admin_email'),
            'version' => defined('AIPT_VERSION') ? AIPT_VERSION : '1.0.0'
        ];

        $result = CreditManager::getInstance()->register($data);

        if (empty($result['success'])) {
            return $this->error($result['error'] ?? 'Registration failed', 400);
        }

        $manager = CreditManager::getInstance();
        $manager->clearCache();
        $balance = $manager->getBalance(true);
        $result['current_balance'] = $balance;

        return $this->success($result);
    }

    /**
     * Run troubleshoot action
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function troubleshoot(\WP_REST_Request $request): \WP_REST_Response
    {
        $action = $request->get_param('action');
        $data = $request->get_params();

        $result = CreditManager::getInstance()->troubleshoot($action, $data);

        if (empty($result['success'])) {
            return $this->error($result['error'] ?? 'Troubleshoot failed', 400);
        }

        return $this->success($result);
    }

    /**
     * Get system status
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function getStatus(\WP_REST_Request $request): \WP_REST_Response
    {
        $manager = CreditManager::getInstance();
        $cachedPlan = \get_option('aipt_credit_plan_name', null);

        return $this->success([
            'registered' => $manager->isRegistered(),
            'has_balance' => $manager->getBalance() !== null,
            'plan' => $cachedPlan ?? 'free'
        ]);
    }

    /**
     * Clear credit cache
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function clearCache(\WP_REST_Request $request): \WP_REST_Response
    {
        CreditManager::getInstance()->clearCache();

        return $this->success([
            'cleared' => true
        ]);
    }

    /**
     * Accept terms and conditions
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function acceptTerms(\WP_REST_Request $request): \WP_REST_Response
    {
        update_option('aipt_bulk_terms_accepted', '1', false);
        update_option('aipt_credit_terms_accepted', '1', false);

        return $this->success([
            'accepted' => true,
            'message' => 'Terms accepted successfully'
        ]);
    }

    public function declineTerms(\WP_REST_Request $request): \WP_REST_Response
    {
        update_option('aipt_bulk_terms_accepted', '0', false);
        update_option('aipt_credit_terms_accepted', '0', false);

        $apiClient = new CreditApiClient();
        $apiClient->optOut();

        return $this->success([
            'declined' => true,
            'message' => 'Terms declined'
        ]);
    }

    /**
     * Get usage summary for registration
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function getUsageSummary(\WP_REST_Request $request): \WP_REST_Response
    {
        $localUsage = get_option('aipt_credit_local_usage', [
            'total' => 0,
            'actions' => [],
            'started' => null
        ]);

        return $this->success([
            'total_local_used' => $localUsage['total'] ?? 0,
            'actions_breakdown' => $localUsage['actions'] ?? [],
            'summary_start_time' => $localUsage['started'] ?? null,
            'summary_last_activity' => $localUsage['last_activity'] ?? null
        ]);
    }

    /**
     * Check if troubleshoot modal should be shown
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function checkTroubleshootFlag(\WP_REST_Request $request): \WP_REST_Response
    {
        $showModal = get_option('aipt_credit_show_troubleshoot', false);

        return $this->success([
            'show_troubleshoot_modal' => (bool) $showModal
        ]);
    }

    /**
     * Clear troubleshoot flag
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function clearTroubleshootFlag(\WP_REST_Request $request): \WP_REST_Response
    {
        delete_option('aipt_credit_show_troubleshoot');

        return $this->success([
            'cleared' => true
        ]);
    }

    /**
     * Check if user has read permissions
     *
     * @return bool
     */
    public function check_permissions(): bool
    {
        return current_user_can('edit_posts');
    }

    /**
     * Check if user has write permissions with nonce verification.
     *
     * Covers low-privilege metered operations (credit consumption / refresh)
     * that are exposed to any user who can publish content — historically
     * Authors / Editors / Shop Managers were allowed to spend credits.
     *
     * @param \WP_REST_Request $request
     * @return bool
     */
    public function check_permissions_write(\WP_REST_Request $request): bool
    {
        $has_capability = current_user_can('manage_options') || current_user_can('edit_posts');
        return $has_capability && $this->verifyNonce($request);
    }

    /**
     * Administrator-only writes with nonce verification.
     *
     * Used for site-level credit-system mutations that must not be available
     * to Authors/Editors/Shop Managers: registering the site with the credit
     * service, troubleshooting/reset flows, terms acceptance, cache flush.
     * Previously enforced via a separate canManageWithNonce() callback; the
     * audit refactor accidentally collapsed both tiers into
     * check_permissions_write() and exposed these endpoints to edit_posts.
     *
     * @param \WP_REST_Request $request
     * @return bool
     */
    public function check_permissions_admin(\WP_REST_Request $request): bool
    {
        return current_user_can('manage_options') && $this->verifyNonce($request);
    }

    /**
     * Verify REST nonce
     *
     * @param \WP_REST_Request $request
     * @return bool
     */
    private function verifyNonce(\WP_REST_Request $request): bool
    {
        $nonce = $request->get_header('X-WP-Nonce');
        if (empty($nonce)) {
            $nonce = $request->get_param('_wpnonce');
        }

        return wp_verify_nonce($nonce, 'wp_rest');
    }

    /**
     * Create success response
     *
     * @param array $data Response data
     * @return \WP_REST_Response
     */
    private function success(array $data): \WP_REST_Response
    {
        return new \WP_REST_Response(
            array_merge(['success' => true], $data),
            200
        );
    }

    /**
     * Create error response
     *
     * @param string $message Error message
     * @param int $code HTTP status code
     * @return \WP_REST_Response
     */
    private function error(string $message, int $code, string $error_code = ''): \WP_REST_Response
    {
        $data = ['success' => false, 'error' => $message];
        if ($error_code !== '') {
            $data['code'] = $error_code;
        }
        return new \WP_REST_Response($data, $code);
    }

    /**
     * Format costs for response
     *
     * @param array $costs Costs by action
     * @return array Formatted costs array
     */
    private function formatCosts(array $costs): array
    {
        $result = [];
        foreach ($costs as $action => $cost) {
            $result[] = [
                'action_type' => $action,
                'cost' => $cost
            ];
        }
        return $result;
    }
}
