<?php
/**
 * Coupon REST Controller
 *
 * Admin, vendor and public endpoints for managing discount coupons.
 *
 * Solo mode:  Admin manages all coupons (vendor_id = 0, platform-wide).
 * Marketplace: Admin manages platform coupons. Vendors manage their own coupons.
 *
 * @package WahraRentalsBookings
 * @since   2.3.0
 */

defined('ABSPATH') || exit;

/**
 * Class WAHRB_Coupon_Controller
 */
class WAHRB_Coupon_Controller extends WAHRB_REST_Controller {

    /**
     * Route base
     *
     * @var string
     */
    protected $rest_base = 'coupons';

    /**
     * Register routes
     */
    public function register_routes(): void {

        // ── Admin routes ──────────────────────────────────────────

        // List / Create coupons (admin sees all)
        register_rest_route($this->namespace, '/admin/' . $this->rest_base, [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [$this, 'get_admin_coupons'],
                'permission_callback' => [$this, 'check_admin_permission'],
            ],
            [
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => [$this, 'create_admin_coupon'],
                'permission_callback' => [$this, 'check_admin_permission'],
                'args'                => $this->get_coupon_create_args(),
            ],
        ]);

        // Single coupon (admin)
        register_rest_route($this->namespace, '/admin/' . $this->rest_base . '/(?P<id>[\d]+)', [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [$this, 'get_admin_coupon'],
                'permission_callback' => [$this, 'check_admin_permission'],
            ],
            [
                'methods'             => WP_REST_Server::EDITABLE,
                'callback'            => [$this, 'update_admin_coupon'],
                'permission_callback' => [$this, 'check_admin_permission'],
            ],
            [
                'methods'             => WP_REST_Server::DELETABLE,
                'callback'            => [$this, 'delete_admin_coupon'],
                'permission_callback' => [$this, 'check_admin_permission'],
            ],
        ]);

        // ── Vendor routes (Marketplace only) ──────────────────────

        // List / Create own coupons
        register_rest_route($this->namespace, '/vendor/' . $this->rest_base, [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [$this, 'get_vendor_coupons'],
                'permission_callback' => [$this, 'check_vendor_permission'],
            ],
            [
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => [$this, 'create_vendor_coupon'],
                'permission_callback' => [$this, 'check_vendor_permission'],
            ],
        ]);

        // Single coupon (vendor owns)
        register_rest_route($this->namespace, '/vendor/' . $this->rest_base . '/(?P<id>[\d]+)', [
            [
                'methods'             => WP_REST_Server::EDITABLE,
                'callback'            => [$this, 'update_vendor_coupon'],
                'permission_callback' => [$this, 'check_vendor_permission'],
            ],
            [
                'methods'             => WP_REST_Server::DELETABLE,
                'callback'            => [$this, 'delete_vendor_coupon'],
                'permission_callback' => [$this, 'check_vendor_permission'],
            ],
        ]);

        // ── Public routes ─────────────────────────────────────────

        // Validate coupon code (guests can validate during booking)
        register_rest_route($this->namespace, '/' . $this->rest_base . '/validate', [
            [
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => [$this, 'validate_coupon'],
                'permission_callback' => '__return_true',
                'args'                => [
                    'code' => [
                        'type'     => 'string',
                        'required' => true,
                    ],
                    'product_id' => [
                        'type'     => 'integer',
                        'required' => true,
                    ],
                    'subtotal' => [
                        'type'     => 'number',
                        'required' => true,
                    ],
                    'customer_email' => [
                        'type'    => 'string',
                        'default' => '',
                    ],
                ],
            ],
        ]);

        // Generate random code (admin/vendor utility)
        register_rest_route($this->namespace, '/' . $this->rest_base . '/generate-code', [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [$this, 'generate_code'],
                'permission_callback' => [$this, 'check_vendor_permission'],
            ],
        ]);
    }

    // ──────────────────────────────────────────────────────────────
    // Admin Callbacks
    // ──────────────────────────────────────────────────────────────

    /**
     * List all coupons (admin sees everything)
     *
     * @param WP_REST_Request $request Request
     * @return WP_REST_Response
     */
    public function get_admin_coupons($request) {
        $manager = WAHRB_Coupon_Manager::instance();

        $args = [];
        if ($request->has_param('vendor_id')) {
            $args['vendor_id'] = absint($request->get_param('vendor_id'));
        }
        if ($request->has_param('is_active')) {
            $args['is_active'] = (bool) $request->get_param('is_active');
        }

        return $this->success($manager->get_coupons($args));
    }

    /**
     * Get single coupon (admin)
     *
     * @param WP_REST_Request $request Request
     * @return WP_REST_Response|WP_Error
     */
    public function get_admin_coupon($request) {
        $coupon = WAHRB_Coupon_Manager::instance()->get_coupon(absint($request['id']));
        if (!$coupon) {
            return $this->error('not_found', __('Coupon not found.', 'wahra-rentals-bookings'), 404);
        }
        return $this->success($coupon);
    }

    /**
     * Create coupon (admin — platform-wide, vendor_id = 0)
     *
     * @param WP_REST_Request $request Request
     * @return WP_REST_Response|WP_Error
     */
    public function create_admin_coupon($request) {
        $data = $this->extract_coupon_data($request);
        $data['vendor_id'] = absint($request->get_param('vendor_id') ?? 0); // Admin can assign to vendor or 0 for platform
        $data['is_active'] = $request->get_param('is_active') ?? true;

        $coupon_id = WAHRB_Coupon_Manager::instance()->create_coupon($data);

        if (!$coupon_id) {
            return $this->error('create_failed', __('Failed to create coupon. Code may already exist.', 'wahra-rentals-bookings'), 400);
        }

        return $this->success([
            'coupon_id' => $coupon_id,
            'message'   => __('Coupon created.', 'wahra-rentals-bookings'),
        ], 201);
    }

    /**
     * Update coupon (admin)
     *
     * @param WP_REST_Request $request Request
     * @return WP_REST_Response|WP_Error
     */
    public function update_admin_coupon($request) {
        $manager = WAHRB_Coupon_Manager::instance();
        $coupon_id = absint($request['id']);

        if (!$manager->get_coupon($coupon_id)) {
            return $this->error('not_found', __('Coupon not found.', 'wahra-rentals-bookings'), 404);
        }

        $data = $this->extract_coupon_data($request);

        if ($request->has_param('vendor_id')) {
            $data['vendor_id'] = absint($request->get_param('vendor_id'));
        }
        if ($request->has_param('is_active')) {
            $data['is_active'] = (bool) $request->get_param('is_active');
        }

        $updated = $manager->update_coupon($coupon_id, $data);

        if (!$updated) {
            return $this->error('update_failed', __('Failed to update coupon.', 'wahra-rentals-bookings'), 400);
        }

        return $this->success(['message' => __('Coupon updated.', 'wahra-rentals-bookings')]);
    }

    /**
     * Delete coupon (admin)
     *
     * @param WP_REST_Request $request Request
     * @return WP_REST_Response|WP_Error
     */
    public function delete_admin_coupon($request) {
        $manager = WAHRB_Coupon_Manager::instance();
        $coupon_id = absint($request['id']);

        if (!$manager->get_coupon($coupon_id)) {
            return $this->error('not_found', __('Coupon not found.', 'wahra-rentals-bookings'), 404);
        }

        $manager->delete_coupon($coupon_id);

        return $this->success(['message' => __('Coupon deleted.', 'wahra-rentals-bookings')]);
    }

    // ──────────────────────────────────────────────────────────────
    // Vendor Callbacks (Marketplace mode)
    // ──────────────────────────────────────────────────────────────

    /**
     * List vendor's own coupons
     *
     * In Solo mode, the site owner sees platform coupons (vendor_id = 0).
     * In Marketplace mode, vendor sees own coupons only.
     *
     * @param WP_REST_Request $request Request
     * @return WP_REST_Response
     */
    public function get_vendor_coupons($request) {
        $manager = WAHRB_Coupon_Manager::instance();
        $vendor_id = get_current_user_id();

        if (!wahrb_is_dokan_active()) {
            // Solo mode: site owner sees all platform coupons
            $coupons = $manager->get_coupons(['vendor_id' => 0]);
        } else {
            // Marketplace: vendor sees only own coupons
            $coupons = $manager->get_coupons(['vendor_id' => $vendor_id]);
        }

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

    /**
     * Create vendor coupon
     *
     * Solo mode: creates platform-wide coupon (vendor_id = 0).
     * Marketplace: creates vendor-scoped coupon.
     *
     * @param WP_REST_Request $request Request
     * @return WP_REST_Response|WP_Error
     */
    public function create_vendor_coupon($request) {
        $data = $this->extract_coupon_data($request);

        if (!wahrb_is_dokan_active()) {
            // Solo mode: all coupons are platform-wide
            $data['vendor_id'] = 0;
        } else {
            // Marketplace: coupon belongs to this vendor
            $data['vendor_id'] = get_current_user_id();
        }

        $data['is_active'] = $request->get_param('is_active') ?? true;

        $coupon_id = WAHRB_Coupon_Manager::instance()->create_coupon($data);

        if (!$coupon_id) {
            return $this->error('create_failed', __('Failed to create coupon. Code may already exist.', 'wahra-rentals-bookings'), 400);
        }

        return $this->success([
            'coupon_id' => $coupon_id,
            'message'   => __('Coupon created.', 'wahra-rentals-bookings'),
        ], 201);
    }

    /**
     * Update vendor coupon (own only)
     *
     * @param WP_REST_Request $request Request
     * @return WP_REST_Response|WP_Error
     */
    public function update_vendor_coupon($request) {
        $manager = WAHRB_Coupon_Manager::instance();
        $coupon_id = absint($request['id']);
        $vendor_id = get_current_user_id();

        $coupon = $manager->get_coupon($coupon_id);
        if (!$coupon) {
            return $this->error('not_found', __('Coupon not found.', 'wahra-rentals-bookings'), 404);
        }

        // Ownership check
        if (wahrb_is_dokan_active()) {
            if ((int) $coupon['vendor_id'] !== $vendor_id) {
                return $this->error('forbidden', __('You can only edit your own coupons.', 'wahra-rentals-bookings'), 403);
            }
        } else {
            // Solo mode: only platform coupons (vendor_id = 0) are editable
            if ((int) $coupon['vendor_id'] !== 0) {
                return $this->error('forbidden', __('Coupon not found.', 'wahra-rentals-bookings'), 404);
            }
        }

        $data = $this->extract_coupon_data($request);
        if ($request->has_param('is_active')) {
            $data['is_active'] = (bool) $request->get_param('is_active');
        }

        $updated = $manager->update_coupon($coupon_id, $data);

        if (!$updated) {
            return $this->error('update_failed', __('Failed to update coupon.', 'wahra-rentals-bookings'), 400);
        }

        return $this->success(['message' => __('Coupon updated.', 'wahra-rentals-bookings')]);
    }

    /**
     * Delete vendor coupon (own only)
     *
     * @param WP_REST_Request $request Request
     * @return WP_REST_Response|WP_Error
     */
    public function delete_vendor_coupon($request) {
        $manager = WAHRB_Coupon_Manager::instance();
        $coupon_id = absint($request['id']);
        $vendor_id = get_current_user_id();

        $coupon = $manager->get_coupon($coupon_id);
        if (!$coupon) {
            return $this->error('not_found', __('Coupon not found.', 'wahra-rentals-bookings'), 404);
        }

        // Ownership check
        if (wahrb_is_dokan_active()) {
            if ((int) $coupon['vendor_id'] !== $vendor_id) {
                return $this->error('forbidden', __('You can only delete your own coupons.', 'wahra-rentals-bookings'), 403);
            }
        } else {
            if ((int) $coupon['vendor_id'] !== 0) {
                return $this->error('forbidden', __('Coupon not found.', 'wahra-rentals-bookings'), 404);
            }
        }

        $manager->delete_coupon($coupon_id);

        return $this->success(['message' => __('Coupon deleted.', 'wahra-rentals-bookings')]);
    }

    // ──────────────────────────────────────────────────────────────
    // Public Callbacks
    // ──────────────────────────────────────────────────────────────

    /**
     * Validate a coupon code (public, used during booking)
     *
     * @param WP_REST_Request $request Request
     * @return WP_REST_Response
     */
    public function validate_coupon($request) {
        $code           = sanitize_text_field($request->get_param('code'));
        $product_id     = absint($request->get_param('product_id'));
        $subtotal       = (float) $request->get_param('subtotal');
        $customer_email = sanitize_email($request->get_param('customer_email'));

        $manager = WAHRB_Coupon_Manager::instance();
        $result  = $manager->validate_coupon($code, $product_id, $subtotal, $customer_email);

        if (!$result['valid']) {
            return $this->success([
                'valid'   => false,
                'message' => $result['error'],
            ]);
        }

        // Calculate preview discount
        $discount = $manager->calculate_discount($result['coupon'], $subtotal);

        return $this->success([
            'valid'            => true,
            'discount_type'    => $result['coupon']['discount_type'],
            'discount_value'   => $result['coupon']['discount_value'],
            'discount_amount'  => $discount,
            'new_total'        => max(0, $subtotal - $discount),
            'formatted_discount' => wc_price($discount),
            'message'          => __('Coupon applied successfully!', 'wahra-rentals-bookings'),
        ]);
    }

    /**
     * Generate random coupon code
     *
     * @param WP_REST_Request $request Request
     * @return WP_REST_Response
     */
    public function generate_code($request) {
        $prefix = sanitize_text_field($request->get_param('prefix') ?? '');
        $length = absint($request->get_param('length') ?? 8);
        $length = max(4, min(16, $length));

        return $this->success([
            'code' => WAHRB_Coupon_Manager::generate_code($length, $prefix),
        ]);
    }

    // ──────────────────────────────────────────────────────────────
    // Helpers
    // ──────────────────────────────────────────────────────────────

    /**
     * Extract coupon data from request
     *
     * @param WP_REST_Request $request Request
     * @return array
     */
    private function extract_coupon_data(WP_REST_Request $request): array {
        $data = [];

        $simple_fields = [
            'code', 'description', 'discount_type',
            'valid_from', 'valid_until',
        ];
        foreach ($simple_fields as $f) {
            if ($request->has_param($f)) {
                $data[$f] = $request->get_param($f);
            }
        }

        $numeric_fields = [
            'discount_value', 'min_order_amount', 'max_discount_amount',
            'usage_limit', 'per_user_limit',
        ];
        foreach ($numeric_fields as $f) {
            if ($request->has_param($f)) {
                $data[$f] = $request->get_param($f);
            }
        }

        if ($request->has_param('category_slugs')) {
            $data['category_slugs'] = $request->get_param('category_slugs');
        }
        if ($request->has_param('product_ids')) {
            $data['product_ids'] = $request->get_param('product_ids');
        }

        return $data;
    }

    /**
     * Get create args
     *
     * @return array
     */
    private function get_coupon_create_args(): array {
        return [
            'code' => [
                'type'     => 'string',
                'required' => true,
            ],
            'description' => [
                'type'    => 'string',
                'default' => '',
            ],
            'discount_type' => [
                'type'    => 'string',
                'default' => 'percent',
                'enum'    => ['percent', 'fixed'],
            ],
            'discount_value' => [
                'type'     => 'number',
                'required' => true,
            ],
            'min_order_amount' => [
                'type'    => 'number',
                'default' => 0,
            ],
            'max_discount_amount' => [
                'type'    => 'number',
                'default' => 0,
            ],
            'usage_limit' => [
                'type'    => 'integer',
                'default' => 0,
            ],
            'per_user_limit' => [
                'type'    => 'integer',
                'default' => 0,
            ],
            'valid_from' => [
                'type'    => 'string',
                'default' => '',
            ],
            'valid_until' => [
                'type'    => 'string',
                'default' => '',
            ],
            'category_slugs' => [
                'type'    => 'array',
                'default' => [],
            ],
            'product_ids' => [
                'type'    => 'array',
                'default' => [],
            ],
            'is_active' => [
                'type'    => 'boolean',
                'default' => true,
            ],
        ];
    }
}
