<?php

namespace RecastPaywall\Rest;

use RecastPaywall\Services\EntitlementService;
use RecastPaywall\Sync\InventorySync;

/**
 * REST API controller
 */
class ApiController {
    /**
     * Namespace
     */
    private const NAMESPACE = 'recast-paywall/v1';

    /**
     * Entitlement service
     */
    private EntitlementService $entitlementService;

    /**
     * Inventory sync
     */
    private InventorySync $inventorySync;

    /**
     * Constructor
     */
    public function __construct(EntitlementService $entitlementService, InventorySync $inventorySync) {
        $this->entitlementService = $entitlementService;
        $this->inventorySync = $inventorySync;
    }

    /**
     * Get brand ID from settings
     */
    private function getBrandId(): string {
        $settings = get_option('recast_paywall_settings', []);
        return trim($settings['brand_id'] ?? '');
    }

    /**
     * Register REST routes
     */
    public function registerRoutes(): void {
        // Entitlement check endpoint
        register_rest_route(self::NAMESPACE, '/entitlement', [
            [
                'methods' => \WP_REST_Server::READABLE,
                'callback' => [$this, 'checkEntitlement'],
                'permission_callback' => [$this, 'checkEntitlementPermission'],
                'args' => [
                    'post_id' => [
                        'required' => true,
                        'type' => 'integer',
                        'sanitize_callback' => 'absint',
                        'validate_callback' => function($param) {
                            return get_post($param) !== null;
                        },
                    ],
                ],
            ],
        ]);

        // Sync endpoint (admin only)
        register_rest_route(self::NAMESPACE, '/sync', [
            [
                'methods' => \WP_REST_Server::CREATABLE,
                'callback' => [$this, 'syncPost'],
                'permission_callback' => [$this, 'checkSyncPermission'],
                'args' => [
                    'post_id' => [
                        'required' => true,
                        'type' => 'integer',
                        'sanitize_callback' => 'absint',
                        'validate_callback' => function($param) {
                            return get_post($param) !== null;
                        },
                    ],
                ],
            ],
        ]);

        // Status endpoint
        register_rest_route(self::NAMESPACE, '/status', [
            [
                'methods' => \WP_REST_Server::READABLE,
                'callback' => [$this, 'getStatus'],
                'permission_callback' => [$this, 'checkStatusPermission'],
                'args' => [
                    'post_id' => [
                        'required' => true,
                        'type' => 'integer',
                        'sanitize_callback' => 'absint',
                        'validate_callback' => function($param) {
                            return get_post($param) !== null;
                        },
                    ],
                ],
            ],
        ]);

        // Create purchase intent (public; server-side auth)
        register_rest_route(self::NAMESPACE, '/purchase-intent', [
            [
                'methods' => \WP_REST_Server::CREATABLE,
                'callback' => [$this, 'createPurchaseIntent'],
                'permission_callback' => [$this, 'checkPurchasePermission'],
                'args' => [
                    'post_id' => [
                        'required' => true,
                        'type' => 'integer',
                        'sanitize_callback' => 'absint',
                        'validate_callback' => function($param) {
                            return get_post($param) !== null;
                        },
                    ],
                ],
            ],
        ]);

        // Clear cache endpoint (public; for post-purchase cache clearing)
        register_rest_route(self::NAMESPACE, '/clear-cache', [
            [
                'methods' => \WP_REST_Server::CREATABLE,
                'callback' => [$this, 'clearCache'],
                'permission_callback' => [$this, 'checkPurchasePermission'],
                'args' => [
                    'post_id' => [
                        'required' => true,
                        'type' => 'integer',
                        'sanitize_callback' => 'absint',
                        'validate_callback' => function($param) {
                            return get_post($param) !== null;
                        },
                    ],
                ],
            ],
        ]);
    }

    /**
     * Check entitlement permission
     */
    public function checkEntitlementPermission(\WP_REST_Request $request): bool {
        // Allow public access for entitlement checks
        return true;
    }

    /**
     * Check sync permission
     */
    public function checkSyncPermission(\WP_REST_Request $request): bool {
        return current_user_can('edit_posts');
    }

    /**
     * Check status permission
     */
    public function checkStatusPermission(\WP_REST_Request $request): bool {
        return current_user_can('edit_posts');
    }

    /**
     * Check purchase intent permission (public; relies on server auth)
     */
    public function checkPurchasePermission(\WP_REST_Request $request): bool {
        return true;
    }

    /**
     * Check entitlement
     */
    public function checkEntitlement(\WP_REST_Request $request): \WP_REST_Response {
        $postId = $request->get_param('post_id');
        $userId = get_current_user_id();

        $isEntitled = $this->entitlementService->isEntitled($postId, $userId, true); // Force bypass cache
        $isPaywalled = $this->entitlementService->isPostPaywalled($postId);

        return new \WP_REST_Response([
            'entitled' => $isEntitled,
            'paywalled' => $isPaywalled,
            'post_id' => $postId,
            'user_id' => $userId,
        ]);
    }

    /**
     * Sync post
     */
    public function syncPost(\WP_REST_Request $request): \WP_REST_Response {
        $postId = $request->get_param('post_id');
        $post = get_post($postId);

        if (!$post) {
            return new \WP_REST_Response([
                'success' => false,
                'message' => __('Post not found', 'recast-paywall'),
            ], 404);
        }

        // Force sync regardless of current gating/settings
        $this->inventorySync->forceSyncPost($postId);

        // Get updated status
        $status = $this->inventorySync->getSyncStatus($postId);

        return new \WP_REST_Response([
            'success' => true,
            'message' => __('Post synced successfully', 'recast-paywall'),
            'status' => $status,
        ]);
    }

    /**
     * Get status
     */
    public function getStatus(\WP_REST_Request $request): \WP_REST_Response {
        $postId = $request->get_param('post_id');
        $status = $this->inventorySync->getSyncStatus($postId);

        return new \WP_REST_Response($status);
    }

    /**
     * Create purchase intent for a post/product
     */
    public function createPurchaseIntent(\WP_REST_Request $request): \WP_REST_Response {
        $postId = (int) $request->get_param('post_id');
        $post = get_post($postId);
        if (!$post) {
            return new \WP_REST_Response(['message' => __('Post not found', 'recast-paywall')], 404);
        }

        // Determine external user id per existing mapping
        $currentUserId = get_current_user_id();
        $externalUserId = $this->entitlementService->getExternalUserId($currentUserId ?: null, $postId);
        
        if (empty($externalUserId)) {
            return new \WP_REST_Response(['message' => __('Unable to determine user identity', 'recast-paywall')], 400);
        }

        $client = new \RecastPaywall\Api\RecastClient();
        // Optional tariff details via post meta (price in minor units, currency optional)
        $tariff = [];
        $price = get_post_meta($postId, '_recast_price', true);
        if ($price !== '') {
            $tariff['amount'] = (int) $price;
        }
        $currency = apply_filters('recast_paywall_tariff_currency', 'CST', $postId);
        if (!empty($currency)) {
            $tariff['currency'] = (string) $currency;
        }

        $options = [];
        if (!empty($tariff)) {
            $options['tariffDetails'] = $tariff;
        }

        // Prefix external IDs with brandId for proper namespacing
        // Note: Use hyphen separator (not underscore) - API requires /^[0-9a-zA-Z-]+$/
        $brandId = $this->getBrandId();
        $prefixedUserId = $brandId ? $brandId . '-' . $externalUserId : $externalUserId;
        $prefixedProductId = $brandId ? $brandId . '-' . $postId : (string) $postId;

        $result = $client->createPurchaseIntent($prefixedUserId, $prefixedProductId, $options);

        if (is_wp_error($result)) {
            return new \WP_REST_Response(['message' => $result->get_error_message()], 400);
        }

        // Mark purchase activity for cache bypass
        $this->entitlementService->markPurchaseActivity($postId, $currentUserId ?: null);

        // Normalize response keys
        $intentToken = $result['intentToken'] ?? ($result['item']['intentToken'] ?? ($result['data']['intentToken'] ?? null));
        $intentUrl = $result['intentUrl'] ?? ($result['item']['intentUrl'] ?? ($result['data']['intentUrl'] ?? null));

        return new \WP_REST_Response([
            'post_id' => $postId,
            'intentToken' => $intentToken,
            'intentUrl' => $intentUrl,
        ]);
    }

    /**
     * Clear entitlement cache for a post
     */
    public function clearCache(\WP_REST_Request $request): \WP_REST_Response {
        $postId = (int) $request->get_param('post_id');
        $userId = get_current_user_id();
        
        if ($userId) {
            // Clear cache for specific user/post combination
            $this->entitlementService->clearCache($postId, $userId);
        } else {
            // Clear all caches for this post (for anonymous users)
            $this->entitlementService->clearCache($postId);
        }

        return new \WP_REST_Response([
            'success' => true,
            'message' => __('Cache cleared', 'recast-paywall'),
        ]);
    }
}
