<?php

/**
 * Pause Subscription REST Controller
 *
 * REST API endpoints for subscription pause/vacation operations.
 *
 * @package ArraySubs\Features\SkipRenewal\REST
 * @since 1.0.0
 */

namespace ArraySubs\Features\SkipRenewal\REST;

defined('ABSPATH') || exit;

use ArraySubs\Supports\BaseRestController;
use ArraySubs\Features\SkipRenewal\Services\PauseManager;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

/**
 * Pause REST controller
 */
class PauseController extends BaseRestController
{
    /**
     * Enable auto-loading
     *
     * @var bool
     */
    public static $loadable = true;

    /**
     * Pause manager instance
     *
     * @var PauseManager
     */
    private PauseManager $pause_manager;

    /**
     * Initialize controller
     */
    public function __construct()
    {
        parent::__construct();
        $this->pause_manager = new PauseManager();
    }

    /**
     * Register REST routes
     *
     * @return void
     */
    public function registerRoutes(): void
    {
        // Get pause status
        register_rest_route(
            $this->namespace,
            '/subscriptions/(?P<id>\d+)/pause-status',
            [
                'methods'             => 'GET',
                'callback'            => [$this, 'getPauseStatus'],
                'permission_callback' => [$this, 'checkAdminPermission'],
                'args'                => [
                    'id' => [
                        'required'          => true,
                        'type'              => 'integer',
                        'sanitize_callback' => 'absint',
                    ],
                ],
            ]
        );

        // Can pause check
        register_rest_route(
            $this->namespace,
            '/subscriptions/(?P<id>\d+)/can-pause',
            [
                'methods'             => 'GET',
                'callback'            => [$this, 'canPause'],
                'permission_callback' => [$this, 'checkAdminPermission'],
                'args'                => [
                    'id' => [
                        'required'          => true,
                        'type'              => 'integer',
                        'sanitize_callback' => 'absint',
                    ],
                ],
            ]
        );

        // Pause subscription
        register_rest_route(
            $this->namespace,
            '/subscriptions/(?P<id>\d+)/pause',
            [
                'methods'             => 'POST',
                'callback'            => [$this, 'pauseSubscription'],
                'permission_callback' => [$this, 'checkAdminPermission'],
                'args'                => [
                    'id' => [
                        'required'          => true,
                        'type'              => 'integer',
                        'sanitize_callback' => 'absint',
                    ],
                    'days' => [
                        'required'          => false,
                        'type'              => 'integer',
                        'minimum'           => 1,
                        'sanitize_callback' => 'absint',
                    ],
                    'resume_date' => [
                        'required'          => false,
                        'type'              => 'string',
                        'sanitize_callback' => 'sanitize_text_field',
                    ],
                    'reason' => [
                        'required'          => false,
                        'type'              => 'string',
                        'sanitize_callback' => 'sanitize_textarea_field',
                    ],
                ],
            ]
        );

        // Resume subscription
        register_rest_route(
            $this->namespace,
            '/subscriptions/(?P<id>\d+)/resume',
            [
                'methods'             => 'POST',
                'callback'            => [$this, 'resumeSubscription'],
                'permission_callback' => [$this, 'checkAdminPermission'],
                'args'                => [
                    'id' => [
                        'required'          => true,
                        'type'              => 'integer',
                        'sanitize_callback' => 'absint',
                    ],
                ],
            ]
        );

        // Get pause history
        register_rest_route(
            $this->namespace,
            '/subscriptions/(?P<id>\d+)/pause-history',
            [
                'methods'             => 'GET',
                'callback'            => [$this, 'getPauseHistory'],
                'permission_callback' => [$this, 'checkAdminPermission'],
                'args'                => [
                    'id' => [
                        'required'          => true,
                        'type'              => 'integer',
                        'sanitize_callback' => 'absint',
                    ],
                ],
            ]
        );

        // =========================================
        // Customer-facing routes (My Subscriptions)
        // =========================================

        // Customer: Pause subscription
        register_rest_route(
            $this->namespace,
            '/my-subscriptions/(?P<id>\d+)/pause',
            [
                'methods'             => 'POST',
                'callback'            => [$this, 'pauseSubscription'],
                'permission_callback' => [$this, 'checkCustomerPermission'],
                'args'                => [
                    'id' => [
                        'required'          => true,
                        'type'              => 'integer',
                        'sanitize_callback' => 'absint',
                    ],
                    'days' => [
                        'required'          => false,
                        'type'              => 'integer',
                        'minimum'           => 1,
                        'sanitize_callback' => 'absint',
                    ],
                    'resume_date' => [
                        'required'          => false,
                        'type'              => 'string',
                        'sanitize_callback' => 'sanitize_text_field',
                    ],
                    'reason' => [
                        'required'          => false,
                        'type'              => 'string',
                        'sanitize_callback' => 'sanitize_textarea_field',
                    ],
                ],
            ]
        );

        // Customer: Resume subscription
        register_rest_route(
            $this->namespace,
            '/my-subscriptions/(?P<id>\d+)/resume',
            [
                'methods'             => 'POST',
                'callback'            => [$this, 'resumeSubscription'],
                'permission_callback' => [$this, 'checkCustomerPermission'],
                'args'                => [
                    'id' => [
                        'required'          => true,
                        'type'              => 'integer',
                        'sanitize_callback' => 'absint',
                    ],
                ],
            ]
        );
    }

    /**
     * Check admin permission for pause management endpoints.
     *
     * @return bool
     */
    public function checkAdminPermission(): bool
    {
        return current_user_can('manage_woocommerce') || current_user_can('manage_options');
    }

    /**
     * Check customer permission
     *
     * Validates that the current user is logged in and owns the subscription.
     *
     * @param WP_REST_Request $request Request object.
     * @return bool|WP_Error True if has permission, WP_Error otherwise.
     */
    public function checkCustomerPermission(WP_REST_Request $request)
    {
        if (!is_user_logged_in()) {
            return new WP_Error(
                'not_logged_in',
                __('You must be logged in.', 'arraysubs'),
                ['status' => 401]
            );
        }

        $subscription_id = $request->get_param('id');
        $subscription = arraysubs_get_subscription($subscription_id);

        if (!$subscription instanceof \WP_Post) {
            return new WP_Error(
                'subscription_not_found',
                __('Subscription not found.', 'arraysubs'),
                ['status' => 404]
            );
        }

        $current_user_id = get_current_user_id();
        $customer_id = (int) get_post_meta($subscription_id, '_customer_id', true);

        if ($customer_id <= 0) {
            return new WP_Error(
                'invalid_subscription_owner',
                __('Invalid subscription ownership data.', 'arraysubs'),
                ['status' => 403]
            );
        }

        if ($current_user_id !== $customer_id) {
            return new WP_Error(
                'permission_denied',
                __('You do not have permission to manage this subscription.', 'arraysubs'),
                ['status' => 403]
            );
        }

        // Check if customer pause is enabled
        $customer_can_pause = arraysubs_get_setting('pause_subscription.customer_can_pause', true);
        if (!$customer_can_pause) {
            return new WP_Error(
                'pause_disabled',
                __('Pause subscription is not available for customers.', 'arraysubs'),
                ['status' => 403]
            );
        }

        return true;
    }

    /**
     * Get pause status for a subscription
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response
     */
    public function getPauseStatus(WP_REST_Request $request): WP_REST_Response
    {
        $subscription_id = $request->get_param('id');

        $subscription = get_post($subscription_id);
        if (!$subscription instanceof \WP_Post || $subscription->post_type !== 'arraysubs_data') {
            return arraysubs_rest_response(
                null,
                404,
                __('Subscription not found.', 'arraysubs')
            );
        }

        $status = $this->pause_manager->getPauseStatus($subscription_id);
        $can_pause = $this->pause_manager->canPause($subscription_id);

        // Flatten response for frontend
        $enabled = arraysubs_get_setting('pause_subscription.enabled', false);
        $max_duration = (int) arraysubs_get_setting('pause_subscription.max_duration_days', 90);
        $require_reason = (bool) arraysubs_get_setting('pause_subscription.require_reason', false);

        return arraysubs_rest_response([
            'subscription_id'    => $subscription_id,
            'enabled'            => (bool) $enabled,
            'is_paused'          => $status['is_paused'],
            'paused_date'        => $status['start_date'],
            'resume_date'        => $status['end_date'],
            'pause_duration'     => $status['duration_days'],
            'days_paused'        => $status['days_paused'],
            'days_remaining'     => $status['days_remaining'],
            'pause_count'        => $status['pause_count'],
            'pause_reason'       => $status['reason'],
            'can_pause'          => $can_pause['can_pause'],
            'max_duration_days'  => $max_duration,
            'require_reason'     => $require_reason,
            'cannot_pause_reason' => $can_pause['reason'],
        ]);
    }

    /**
     * Check if subscription can be paused
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response
     */
    public function canPause(WP_REST_Request $request): WP_REST_Response
    {
        $subscription_id = $request->get_param('id');

        $subscription = get_post($subscription_id);
        if (!$subscription instanceof \WP_Post || $subscription->post_type !== 'arraysubs_data') {
            return arraysubs_rest_response(
                null,
                404,
                __('Subscription not found.', 'arraysubs')
            );
        }

        $result = $this->pause_manager->canPause($subscription_id);

        return arraysubs_rest_response([
            'subscription_id' => $subscription_id,
            'can_pause'       => $result['can_pause'],
            'max_days'        => $result['max_duration_days'],
            'reason'          => $result['reason'],
        ]);
    }

    /**
     * Pause a subscription
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response
     */
    public function pauseSubscription(WP_REST_Request $request): WP_REST_Response
    {
        $subscription_id = $request->get_param('id');
        $days = $request->get_param('days');
        $resume_date_string = $request->get_param('resume_date');
        $reason = $request->get_param('reason') ?? '';

        $subscription = get_post($subscription_id);
        if (!$subscription instanceof \WP_Post || $subscription->post_type !== 'arraysubs_data') {
            return arraysubs_rest_response(
                null,
                404,
                __('Subscription not found.', 'arraysubs')
            );
        }

        // Check if can pause
        $can_pause = $this->pause_manager->canPause($subscription_id);
        if (!$can_pause['can_pause']) {
            return arraysubs_rest_response(
                null,
                400,
                $can_pause['reason']
            );
        }

        // Calculate pause duration
        $resume_date = null;
        $duration_days = absint($days);
        if (!empty($resume_date_string)) {
            $resume_date = strtotime($resume_date_string);
            if ($resume_date === false || $resume_date <= time()) {
                return arraysubs_rest_response(
                    null,
                    400,
                    __('Invalid resume date. Must be a future date.', 'arraysubs')
                );
            }
            $duration_days = max(1, (int) ceil(($resume_date - time()) / DAY_IN_SECONDS));
        } elseif (!empty($days)) {
            $resume_date = strtotime("+{$duration_days} days");
        } else {
            $duration_days = 1;
            $resume_date = strtotime('+1 day');
        }

        // Validate resume date against max days
        if ($resume_date && $can_pause['max_duration_days'] > 0) {
            $max_resume_date = strtotime("+{$can_pause['max_duration_days']} days");
            if ($resume_date > $max_resume_date) {
                return arraysubs_rest_response(
                    null,
                    400,
                    sprintf(
                        /* translators: %d: maximum number of days */
                        __('Pause duration exceeds maximum allowed (%d days).', 'arraysubs'),
                        $can_pause['max_duration_days']
                    )
                );
            }
        }

        $user_id = get_current_user_id();
        $result = $this->pause_manager->pause($subscription_id, $duration_days, $user_id, $reason);

        if (!$result) {
            return arraysubs_rest_response(
                null,
                500,
                __('Failed to pause subscription.', 'arraysubs')
            );
        }

        // Get updated status
        $status = $this->pause_manager->getPauseStatus($subscription_id);

        $message = $resume_date
            ? sprintf(
                /* translators: %s: resume date */
                __('Subscription paused. Will auto-resume on %s.', 'arraysubs'),
                arraysubs_format_timestamp_local($resume_date, get_option('date_format'))
            )
            : __('Subscription paused indefinitely.', 'arraysubs');

        return arraysubs_rest_response(
            [
                'subscription_id' => $subscription_id,
                'pause_status'    => $status,
            ],
            200,
            $message
        );
    }

    /**
     * Resume a paused subscription
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response
     */
    public function resumeSubscription(WP_REST_Request $request): WP_REST_Response
    {
        $subscription_id = $request->get_param('id');

        $subscription = get_post($subscription_id);
        if (!$subscription instanceof \WP_Post || $subscription->post_type !== 'arraysubs_data') {
            return arraysubs_rest_response(
                null,
                404,
                __('Subscription not found.', 'arraysubs')
            );
        }

        // Check if currently paused
        $status = $this->pause_manager->getPauseStatus($subscription_id);
        if (!$status['is_paused']) {
            return arraysubs_rest_response(
                null,
                400,
                __('Subscription is not paused.', 'arraysubs')
            );
        }

        $user_id = get_current_user_id();
        $result = $this->pause_manager->resume($subscription_id, $user_id);

        if (!$result) {
            return arraysubs_rest_response(
                null,
                500,
                __('Failed to resume subscription.', 'arraysubs')
            );
        }

        // Get updated status
        $new_status = $this->pause_manager->getPauseStatus($subscription_id);

        return arraysubs_rest_response(
            [
                'subscription_id' => $subscription_id,
                'pause_status'    => $new_status,
            ],
            200,
            __('Subscription resumed successfully.', 'arraysubs')
        );
    }

    /**
     * Get pause history for a subscription
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response
     */
    public function getPauseHistory(WP_REST_Request $request): WP_REST_Response
    {
        $subscription_id = $request->get_param('id');

        $subscription = get_post($subscription_id);
        if (!$subscription instanceof \WP_Post || $subscription->post_type !== 'arraysubs_data') {
            return arraysubs_rest_response(
                null,
                404,
                __('Subscription not found.', 'arraysubs')
            );
        }

        $history_json = get_post_meta($subscription_id, '_pause_history', true);
        $history = !empty($history_json) ? json_decode($history_json, true) : [];

        // Ensure it's an array
        if (!is_array($history)) {
            $history = [];
        }

        // Sort by start date descending (most recent first)
        usort($history, function ($a, $b) {
            return ($b['started_at'] ?? 0) - ($a['started_at'] ?? 0);
        });

        return arraysubs_rest_response([
            'subscription_id' => $subscription_id,
            'pause_count'     => count($history),
            'history'         => $history,
        ]);
    }
}
