<?php
/**
 * Arag_Shop_Controller — فروشگاه عرقیات
 *
 * GET  /public/arag/families
 * GET  /public/arag/families/{id}/variants
 * GET  /public/arag/variants/{id}/packages
 * POST /public/arag/auth/send-otp
 * POST /public/arag/auth/verify-otp
 * GET  /public/arag/payment-methods
 * POST /public/arag/orders/create
 * GET  /public/arag/orders/verify
 * GET  /public/arag/account/dashboard     (JWT)
 * GET  /public/arag/account/orders        (JWT)
 * PUT  /public/arag/account/profile       (JWT)
 */

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

require_once ACC_PATH . 'includes/helpers/arag-shop.php';
require_once ACC_PATH . 'includes/helpers/acc-sms.php';
require_once ACC_PATH . 'includes/helpers/arag-shop-ai.php';
require_once ACC_PATH . 'includes/helpers/sr-zarinpal.php';
require_once ACC_PATH . 'includes/helpers/arag-mizaj.php';
require_once ACC_PATH . 'includes/helpers/arag-referral.php';
require_once ACC_PATH . 'includes/helpers/acc-shop-platform.php';
require_once ACC_PATH . 'includes/helpers/arag-marketer.php';

class Arag_Shop_Controller {

    const ZP_MERCHANT = '1344b5d4-0048-11e8-94db-005056a205be';
    const ZP_REQUEST  = 'https://sandbox.zarinpal.com/pg/v4/payment/request.json';
    const ZP_VERIFY   = 'https://sandbox.zarinpal.com/pg/v4/payment/verify.json';
    const ZP_STARTPAY = 'https://sandbox.zarinpal.com/pg/StartPay/';

    public static function register_routes(): void {
        $ns = 'acc/v1';
        $jwt = 'acc_jwt_check_permission';

        register_rest_route( $ns, '/public/arag/families', [
            'methods' => 'GET', 'callback' => [ self::class, 'get_families' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/families/(?P<id>\d+)/variants', [
            'methods' => 'GET', 'callback' => [ self::class, 'get_variants' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/variants/(?P<id>\d+)/packages', [
            'methods' => 'GET', 'callback' => [ self::class, 'get_packages' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/auth/send-otp', [
            'methods' => 'POST', 'callback' => [ self::class, 'send_otp' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/auth/verify-otp', [
            'methods' => 'POST', 'callback' => [ self::class, 'verify_otp' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/payment-methods', [
            'methods' => 'GET', 'callback' => [ self::class, 'payment_methods' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/orders/create', [
            'methods' => 'POST', 'callback' => [ self::class, 'create_order' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/orders/verify', [
            'methods' => 'GET', 'callback' => [ self::class, 'verify_payment' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/orders/simulate-pay', [
            'methods' => 'GET', 'callback' => [ self::class, 'simulate_pay' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/orders/(?P<id>\d+)/receipt', [
            'methods' => 'GET', 'callback' => [ self::class, 'order_receipt' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/orders/track', [
            'methods' => 'GET', 'callback' => [ self::class, 'track_order' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/coupons/check', [
            'methods' => 'GET', 'callback' => [ self::class, 'check_coupon' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/cart', [
            [ 'methods' => 'GET',  'callback' => [ self::class, 'get_cart' ], 'permission_callback' => '__return_true' ],
            [ 'methods' => 'PUT',  'callback' => [ self::class, 'put_cart' ], 'permission_callback' => '__return_true' ],
            [ 'methods' => 'DELETE', 'callback' => [ self::class, 'clear_cart' ], 'permission_callback' => '__return_true' ],
        ] );
        register_rest_route( $ns, '/public/arag/account/dashboard', [
            'methods' => 'GET', 'callback' => [ self::class, 'account_dashboard' ],
            'permission_callback' => $jwt,
        ] );
        register_rest_route( $ns, '/public/arag/account/orders', [
            'methods' => 'GET', 'callback' => [ self::class, 'account_orders' ],
            'permission_callback' => $jwt,
        ] );
        register_rest_route( $ns, '/public/arag/account/profile', [
            'methods' => 'PUT', 'callback' => [ self::class, 'update_profile' ],
            'permission_callback' => $jwt,
        ] );

        register_rest_route( $ns, '/public/arag/shop/settings', [
            'methods' => 'GET', 'callback' => [ self::class, 'get_shop_settings' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/families/(?P<id>\d+)', [
            'methods' => 'GET', 'callback' => [ self::class, 'get_family_detail' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/families/slug/(?P<slug>[a-z0-9\-]+)', [
            'methods' => 'GET', 'callback' => [ self::class, 'get_family_by_slug' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/families/(?P<id>\d+)/reviews', [
            [ 'methods' => 'GET',  'callback' => [ self::class, 'get_reviews' ], 'permission_callback' => '__return_true' ],
            [ 'methods' => 'POST', 'callback' => [ self::class, 'post_review' ], 'permission_callback' => '__return_true' ],
        ] );

        register_rest_route( $ns, '/arag/admin/products', [
            'methods' => 'GET', 'callback' => [ self::class, 'admin_products' ],
            'permission_callback' => [ self::class, 'admin_perm' ],
        ] );
        register_rest_route( $ns, '/arag/admin/products/(?P<id>\d+)', [
            'methods' => 'PUT', 'callback' => [ self::class, 'admin_update_product' ],
            'permission_callback' => [ self::class, 'admin_perm' ],
        ] );
        register_rest_route( $ns, '/arag/admin/settings', [
            [ 'methods' => 'GET', 'callback' => [ self::class, 'admin_get_settings' ], 'permission_callback' => [ self::class, 'admin_perm' ] ],
            [ 'methods' => 'PUT', 'callback' => [ self::class, 'admin_save_settings' ], 'permission_callback' => [ self::class, 'admin_perm' ] ],
        ] );
        register_rest_route( $ns, '/arag/admin/upload', [
            'methods' => 'POST', 'callback' => [ self::class, 'admin_upload' ],
            'permission_callback' => [ self::class, 'admin_perm' ],
        ] );
        register_rest_route( $ns, '/arag/admin/families/(?P<family_id>\d+)/catalog', [
            'methods' => 'GET', 'callback' => [ self::class, 'admin_catalog' ],
            'permission_callback' => [ self::class, 'admin_perm' ],
        ] );
        register_rest_route( $ns, '/arag/admin/variants', [
            'methods' => 'POST', 'callback' => [ self::class, 'admin_create_variant' ],
            'permission_callback' => [ self::class, 'admin_perm' ],
        ] );
        register_rest_route( $ns, '/arag/admin/variants/(?P<id>\d+)', [
            [ 'methods' => 'PUT',    'callback' => [ self::class, 'admin_update_variant' ], 'permission_callback' => [ self::class, 'admin_perm' ] ],
            [ 'methods' => 'DELETE', 'callback' => [ self::class, 'admin_delete_variant' ], 'permission_callback' => [ self::class, 'admin_perm' ] ],
        ] );
        register_rest_route( $ns, '/arag/admin/packages', [
            'methods' => 'POST', 'callback' => [ self::class, 'admin_create_package' ],
            'permission_callback' => [ self::class, 'admin_perm' ],
        ] );
        register_rest_route( $ns, '/arag/admin/packages/(?P<id>\d+)', [
            [ 'methods' => 'PUT',    'callback' => [ self::class, 'admin_update_package' ], 'permission_callback' => [ self::class, 'admin_perm' ] ],
            [ 'methods' => 'DELETE', 'callback' => [ self::class, 'admin_delete_package' ], 'permission_callback' => [ self::class, 'admin_perm' ] ],
        ] );
        register_rest_route( $ns, '/arag/admin/coupons', [
            [ 'methods' => 'GET',  'callback' => [ self::class, 'admin_coupons' ], 'permission_callback' => [ self::class, 'admin_perm' ] ],
            [ 'methods' => 'POST', 'callback' => [ self::class, 'admin_create_coupon' ], 'permission_callback' => [ self::class, 'admin_perm' ] ],
        ] );
        register_rest_route( $ns, '/arag/admin/coupons/(?P<id>\d+)', [
            [ 'methods' => 'PUT',    'callback' => [ self::class, 'admin_update_coupon' ], 'permission_callback' => [ self::class, 'admin_perm' ] ],
            [ 'methods' => 'DELETE', 'callback' => [ self::class, 'admin_delete_coupon' ], 'permission_callback' => [ self::class, 'admin_perm' ] ],
        ] );
        register_rest_route( $ns, '/arag/admin/reviews', [
            'methods' => 'GET', 'callback' => [ self::class, 'admin_reviews' ],
            'permission_callback' => [ self::class, 'admin_perm' ],
        ] );
        register_rest_route( $ns, '/arag/admin/reviews/(?P<id>\d+)/moderate', [
            'methods' => 'POST', 'callback' => [ self::class, 'admin_moderate_review' ],
            'permission_callback' => [ self::class, 'admin_perm' ],
        ] );
        register_rest_route( $ns, '/public/arag/ai/chat', [
            'methods' => 'POST', 'callback' => [ self::class, 'ai_chat' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/ai/status', [
            'methods' => 'GET', 'callback' => [ self::class, 'ai_status' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/arag/admin/integrations', [
            [ 'methods' => 'GET', 'callback' => [ self::class, 'admin_get_integrations' ], 'permission_callback' => [ self::class, 'admin_perm' ] ],
            [ 'methods' => 'PUT', 'callback' => [ self::class, 'admin_save_integrations' ], 'permission_callback' => [ self::class, 'admin_perm' ] ],
        ] );
        register_rest_route( $ns, '/public/arag/mizaj/questions', [
            'methods' => 'GET', 'callback' => [ self::class, 'mizaj_questions' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/mizaj/submit', [
            'methods' => 'POST', 'callback' => [ self::class, 'mizaj_submit' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/mizaj/result/(?P<session>[a-zA-Z0-9_-]+)', [
            'methods' => 'GET', 'callback' => [ self::class, 'mizaj_result' ],
            'permission_callback' => '__return_true',
        ] );
        register_rest_route( $ns, '/public/arag/referral', [
            [ 'methods' => 'GET',  'callback' => [ self::class, 'referral_get' ], 'permission_callback' => '__return_true' ],
            [ 'methods' => 'POST', 'callback' => [ self::class, 'referral_create' ], 'permission_callback' => '__return_true' ],
        ] );
        register_rest_route( $ns, '/public/arag/subscribe', [
            'methods' => 'POST', 'callback' => [ self::class, 'subscribe_plan' ],
            'permission_callback' => '__return_true',
        ] );

        require_once ACC_PATH . 'includes/controllers/Platform_Shop_Controller.php';
        Platform_Shop_Controller::register_routes();
    }

    private static function _fire_webhook( string $event, int $order_id ): void {
        if ( ! class_exists( 'Acc_Shop_Platform' ) ) {
            return;
        }
        $payload = Acc_Shop_Platform::order_payload( $order_id );
        if ( $payload ) {
            Acc_Shop_Platform::dispatch_webhook( $event, $payload );
        }
    }

    public static function admin_perm(): bool {
        return Arag_Shop::admin_can();
    }

    /* ── Families ── */
    public static function get_families( WP_REST_Request $req ): WP_REST_Response {
        return new WP_REST_Response( [ 'data' => Arag_Shop::list_families_public() ] );
    }

    public static function get_shop_settings( WP_REST_Request $req ): WP_REST_Response {
        return new WP_REST_Response( [ 'success' => true, 'data' => Arag_Shop::get_settings() ] );
    }

    public static function get_family_detail( WP_REST_Request $req ): WP_REST_Response {
        $id  = (int) $req->get_param( 'id' );
        $pdp = Arag_Shop::get_family_by_id( $id );
        if ( ! $pdp ) {
            return new WP_REST_Response( [ 'message' => 'یافت نشد' ], 404 );
        }
        return new WP_REST_Response( [ 'success' => true, 'data' => $pdp ] );
    }

    public static function get_family_by_slug( WP_REST_Request $req ): WP_REST_Response {
        $slug = sanitize_title( (string) $req->get_param( 'slug' ) );
        $pdp  = Arag_Shop::get_family_by_slug( $slug );
        if ( ! $pdp ) {
            return new WP_REST_Response( [ 'message' => 'یافت نشد' ], 404 );
        }
        return new WP_REST_Response( [ 'success' => true, 'data' => $pdp ] );
    }

    public static function get_reviews( WP_REST_Request $req ): WP_REST_Response {
        $id = (int) $req->get_param( 'id' );
        return new WP_REST_Response( [
            'success' => true,
            'data'    => Arag_Shop::list_reviews( $id, 50 ),
            'rating'  => Arag_Shop::avg_rating( $id ),
        ] );
    }

    public static function post_review( WP_REST_Request $req ): WP_REST_Response {
        $id   = (int) $req->get_param( 'id' );
        $body = $req->get_json_params() ?: [];
        $res  = Arag_Shop::add_review( $id, $body );
        if ( empty( $res['ok'] ) ) {
            return new WP_REST_Response( [
                'success' => false,
                'message' => $res['message'] ?? 'ثبت نظر انجام نشد',
                'pending' => ! empty( $res['pending'] ),
            ], 400 );
        }
        return new WP_REST_Response( [
            'success' => true,
            'data'    => $res['data'],
            'pending' => ! empty( $res['pending'] ),
            'message' => $res['message'] ?? '',
        ], 201 );
    }

    public static function admin_products( WP_REST_Request $req ): WP_REST_Response {
        return new WP_REST_Response( [
            'success'  => true,
            'data'     => Arag_Shop::admin_list_families(),
            'settings' => Arag_Shop::get_settings(),
        ] );
    }

    public static function admin_update_product( WP_REST_Request $req ): WP_REST_Response {
        $id   = (int) $req->get_param( 'id' );
        $body = $req->get_json_params() ?: [];
        Arag_Shop::admin_update_family( $id, $body );
        $pdp = Arag_Shop::get_family_by_id( $id );
        return new WP_REST_Response( [ 'success' => true, 'data' => $pdp ] );
    }

    public static function admin_get_settings( WP_REST_Request $req ): WP_REST_Response {
        return new WP_REST_Response( [ 'success' => true, 'data' => Arag_Shop::get_settings() ] );
    }

    public static function admin_save_settings( WP_REST_Request $req ): WP_REST_Response {
        $body = $req->get_json_params() ?: [];
        return new WP_REST_Response( [
            'success' => true,
            'data'    => Arag_Shop::save_settings( $body ),
        ] );
    }

    public static function admin_upload( WP_REST_Request $req ): WP_REST_Response {
        $files = $req->get_file_params();
        $file  = $files['file'] ?? $files['image'] ?? null;
        if ( ! $file || empty( $file['tmp_name'] ) ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'فایل ارسال نشد' ], 400 );
        }
        $result = Arag_Shop::handle_upload( $file );
        if ( ! $result ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'فرمت فایل مجاز نیست' ], 400 );
        }
        return new WP_REST_Response( [ 'success' => true, 'data' => $result ] );
    }

    public static function admin_catalog( WP_REST_Request $req ): WP_REST_Response {
        $fid = (int) $req->get_param( 'family_id' );
        return new WP_REST_Response( [
            'success' => true,
            'data'    => Arag_Shop::admin_get_catalog( $fid ),
        ] );
    }

    public static function admin_create_variant( WP_REST_Request $req ): WP_REST_Response {
        $body = $req->get_json_params() ?: [];
        $fid  = (int) ( $body['family_id'] ?? 0 );
        if ( $fid <= 0 ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'family_id الزامی است' ], 400 );
        }
        return new WP_REST_Response( [
            'success' => true,
            'data'    => Arag_Shop::admin_save_variant( $fid, $body ),
        ], 201 );
    }

    public static function admin_update_variant( WP_REST_Request $req ): WP_REST_Response {
        $id   = (int) $req->get_param( 'id' );
        $body = $req->get_json_params() ?: [];
        global $wpdb;
        $fid = (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT family_id FROM {$wpdb->prefix}arag_variants WHERE id = %d", $id
        ) );
        return new WP_REST_Response( [
            'success' => true,
            'data'    => Arag_Shop::admin_save_variant( $fid, $body, $id ),
        ] );
    }

    public static function admin_delete_variant( WP_REST_Request $req ): WP_REST_Response {
        $id = (int) $req->get_param( 'id' );
        return new WP_REST_Response( [ 'success' => Arag_Shop::admin_delete_variant( $id ) ] );
    }

    public static function admin_create_package( WP_REST_Request $req ): WP_REST_Response {
        $body = $req->get_json_params() ?: [];
        $vid  = (int) ( $body['variant_id'] ?? 0 );
        if ( $vid <= 0 ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'variant_id الزامی است' ], 400 );
        }
        return new WP_REST_Response( [
            'success' => true,
            'data'    => Arag_Shop::admin_save_package( $vid, $body ),
        ], 201 );
    }

    public static function admin_update_package( WP_REST_Request $req ): WP_REST_Response {
        $id   = (int) $req->get_param( 'id' );
        $body = $req->get_json_params() ?: [];
        global $wpdb;
        $vid = (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT variant_id FROM {$wpdb->prefix}arag_packages WHERE id = %d", $id
        ) );
        return new WP_REST_Response( [
            'success' => true,
            'data'    => Arag_Shop::admin_save_package( $vid, $body, $id ),
        ] );
    }

    public static function admin_delete_package( WP_REST_Request $req ): WP_REST_Response {
        $id = (int) $req->get_param( 'id' );
        return new WP_REST_Response( [ 'success' => Arag_Shop::admin_delete_package( $id ) ] );
    }

    public static function admin_coupons( WP_REST_Request $req ): WP_REST_Response {
        return new WP_REST_Response( [ 'success' => true, 'data' => Arag_Shop::admin_list_coupons() ] );
    }

    public static function admin_create_coupon( WP_REST_Request $req ): WP_REST_Response {
        $body = $req->get_json_params() ?: [];
        return new WP_REST_Response( [
            'success' => true,
            'data'    => Arag_Shop::admin_save_coupon( $body ),
        ], 201 );
    }

    public static function admin_update_coupon( WP_REST_Request $req ): WP_REST_Response {
        $id   = (int) $req->get_param( 'id' );
        $body = $req->get_json_params() ?: [];
        return new WP_REST_Response( [
            'success' => true,
            'data'    => Arag_Shop::admin_save_coupon( $body, $id ),
        ] );
    }

    public static function admin_delete_coupon( WP_REST_Request $req ): WP_REST_Response {
        $id = (int) $req->get_param( 'id' );
        return new WP_REST_Response( [ 'success' => Arag_Shop::admin_delete_coupon( $id ) ] );
    }

    public static function admin_reviews( WP_REST_Request $req ): WP_REST_Response {
        $status = sanitize_key( $req->get_param( 'status' ) ?? 'pending' );
        return new WP_REST_Response( [
            'success' => true,
            'data'    => Arag_Shop::admin_list_reviews( $status ),
        ] );
    }

    public static function admin_moderate_review( WP_REST_Request $req ): WP_REST_Response {
        $id      = (int) $req->get_param( 'id' );
        $body    = $req->get_json_params() ?: [];
        $approve = ! empty( $body['approve'] );
        return new WP_REST_Response( [
            'success' => Arag_Shop::admin_moderate_review( $id, $approve ),
        ] );
    }

    public static function get_cart( WP_REST_Request $req ): WP_REST_Response {
        [ $session, $user_id ] = self::_cart_context( $req );
        $items = Arag_Shop::get_cart( $session, $user_id );
        return new WP_REST_Response( [
            'success'      => true,
            'data'         => $items,
            'session_key'  => $session,
        ] );
    }

    public static function put_cart( WP_REST_Request $req ): WP_REST_Response {
        [ $session, $user_id ] = self::_cart_context( $req );
        $items = $req->get_param( 'items' );
        if ( ! is_array( $items ) ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'items الزامی است' ], 400 );
        }
        $saved = Arag_Shop::save_cart( $session, $items, $user_id );
        return new WP_REST_Response( [
            'success'     => true,
            'data'        => $saved,
            'session_key' => $session,
        ] );
    }

    public static function clear_cart( WP_REST_Request $req ): WP_REST_Response {
        [ $session, $user_id ] = self::_cart_context( $req );
        Arag_Shop::clear_cart( $session, $user_id );
        return new WP_REST_Response( [ 'success' => true ] );
    }

    private static function _cart_context( WP_REST_Request $req ): array {
        $session = sanitize_text_field( $req->get_header( 'X-Cart-Session' ) ?: $req->get_param( 'session_key' ) ?: '' );
        if ( ! $session ) {
            $session = Arag_Shop::cart_session_key();
        }
        $user_id = 0;
        if ( function_exists( '_acc_jwt_user_id_from_request' ) ) {
            $user_id = _acc_jwt_user_id_from_request();
        }
        return [ $session, $user_id ];
    }

    public static function get_variants( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $family_id = (int) $req->get_param('id');
        $family = $wpdb->get_row(
            "SELECT id, name, icon FROM {$wpdb->prefix}arag_families WHERE id = {$family_id} AND is_active = 1"
        );
        if ( ! $family ) {
            return new WP_REST_Response( [ 'message' => 'یافت نشد' ], 404 );
        }
        $variants = $wpdb->get_results(
            "SELECT id, family_id, name, slug, description, sort_order
             FROM {$wpdb->prefix}arag_variants
             WHERE family_id = {$family_id} AND is_active = 1
             ORDER BY sort_order ASC, name ASC"
        );
        return new WP_REST_Response( [ 'family' => $family, 'data' => $variants ?: [] ] );
    }

    public static function get_packages( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $variant_id = (int) $req->get_param('id');
        $variant = $wpdb->get_row(
            "SELECT v.*, f.name AS family_name, f.icon AS family_icon
             FROM {$wpdb->prefix}arag_variants v
             INNER JOIN {$wpdb->prefix}arag_families f ON f.id = v.family_id
             WHERE v.id = {$variant_id} AND v.is_active = 1"
        );
        if ( ! $variant ) {
            return new WP_REST_Response( [ 'message' => 'یافت نشد' ], 404 );
        }
        $packages = $wpdb->get_results(
            "SELECT id, variant_id, label, volume, price, sort_order
             FROM {$wpdb->prefix}arag_packages
             WHERE variant_id = {$variant_id} AND is_active = 1
             ORDER BY sort_order ASC, price ASC"
        );
        return new WP_REST_Response( [ 'variant' => $variant, 'data' => $packages ?: [] ] );
    }

    /* ── OTP Auth ── */
    public static function send_otp( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $phone = self::_normalize_phone( $req->get_param('phone') ?? '' );
        if ( ! $phone ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'شماره موبایل معتبر نیست' ], 400 );
        }

        if ( function_exists( 'acc_rate_limit' ) ) {
            $ip = function_exists( 'acc_client_ip' ) ? acc_client_ip() : ( $_SERVER['REMOTE_ADDR'] ?? '0' );
            if ( ! acc_rate_limit( 'otp_ip_' . $ip, 20, 3600 ) ) {
                return new WP_REST_Response( [ 'success' => false, 'message' => 'تعداد درخواست از این IP زیاد است' ], 429 );
            }
            if ( ! acc_rate_limit( 'otp_phone_' . $phone, 5, 900 ) ) {
                return new WP_REST_Response( [ 'success' => false, 'message' => 'تعداد ارسال کد برای این شماره زیاد است' ], 429 );
            }
        }

        $code = (string) random_int( 100000, 999999 );
        $expires = date( 'Y-m-d H:i:s', time() + 300 );

        $wpdb->insert( "{$wpdb->prefix}shop_otp", [
            'phone'      => $phone,
            'code'       => $code,
            'expires_at' => $expires,
            'verified'   => 0,
        ] );

        // demo_code فقط روی لوکال — هرگز در production برنگردان
        $demo = function_exists( 'acc_is_local_environment' )
            && acc_is_local_environment()
            && get_option( 'acc_shop_otp_demo', '1' ) === '1';
        $resp = [
            'success'    => true,
            'message'    => 'کد تأیید ارسال شد.',
            'expires_in' => 300,
        ];

        if ( $demo ) {
            $resp['demo_code'] = $code;
            $resp['sms_mode']  = 'demo';
        } else {
            $sms = Acc_SMS::send_otp( $phone, $code );
            if ( empty( $sms['success'] ) ) {
                return new WP_REST_Response( [
                    'success' => false,
                    'message' => $sms['message'] ?? 'ارسال پیامک ناموفق بود',
                ], 502 );
            }
            $resp['sms_mode'] = $sms['provider'] ?? 'sms';
        }

        return new WP_REST_Response( $resp );
    }

    public static function verify_otp( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $phone = self::_normalize_phone( $req->get_param('phone') ?? '' );
        $code  = sanitize_text_field( $req->get_param('code') ?? '' );

        if ( ! $phone || ! $code ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'شماره و کد الزامی است' ], 400 );
        }

        if ( function_exists( 'acc_rate_limit' ) ) {
            $ip = function_exists( 'acc_client_ip' ) ? acc_client_ip() : ( $_SERVER['REMOTE_ADDR'] ?? '0' );
            if ( ! acc_rate_limit( 'otp_verify_ip_' . $ip, 40, 3600 ) ) {
                return new WP_REST_Response( [ 'success' => false, 'message' => 'تعداد تلاش ورود زیاد است' ], 429 );
            }
            if ( ! acc_rate_limit( 'otp_verify_phone_' . $phone, 12, 900 ) ) {
                return new WP_REST_Response( [ 'success' => false, 'message' => 'تعداد تلاش برای این شماره زیاد است' ], 429 );
            }
        }

        $row = $wpdb->get_row(
            $wpdb->prepare(
                "SELECT * FROM {$wpdb->prefix}shop_otp
                 WHERE phone = %s AND code = %s AND verified = 0 AND expires_at > NOW()
                 ORDER BY id DESC LIMIT 1",
                $phone, $code
            )
        );

        if ( ! $row ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'کد نامعتبر یا منقضی شده' ], 401 );
        }

        $wpdb->update( "{$wpdb->prefix}shop_otp", [ 'verified' => 1 ], [ 'id' => (int) $row->id ] );

        $user = self::_get_or_create_customer( $phone );
        if ( is_wp_error( $user ) ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => $user->get_error_message() ], 500 );
        }

        if ( ! function_exists( 'acc_jwt_generate_token' ) ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'JWT در دسترس نیست' ], 500 );
        }

        $token = acc_jwt_generate_token( $user, false );

        $session = sanitize_text_field( $req->get_param( 'session_key' ) ?? $req->get_header( 'X-Cart-Session' ) ?? '' );
        if ( $session ) {
            Arag_Shop::merge_cart_on_login( $session, (int) $user->ID );
        }

        return new WP_REST_Response( [
            'success' => true,
            'token'   => $token,
            'user'    => self::_format_user( $user ),
        ] );
    }

    /* ── Payment methods (شبیه وردپرس/WC) ── */
    public static function payment_methods( WP_REST_Request $req ): WP_REST_Response {
        $methods = [];
        if ( SR_Zarinpal::is_sandbox() ) {
            $methods[] = [
                'id'    => 'demo',
                'title' => 'پرداخت آزمایشی (Sandbox)',
                'icon'  => '🧪',
                'desc'  => 'بدون درگاه واقعی — فوری پرداخت‌شده (مناسب تست localhost)',
            ];
        }
        $methods[] = [ 'id' => 'zarinpal', 'title' => 'پرداخت آنلاین (زرین‌پال)', 'icon' => '💳', 'desc' => 'پرداخت امن با کارت بانکی' ];
        $methods[] = [ 'id' => 'cod',      'title' => 'پرداخت در محل',           'icon' => '🏠', 'desc' => 'پرداخت هنگام تحویل سفارش' ];
        $methods[] = [ 'id' => 'bank',     'title' => 'کارت به کارت',            'icon' => '🏦', 'desc' => 'واریز به شماره حساب و ارسال رسید' ];

        return new WP_REST_Response( [
            'data'     => $methods,
            'sandbox'  => SR_Zarinpal::is_sandbox(),
            'shipping' => [
                [ 'id' => 'post',   'title' => 'پست پیشتاز',  'icon' => '📮', 'cod' => true,  'desc' => 'ارسال با پست — کرایه پس‌پرداخت' ],
                [ 'id' => 'tipax',  'title' => 'تیپاکس',      'icon' => '🚚', 'cod' => true,  'desc' => 'ارسال با تیپاکس — کرایه پس‌پرداخت' ],
                [ 'id' => 'pickup', 'title' => 'تحویل حضوری', 'icon' => '🏪', 'cod' => false, 'desc' => 'دریافت از فروشگاه' ],
            ],
        ] );
    }

    /* ── Create order ── */
    public static function create_order( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;

        $items           = $req->get_param('items');
        $billing         = (array) ( $req->get_param('billing') ?? [] );
        $shipping_method = sanitize_key( $req->get_param('shipping_method') ?? 'post' );
        $payment_method  = sanitize_key( $req->get_param('payment_method') ?? 'zarinpal' );
        $note            = sanitize_textarea_field( $req->get_param('note') ?? '' );
        $user_id         = (int) ( $req->get_param('user_id') ?? 0 );
        $coupon_code     = strtoupper( sanitize_text_field( $req->get_param('coupon_code') ?? '' ) );
        $sold_by_marketer_id = (int) ( $req->get_param( 'sold_by_marketer_id' ) ?? 0 );

        if ( $user_id <= 0 && function_exists( '_acc_jwt_user_id_from_request' ) ) {
            $jwt_uid = _acc_jwt_user_id_from_request();
            if ( $jwt_uid > 0 ) $user_id = $jwt_uid;
        }

        if ( empty( $items ) || ! is_array( $items ) ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'سبد خرید خالی است' ], 400 );
        }

        $phone = self::_normalize_phone( $billing['phone'] ?? '' );
        $name  = sanitize_text_field( $billing['name'] ?? '' );
        if ( ! $phone ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'شماره موبایل الزامی است' ], 400 );
        }

        if ( ! in_array( $shipping_method, [ 'post', 'tipax', 'pickup' ], true ) ) {
            $shipping_method = 'post';
        }
        if ( ! in_array( $payment_method, [ 'zarinpal', 'cod', 'bank', 'demo' ], true ) ) {
            $payment_method = SR_Zarinpal::is_sandbox() ? 'demo' : 'zarinpal';
        }
        if ( $payment_method === 'demo' && ! SR_Zarinpal::is_sandbox() ) {
            $payment_method = 'zarinpal';
        }

        $line_items = [];
        $subtotal   = 0;

        foreach ( $items as $item ) {
            $pkg_id = (int) ( $item['package_id'] ?? 0 );
            $qty    = max( 1, (int) ( $item['qty'] ?? 1 ) );
            if ( $pkg_id <= 0 ) continue;

            $pkg = $wpdb->get_row(
                "SELECT p.*, v.name AS variant_name, f.name AS family_name
                 FROM {$wpdb->prefix}arag_packages p
                 INNER JOIN {$wpdb->prefix}arag_variants v ON v.id = p.variant_id
                 INNER JOIN {$wpdb->prefix}arag_families f ON f.id = v.family_id
                 WHERE p.id = {$pkg_id} AND p.is_active = 1"
            );
            if ( ! $pkg ) continue;

            $price = (float) $pkg->price;
            $line_items[] = [
                'package_id'  => $pkg_id,
                'qty'         => $qty,
                'price'       => $price,
                'label'       => "{$pkg->family_name} — {$pkg->variant_name} — {$pkg->label}",
                'family_name' => $pkg->family_name,
                'variant_name'=> $pkg->variant_name,
                'package_label'=> $pkg->label,
                'volume'      => $pkg->volume,
                'inv_product_id' => null,
            ];
            $subtotal += $price * $qty;
        }

        if ( empty( $line_items ) ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'اقلام نامعتبر' ], 400 );
        }

        $discount_amount = 0.0;
        $applied_coupon  = '';
        if ( $coupon_code ) {
            if ( str_starts_with( $coupon_code, 'REF' ) && strlen( $coupon_code ) > 5 && Arag_Referral::validate_code( $coupon_code ) ) {
                $discount_amount = round( $subtotal * 10 / 100 );
                $applied_coupon  = $coupon_code;
            } else {
                $cv = Arag_Shop::validate_coupon( $coupon_code, $subtotal );
                if ( empty( $cv['ok'] ) ) {
                    return new WP_REST_Response( [ 'success' => false, 'message' => $cv['message'] ?? 'کد تخفیف نامعتبر' ], 400 );
                }
                $discount_amount = (float) ( $cv['discount_amount'] ?? 0 );
                $applied_coupon  = $cv['code'];
            }
        }
        $total = max( 0, $subtotal - $discount_amount );

        if ( file_exists( ACC_PATH . 'includes/helpers/arag-erp.php' ) ) {
            require_once ACC_PATH . 'includes/helpers/arag-erp.php';
            $line_items = Arag_Erp::enrich_line_items( $line_items );
            $stock = Arag_Erp::validate_order_stock( $line_items );
            if ( empty( $stock['success'] ) ) {
                return new WP_REST_Response( [ 'success' => false, 'message' => $stock['message'] ?? 'موجودی کافی نیست' ], 400 );
            }
        }

        $order_key    = 'arag_' . bin2hex( random_bytes( 16 ) );
        $order_number = self::_next_order_number();

        $wpdb->insert( "{$wpdb->prefix}arag_orders", [
            'order_key'       => $order_key,
            'order_number'    => $order_number,
            'user_id'         => $user_id,
            'items_json'      => wp_json_encode( $line_items ),
            'subtotal'        => $subtotal,
            'coupon_code'     => $applied_coupon,
            'discount_amount' => $discount_amount,
            'total'           => $total,
            'shipping_method' => $shipping_method,
            'shipping_cod'    => in_array( $shipping_method, [ 'post', 'tipax' ], true ) ? 1 : 0,
            'payment_method'  => $payment_method,
            'payment_status'  => 'pending',
            'order_status'    => 'pending',
            'billing_name'    => $name ?: 'مشتری',
            'billing_phone'   => $phone,
            'billing_address' => sanitize_text_field( $billing['address'] ?? '' ),
            'billing_city'    => sanitize_text_field( $billing['city'] ?? '' ),
            'customer_note'   => $note,
        ] );
        $order_id = (int) $wpdb->insert_id;

        /* attribution بازاریاب: مغازه با موبایل بسته شده = ۷٪+۳٪ ؛ خرید مستقیم = ۱۰٪ سایت */
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}arag_marketer_accounts'" ) ) {
            Arag_Marketer::attach_to_order( $order_id, $sold_by_marketer_id > 0 ? $sold_by_marketer_id : null );
        }

        self::_fire_webhook( 'order.created', $order_id );

        if ( $applied_coupon ) {
            Arag_Shop::increment_coupon_use( $applied_coupon );
            if ( str_starts_with( $applied_coupon, 'REF' ) && strlen( $applied_coupon ) > 5 ) {
                Arag_Referral::record_use( $applied_coupon, $order_id, $phone, $discount_amount );
            }
        }

        $session_key = sanitize_text_field( $req->get_param( 'session_key' ) ?? $req->get_header( 'X-Cart-Session' ) ?? '' );

        /* پرداخت آزمایشی (sandbox) — فوری paid */
        if ( $payment_method === 'demo' ) {
            $ref_id = 'DEMO-' . strtoupper( substr( md5( $order_key . time() ), 0, 10 ) );
            $wpdb->update( "{$wpdb->prefix}arag_orders", [
                'payment_status' => 'paid',
                'order_status'   => 'processing',
                'ref_id'         => $ref_id,
                'payment_method' => 'demo',
            ], [ 'id' => $order_id ] );

            if ( $session_key ) {
                Arag_Shop::clear_cart( $session_key, $user_id );
            }
            if ( file_exists( ACC_PATH . 'includes/helpers/arag-erp.php' ) ) {
                require_once ACC_PATH . 'includes/helpers/arag-erp.php';
                Arag_Erp::on_order_placed( $order_id );
                Arag_Erp::on_order_confirmed( $order_id );
            }
            if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}arag_marketer_commissions'" ) ) {
                Arag_Marketer::on_payment_received( $order_id );
            }
            self::_fire_webhook( 'order.paid', $order_id );

            return new WP_REST_Response( [
                'success' => true,
                'data'    => [
                    'order_id'       => $order_id,
                    'order_key'      => $order_key,
                    'order_number'   => $order_number,
                    'subtotal'       => $subtotal,
                    'discount_amount'=> $discount_amount,
                    'total'          => $total,
                    'payment_method' => 'demo',
                    'payment_status' => 'paid',
                    'ref_id'         => $ref_id,
                    'redirect_url'   => ACC_URL . 'shop.php?order_success=' . $order_id . '&ref=' . urlencode( $ref_id ) . '&ok=' . urlencode( $order_key ),
                ],
            ], 201 );
        }

        /* پرداخت در محل یا کارت به کارت — بدون درگاه */
        if ( $payment_method !== 'zarinpal' ) {
            $status = $payment_method === 'cod' ? 'processing' : 'on-hold';
            $wpdb->update( "{$wpdb->prefix}arag_orders", [
                'payment_status' => $payment_method === 'cod' ? 'cod' : 'awaiting_transfer',
                'order_status'   => $status,
            ], [ 'id' => $order_id ] );

            if ( $session_key ) {
                Arag_Shop::clear_cart( $session_key, $user_id );
            }
            if ( file_exists( ACC_PATH . 'includes/helpers/arag-erp.php' ) ) {
                require_once ACC_PATH . 'includes/helpers/arag-erp.php';
                Arag_Erp::on_order_placed( $order_id );
                if ( $payment_method === 'cod' ) {
                    Arag_Erp::on_order_confirmed( $order_id );
                    self::_fire_webhook( 'order.paid', $order_id );
                }
            }

            return new WP_REST_Response( [
                'success' => true,
                'data'    => [
                    'order_id'       => $order_id,
                    'order_key'      => $order_key,
                    'order_number'   => $order_number,
                    'subtotal'       => $subtotal,
                    'discount_amount'=> $discount_amount,
                    'total'          => $total,
                    'payment_method' => $payment_method,
                    'redirect_url'   => ACC_URL . 'shop.php?order_success=' . $order_id . '&ok=' . urlencode( $order_key ),
                ],
            ], 201 );
        }

        /* زرین‌پال — سبد را تا تأیید پرداخت نگه می‌داریم */
        $host = ( is_ssl() ? 'https' : 'http' ) . '://' . ( $_SERVER['HTTP_HOST'] ?? 'localhost' );
        $callback = $host . ACC_URL . 'api.php/acc/v1/public/arag/orders/verify?order_key=' . urlencode( $order_key );

        $zp = SR_Zarinpal::request(
            (int) ( $total * 10 ),
            $callback,
            'سفارش عرقیات ' . $order_number,
            $phone
        );

        if ( empty( $zp['success'] ) ) {
            /* روی localhost اگر درگاه خطا داد، لینک شبیه‌سازی sandbox بده */
            if ( SR_Zarinpal::is_sandbox() ) {
                $sim = $host . ACC_URL . 'api.php/acc/v1/public/arag/orders/simulate-pay?order_key=' . urlencode( $order_key );
                return new WP_REST_Response( [
                    'success' => true,
                    'data'    => [
                        'order_id'     => $order_id,
                        'order_key'    => $order_key,
                        'order_number' => $order_number,
                        'subtotal'     => $subtotal,
                        'discount_amount' => $discount_amount,
                        'total'        => $total,
                        'payment_url'  => $sim,
                        'sandbox'      => true,
                        'simulated'    => true,
                        'message'      => 'درگاه در دسترس نبود — مسیر شبیه‌سازی sandbox فعال شد',
                    ],
                ], 201 );
            }
            return new WP_REST_Response( [ 'success' => false, 'message' => $zp['message'] ?? 'خطای درگاه' ], 502 );
        }

        $authority = sanitize_text_field( $zp['authority'] );
        $wpdb->update( "{$wpdb->prefix}arag_orders", [ 'authority' => $authority ], [ 'id' => $order_id ] );

        $payload = [
            'order_id'        => $order_id,
            'order_key'       => $order_key,
            'order_number'    => $order_number,
            'subtotal'        => $subtotal,
            'discount_amount' => $discount_amount,
            'total'           => $total,
            'payment_url'     => $zp['payment_url'],
            'sandbox'         => SR_Zarinpal::is_sandbox(),
        ];
        /* روی localhost کال‌بک زرین‌پال برنمی‌گردد — لینک شبیه‌سازی هم بده */
        if ( SR_Zarinpal::is_sandbox() && ( str_contains( $host, 'localhost' ) || str_contains( $host, '127.0.0.1' ) ) ) {
            $payload['simulate_url'] = $host . ACC_URL . 'api.php/acc/v1/public/arag/orders/simulate-pay?order_key=' . urlencode( $order_key );
        }

        return new WP_REST_Response( [
            'success' => true,
            'data'    => $payload,
        ], 201 );
    }

    public static function verify_payment( WP_REST_Request $req ) {
        global $wpdb;
        $authority  = sanitize_text_field( $req->get_param('Authority') ?? '' );
        $status     = sanitize_text_field( $req->get_param('Status') ?? '' );
        $order_key  = sanitize_text_field( $req->get_param('order_key') ?? '' );

        $shop_base = ACC_URL . 'shop.php';

        if ( ! $order_key ) {
            wp_redirect( $shop_base . '?payment=error' );
            exit;
        }

        $order = $wpdb->get_row(
            $wpdb->prepare(
                "SELECT * FROM {$wpdb->prefix}arag_orders WHERE order_key = %s LIMIT 1",
                $order_key
            )
        );

        if ( ! $order ) {
            wp_redirect( $shop_base . '?payment=error' );
            exit;
        }

        if ( $status !== 'OK' ) {
            $wpdb->update( "{$wpdb->prefix}arag_orders", [
                'payment_status' => 'cancelled',
                'order_status'   => 'cancelled',
            ], [ 'id' => (int) $order->id ] );
            wp_redirect( $shop_base . '?payment=cancelled&order=' . $order->id );
            exit;
        }

        $pay_amount = (float) ( $order->total > 0 ? $order->total : $order->subtotal );
        $zp = SR_Zarinpal::verify(
            $authority ?: (string) $order->authority,
            (int) ( $pay_amount * 10 )
        );

        if ( ! empty( $zp['success'] ) ) {
            self::_mark_order_paid( (int) $order->id, (string) ( $zp['ref_id'] ?? '' ), $authority ?: (string) $order->authority );
            wp_redirect( $shop_base . '?order_success=' . $order->id . '&ref=' . urlencode( (string) ( $zp['ref_id'] ?? '' ) ) . '&ok=' . urlencode( (string) $order->order_key ) );
            exit;
        }

        $wpdb->update( "{$wpdb->prefix}arag_orders", [
            'payment_status' => 'failed',
            'order_status'   => 'failed',
        ], [ 'id' => (int) $order->id ] );
        wp_redirect( $shop_base . '?payment=failed&order=' . $order->id );
        exit;
    }

    /** شبیه‌سازی پرداخت موفق — فقط در حالت sandbox */
    public static function simulate_pay( WP_REST_Request $req ) {
        global $wpdb;
        $shop_base = ACC_URL . 'shop.php';

        if ( ! SR_Zarinpal::is_sandbox() || ( function_exists( 'acc_is_local_environment' ) && ! acc_is_local_environment() ) ) {
            wp_redirect( $shop_base . '?payment=error' );
            exit;
        }

        $order_key = sanitize_text_field( $req->get_param( 'order_key' ) ?? '' );
        if ( ! $order_key ) {
            wp_redirect( $shop_base . '?payment=error' );
            exit;
        }

        $order = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}arag_orders WHERE order_key = %s LIMIT 1", $order_key
        ) );
        if ( ! $order ) {
            wp_redirect( $shop_base . '?payment=error' );
            exit;
        }

        if ( in_array( $order->payment_status, [ 'paid', 'cod' ], true ) ) {
            wp_redirect( $shop_base . '?order_success=' . $order->id . '&ref=' . urlencode( (string) ( $order->ref_id ?: '' ) ) . '&ok=' . urlencode( (string) $order->order_key ) );
            exit;
        }

        $ref_id = 'SIM-' . strtoupper( substr( md5( $order_key . time() ), 0, 10 ) );
        self::_mark_order_paid( (int) $order->id, $ref_id, (string) ( $order->authority ?: 'SIMULATED' ) );
        wp_redirect( $shop_base . '?order_success=' . $order->id . '&ref=' . urlencode( $ref_id ) . '&ok=' . urlencode( (string) $order->order_key ) );
        exit;
    }

    public static function order_receipt( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id = (int) $req['id'];
        $order_key = sanitize_text_field( (string) ( $req->get_param( 'order_key' ) ?? '' ) );
        $phone     = self::_normalize_phone( (string) ( $req->get_param( 'phone' ) ?? '' ) );

        $order = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}arag_orders WHERE id = %d LIMIT 1", $id
        ) );
        if ( ! $order ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'سفارش یافت نشد' ], 404 );
        }

        $key_ok   = $order_key !== '' && hash_equals( (string) $order->order_key, $order_key );
        $phone_ok = $phone !== '' && hash_equals(
            preg_replace( '/\D/', '', (string) $order->billing_phone ),
            preg_replace( '/\D/', '', $phone )
        );
        $jwt_uid = function_exists( '_acc_jwt_user_id_from_request' ) ? (int) _acc_jwt_user_id_from_request() : 0;
        $owner_ok = $jwt_uid > 0 && (int) $order->user_id === $jwt_uid;

        if ( ! $key_ok && ! $phone_ok && ! $owner_ok ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی غیرمجاز' ], 403 );
        }

        $items = json_decode( $order->items_json ?? '[]', true ) ?: [];
        return new WP_REST_Response( [
            'success' => true,
            'data'    => [
                'id'              => (int) $order->id,
                'order_number'    => $order->order_number,
                'order_key'       => $order->order_key,
                'subtotal'        => (float) $order->subtotal,
                'discount_amount' => (float) ( $order->discount_amount ?? 0 ),
                'total'           => (float) ( $order->total > 0 ? $order->total : $order->subtotal ),
                'payment_method'  => $order->payment_method,
                'payment_status'  => $order->payment_status,
                'order_status'    => $order->order_status,
                'ref_id'          => $order->ref_id,
                'shipping_method' => $order->shipping_method,
                'billing_name'    => $order->billing_name,
                'billing_phone'   => $order->billing_phone,
                'billing_city'    => $order->billing_city,
                'items'           => $items,
                'created_at'      => $order->created_at,
            ],
        ] );
    }

    private static function _mark_order_paid( int $order_id, string $ref_id, string $authority = '' ): void {
        global $wpdb;
        $upd = [
            'payment_status' => 'paid',
            'order_status'   => 'processing',
            'ref_id'         => $ref_id,
        ];
        if ( $authority ) {
            $upd['authority'] = $authority;
        }
        $wpdb->update( "{$wpdb->prefix}arag_orders", $upd, [ 'id' => $order_id ] );

        $order = $wpdb->get_row( $wpdb->prepare(
            "SELECT user_id FROM {$wpdb->prefix}arag_orders WHERE id = %d", $order_id
        ) );
        if ( $order && (int) $order->user_id > 0 ) {
            Arag_Shop::clear_cart( '', (int) $order->user_id );
        }

        if ( file_exists( ACC_PATH . 'includes/helpers/arag-erp.php' ) ) {
            require_once ACC_PATH . 'includes/helpers/arag-erp.php';
            Arag_Erp::on_order_confirmed( $order_id );
        }
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}arag_marketer_commissions'" ) ) {
            Arag_Marketer::on_payment_received( $order_id );
        }
        self::_fire_webhook( 'order.paid', $order_id );
    }

    /* ── Account (JWT) ── */
    public static function account_dashboard( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $user_id = get_current_user_id();
        $user    = get_user_by( 'id', $user_id );

        $orders_count = (int) $wpdb->get_var(
            "SELECT COUNT(*) FROM {$wpdb->prefix}arag_orders WHERE user_id = {$user_id}"
        );
        $recent = $wpdb->get_results(
            "SELECT id, order_number, subtotal, order_status, payment_status, created_at
             FROM {$wpdb->prefix}arag_orders WHERE user_id = {$user_id}
             ORDER BY id DESC LIMIT 5"
        );

        return new WP_REST_Response( [
            'user'   => self::_format_user( $user ),
            'stats'  => [
                'orders_count' => $orders_count,
                'shipping_cod' => true,
            ],
            'recent_orders' => $recent ?: [],
        ] );
    }

    public static function account_orders( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $user_id = get_current_user_id();
        $rows = $wpdb->get_results(
            "SELECT * FROM {$wpdb->prefix}arag_orders WHERE user_id = {$user_id} ORDER BY id DESC LIMIT 50"
        );
        $orders = array_map( function( $o ) {
            $o->items = json_decode( $o->items_json, true );
            unset( $o->items_json );
            return $o;
        }, $rows ?: [] );
        return new WP_REST_Response( [ 'data' => $orders ] );
    }

    public static function update_profile( WP_REST_Request $req ): WP_REST_Response {
        $user_id = get_current_user_id();
        $name    = sanitize_text_field( $req->get_param('name') ?? '' );
        $address = sanitize_text_field( $req->get_param('address') ?? '' );
        $city    = sanitize_text_field( $req->get_param('city') ?? '' );

        if ( $name ) {
            wp_update_user( [ 'ID' => $user_id, 'display_name' => $name ] );
        }
        if ( $address ) update_user_meta( $user_id, 'billing_address_1', $address );
        if ( $city )    update_user_meta( $user_id, 'billing_city', $city );

        $user = get_user_by( 'id', $user_id );
        return new WP_REST_Response( [ 'success' => true, 'user' => self::_format_user( $user ) ] );
    }

    /* ── Helpers ── */
    private static function _normalize_phone( string $phone ): string {
        $phone = preg_replace( '/\D/', '', $phone );
        if ( str_starts_with( $phone, '98' ) && strlen( $phone ) === 12 ) {
            $phone = '0' . substr( $phone, 2 );
        }
        if ( preg_match( '/^09\d{9}$/', $phone ) ) {
            return $phone;
        }
        return '';
    }

    private static function _get_or_create_customer( string $phone ) {
        $login = 'm_' . $phone;
        $user  = get_user_by( 'login', $login );
        if ( $user ) {
            return $user;
        }

        if ( ! function_exists( 'wp_create_user' ) ) {
            return new WP_Error( 'no_create', 'ایجاد کاربر پشتیبانی نمی‌شود' );
        }

        $password = wp_generate_password( 12, true );
        $user_id  = wp_create_user( $login, $password, $login . '@shop.local' );
        if ( is_wp_error( $user_id ) ) {
            return $user_id;
        }

        wp_update_user( [
            'ID'           => $user_id,
            'display_name' => 'مشتری ' . substr( $phone, -4 ),
            'role'         => 'customer',
        ] );
        update_user_meta( $user_id, 'billing_phone', $phone );

        return get_user_by( 'id', $user_id );
    }

    private static function _format_user( $user ): array {
        if ( ! $user ) return [];
        return [
            'id'       => (int) $user->ID,
            'name'     => $user->display_name,
            'email'    => $user->user_email,
            'username' => $user->user_login,
            'phone'    => get_user_meta( $user->ID, 'billing_phone', true ) ?: '',
            'address'  => get_user_meta( $user->ID, 'billing_address_1', true ) ?: '',
            'city'     => get_user_meta( $user->ID, 'billing_city', true ) ?: '',
        ];
    }

    private static function _next_order_number(): string {
        global $wpdb;
        $year = date( 'Y' );
        $cnt  = (int) $wpdb->get_var(
            "SELECT COUNT(*) FROM {$wpdb->prefix}arag_orders WHERE YEAR(created_at) = {$year}"
        );
        return 'AR-' . $year . '-' . str_pad( (string) ( $cnt + 1 ), 5, '0', STR_PAD_LEFT );
    }

    /* ── AI Chat ── */
    public static function ai_chat( WP_REST_Request $req ): WP_REST_Response {
        $body    = $req->get_json_params() ?: [];
        $message = sanitize_textarea_field( $body['message'] ?? $req->get_param( 'message' ) ?? '' );
        $history = is_array( $body['history'] ?? null ) ? $body['history'] : [];
        $session = sanitize_text_field( $body['session_id'] ?? $req->get_param( 'session_id' ) ?? '' );
        $mizaj   = sanitize_key( $body['mizaj_type'] ?? '' );

        $result = Arag_Shop_AI::chat( $message, $history, $session, $mizaj );
        if ( empty( $result['success'] ) ) {
            return new WP_REST_Response( [
                'success' => false,
                'message' => $result['message'] ?? 'خطا',
            ], 400 );
        }

        $site = defined( 'ACC_URL' ) ? ACC_URL : '/acc-engine/';
        $suggestions = array_map( static function ( $p ) use ( $site ) {
            return [
                'name'  => $p['name'],
                'slug'  => $p['slug'],
                'price' => $p['min_price'] ?? 0,
                'url'   => rtrim( $site, '/' ) . '/shop.php?p=' . rawurlencode( $p['slug'] ),
            ];
        }, $result['suggestions'] ?? [] );

        return new WP_REST_Response( [
            'success' => true,
            'data'    => [
                'reply'       => $result['reply'],
                'engine'      => $result['engine'] ?? 'rules',
                'suggestions' => $suggestions,
            ],
        ] );
    }

    public static function ai_status( WP_REST_Request $req ): WP_REST_Response {
        $cfg = Arag_Shop_AI::config();
        return new WP_REST_Response( [
            'success' => true,
            'data'    => [
                'enabled'    => $cfg['enabled'],
                'has_llm'    => ! empty( $cfg['api_key'] ),
                'model'      => $cfg['model'],
                'products'   => count( Arag_Shop_AI::catalog_summary() ),
            ],
        ] );
    }

    public static function admin_get_integrations( WP_REST_Request $req ): WP_REST_Response {
        $sms = Acc_SMS::config();
        $ai  = Arag_Shop_AI::config();
        return new WP_REST_Response( [
            'success' => true,
            'data'    => [
                'otp_demo'           => get_option( 'acc_shop_otp_demo', '1' ) === '1',
                'sms_provider'       => $sms['provider'],
                'sms_sender'         => $sms['sender'],
                'sms_otp_template'   => $sms['otp_template'],
                'sms_has_key'        => ! empty( $sms['api_key'] ),
                'zarinpal_merchant'  => SR_Zarinpal::merchant(),
                'zarinpal_sandbox'   => SR_Zarinpal::is_sandbox(),
                'ai_enabled'         => $ai['enabled'],
                'ai_model'           => $ai['model'],
                'ai_base_url'        => $ai['base_url'],
                'ai_has_key'         => ! empty( $ai['api_key'] ),
            ],
        ] );
    }

    public static function admin_save_integrations( WP_REST_Request $req ): WP_REST_Response {
        $body = $req->get_json_params() ?: [];

        if ( isset( $body['otp_demo'] ) ) {
            update_option( 'acc_shop_otp_demo', ! empty( $body['otp_demo'] ) ? '1' : '0' );
        }
        if ( isset( $body['sms_provider'] ) ) {
            update_option( 'acc_sms_provider', sanitize_key( $body['sms_provider'] ) );
        }
        if ( isset( $body['sms_api_key'] ) && $body['sms_api_key'] !== '' ) {
            update_option( 'acc_sms_api_key', sanitize_text_field( $body['sms_api_key'] ) );
        }
        if ( isset( $body['sms_sender'] ) ) {
            update_option( 'acc_sms_sender', sanitize_text_field( $body['sms_sender'] ) );
        }
        if ( isset( $body['sms_otp_template'] ) ) {
            update_option( 'acc_sms_otp_template', sanitize_text_field( $body['sms_otp_template'] ) );
        }
        if ( isset( $body['zarinpal_merchant'] ) ) {
            update_option( 'acc_zarinpal_merchant', sanitize_text_field( $body['zarinpal_merchant'] ) );
        }
        if ( isset( $body['zarinpal_sandbox'] ) ) {
            update_option( 'acc_zarinpal_sandbox', ! empty( $body['zarinpal_sandbox'] ) ? '1' : '0' );
        }
        if ( isset( $body['ai_enabled'] ) ) {
            update_option( 'acc_shop_ai_enabled', ! empty( $body['ai_enabled'] ) ? '1' : '0' );
        }
        if ( isset( $body['ai_api_key'] ) && $body['ai_api_key'] !== '' ) {
            update_option( 'acc_shop_ai_api_key', sanitize_text_field( $body['ai_api_key'] ) );
        }
        if ( isset( $body['ai_base_url'] ) ) {
            update_option( 'acc_shop_ai_base_url', esc_url_raw( $body['ai_base_url'] ) );
        }
        if ( isset( $body['ai_model'] ) ) {
            update_option( 'acc_shop_ai_model', sanitize_text_field( $body['ai_model'] ) );
        }

        return self::admin_get_integrations( $req );
    }

    /* ── Order Tracking (no auth) ── */
    public static function track_order( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $order_id = (int) $req->get_param('order_id');
        $phone    = self::_normalize_phone( (string) ( $req->get_param('phone') ?? '' ) );

        if ( ! $order_id ) {
            return new WP_REST_Response( [ 'message' => 'شماره سفارش الزامی است' ], 400 );
        }
        if ( ! $phone ) {
            return new WP_REST_Response( [ 'message' => 'شماره موبایل برای پیگیری الزامی است' ], 400 );
        }

        if ( function_exists( 'acc_rate_limit' ) ) {
            $ip = function_exists( 'acc_client_ip' ) ? acc_client_ip() : ( $_SERVER['REMOTE_ADDR'] ?? '0' );
            if ( ! acc_rate_limit( 'track_ip_' . $ip, 60, 3600 ) ) {
                return new WP_REST_Response( [ 'message' => 'تعداد درخواست پیگیری زیاد است' ], 429 );
            }
        }

        $row = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}arag_orders WHERE id = %d",
            $order_id
        ) );

        if ( ! $row ) {
            return new WP_REST_Response( [ 'message' => 'سفارشی با این شماره یافت نشد' ], 404 );
        }

        $stored_phone = preg_replace( '/\D/', '', $row->billing_phone ?? '' );
        $given_phone  = preg_replace( '/\D/', '', $phone );
        if ( ! $stored_phone || ! $given_phone || ! hash_equals( $stored_phone, $given_phone ) ) {
            return new WP_REST_Response( [ 'message' => 'شماره موبایل با سفارش مطابقت ندارد' ], 403 );
        }

        $total = (float) ( $row->total > 0 ? $row->total : $row->subtotal );
        $items = json_decode( $row->items_json ?? '[]', true ) ?: [];

        return new WP_REST_Response( [ 'data' => [
            'id'              => (int) $row->id,
            'order_number'    => $row->order_number,
            'status'          => $row->order_status,
            'order_status'    => $row->order_status,
            'payment_status'  => $row->payment_status,
            'subtotal'        => (float) $row->subtotal,
            'discount_amount' => (float) ( $row->discount_amount ?? 0 ),
            'total'           => $total,
            'created_at'      => $row->created_at,
            'items'           => $items,
            'billing'         => [
                'name'    => $row->billing_name ?? '',
                'phone'   => $row->billing_phone ?? '',
                'city'    => $row->billing_city ?? '',
                'address' => $row->billing_address ?? '',
            ],
        ] ] );
    }

    /* ── Coupon Check ── */
    public static function check_coupon( WP_REST_Request $req ): WP_REST_Response {
        $code     = strtoupper( sanitize_text_field( $req->get_param('code') ?? '' ) );
        $subtotal = max( 0, (float) ( $req->get_param('subtotal') ?? 0 ) );

        if ( str_starts_with( $code, 'REF' ) && strlen( $code ) > 5 ) {
            $ref = Arag_Referral::validate_code( $code );
            if ( $ref ) {
                $pct = 10;
                $amt = round( $subtotal * $pct / 100 );
                return new WP_REST_Response( [ 'data' => [
                    'code'            => $code,
                    'discount_pct'    => $pct,
                    'discount_fixed'  => 0,
                    'discount_amount' => $amt,
                    'min_order'       => 0,
                    'referral'        => true,
                ] ] );
            }
        }

        $cv = Arag_Shop::validate_coupon( $code, $subtotal );
        if ( empty( $cv['ok'] ) ) {
            return new WP_REST_Response( [ 'message' => $cv['message'] ?? 'کد تخفیف نامعتبر است' ], 404 );
        }

        return new WP_REST_Response( [ 'data' => [
            'code'            => $cv['code'],
            'discount_pct'    => (int) ( $cv['discount_pct'] ?? 0 ),
            'discount_fixed'  => (float) ( $cv['discount_fixed'] ?? 0 ),
            'discount_amount' => (float) ( $cv['discount_amount'] ?? 0 ),
            'min_order'       => (float) ( $cv['min_order'] ?? 0 ),
        ] ] );
    }

    /* ── Mizaj Test ── */
    public static function mizaj_questions( WP_REST_Request $req ): WP_REST_Response {
        return new WP_REST_Response( [
            'success' => true,
            'data'    => Arag_Mizaj::questions(),
            'total'   => count( Arag_Mizaj::questions() ),
        ] );
    }

    public static function mizaj_submit( WP_REST_Request $req ): WP_REST_Response {
        $body = $req->get_json_params() ?: [];
        $answers = (array) ( $body['answers'] ?? [] );
        $session = sanitize_text_field( $body['session_id'] ?? '' );
        $phone   = sanitize_text_field( $body['phone'] ?? '' );
        if ( count( $answers ) < 10 ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'لطفاً به همه سؤالات پاسخ دهید' ], 400 );
        }
        if ( ! $session ) {
            $session = 'mz_' . bin2hex( random_bytes( 6 ) );
        }
        $result = Arag_Mizaj::build_result( $answers, $session, $phone );
        $result['session_id'] = $session;
        return new WP_REST_Response( [ 'success' => true, 'data' => $result ] );
    }

    public static function mizaj_result( WP_REST_Request $req ): WP_REST_Response {
        $session = sanitize_text_field( $req->get_param( 'session' ) ?? '' );
        $row = Arag_Mizaj::get_session( $session );
        if ( ! $row ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'نتیجه یافت نشد' ], 404 );
        }
        $answers = json_decode( $row['answers_json'] ?? '{}', true ) ?: [];
        $result = Arag_Mizaj::build_result( $answers, $session, $row['phone'] ?? '' );
        return new WP_REST_Response( [ 'success' => true, 'data' => $result ] );
    }

    /* ── Referral ── */
    public static function referral_get( WP_REST_Request $req ): WP_REST_Response {
        $phone = sanitize_text_field( $req->get_param( 'phone' ) ?? '' );
        $uid   = function_exists( '_acc_jwt_user_id_from_request' ) ? _acc_jwt_user_id_from_request() : 0;
        $res   = Arag_Referral::get_or_create( $uid, $phone );
        if ( empty( $res['success'] ) ) {
            return new WP_REST_Response( $res, 400 );
        }
        return new WP_REST_Response( $res );
    }

    public static function referral_create( WP_REST_Request $req ): WP_REST_Response {
        $uid = function_exists( '_acc_jwt_user_id_from_request' ) ? (int) _acc_jwt_user_id_from_request() : 0;
        if ( $uid <= 0 ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'ورود لازم است' ], 401 );
        }
        $body  = $req->get_json_params() ?: [];
        $phone = sanitize_text_field( $body['phone'] ?? '' );
        $res   = Arag_Referral::get_or_create( $uid, $phone );
        if ( empty( $res['success'] ) ) {
            return new WP_REST_Response( $res, 400 );
        }
        return new WP_REST_Response( $res, 201 );
    }

    /* ── Subscription interest ── */
    public static function subscribe_plan( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $body = $req->get_json_params() ?: [];
        $phone = preg_replace( '/\D/', '', (string) ( $body['phone'] ?? '' ) );
        if ( ! preg_match( '/^09\d{9}$/', $phone ) ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'شماره موبایل معتبر نیست' ], 400 );
        }
        $t = $wpdb->prefix . 'arag_subscriptions';
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$t}'" ) !== $t ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'ماژول اشتراک نصب نشده' ], 503 );
        }
        $wpdb->insert( $t, [
            'phone'      => $phone,
            'name'       => sanitize_text_field( $body['name'] ?? '' ),
            'plan_key'   => sanitize_key( $body['plan'] ?? 'monthly_classic' ),
            'mizaj_type' => sanitize_key( $body['mizaj_type'] ?? '' ),
            'notes'      => sanitize_textarea_field( $body['notes'] ?? '' ),
            'status'     => 'pending',
        ] );
        return new WP_REST_Response( [
            'success' => true,
            'message' => 'درخواست اشتراک ثبت شد. به زودی با شما تماس می‌گیریم.',
            'id'      => (int) $wpdb->insert_id,
        ], 201 );
    }
}
