<?php
defined('ABSPATH') || exit;

use Nabik\Gateland\Pay;
use Nabik\Gateland\Services\GatewayService;

class Dori_Chatbot_Gateland_API
{
    public const MORI_CLIENT = 'mori_chatbot';

    public static bool $guest_enabled = false;
    public static array $active_gateways = array();

    public static function init()
    {
        self::$guest_enabled = get_option('woocommerce_enable_guest_checkout', 'no') === 'yes';
        add_filter('nabik/gateland/transaction_clients', array(__CLASS__, 'append_mori_client'));
        add_action('rest_api_init', array(__CLASS__, 'register_routes'));

        if (class_exists('Nabik\\Gateland\\Services\\GatewayService')) {
            self::$active_gateways = GatewayService::activated();
        } else {
            Dori_Chatbot_Logger::debug('Gateland classes not found, routes will be skipped');
        }
    }

    public static function append_mori_client($clients)
    {
        $clients[self::MORI_CLIENT] = 'چت بات موری';
        return $clients;
    }

    public static function register_routes()
    {
        if (!class_exists('Nabik\\Gateland\\Pay') || !class_exists('Nabik\\Gateland\\Services\\GatewayService')) {
            Dori_Chatbot_Logger::debug('Gateland classes not found during route registration');
            return;
        }

        self::$active_gateways = GatewayService::activated();

        register_rest_route('mori/v1', 'gateland/create-order', array(
            'methods' => 'POST',
            'callback' => array(__CLASS__, 'handle_create_order_endpoint'),
            'permission_callback' => array(__CLASS__, 'validate_client_credentials'),
            'args' => array(
                'customer_id' => array(
                    'required' => !self::$guest_enabled,
                    'type' => 'integer',
                    'validate_callback' => function ($value) {
                        return $value > 0 && get_user_by('id', $value) !== false;
                    },
                ),
                'currency' => array(
                    'required' => true,
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_text_field',
                    'validate_callback' => function ($value) {
                        return in_array($value, array('IRT', 'IRR', 'IRHR', 'IRHT'), true);
                    },
                ),
                'created_via' => array(
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_text_field',
                    'validate_callback' => function ($value) {
                        return $value === self::MORI_CLIENT;
                    },
                ),
                'line_items' => array(
                    'required' => true,
                    'validate_callback' => function ($items) {
                        if (!is_array($items) || empty($items)) {
                            return false;
                        }

                        foreach ($items as $item) {
                            if (empty($item['product_id']) || empty($item['quantity'])) {
                                return false;
                            }

                            if (!empty($item['variation_id'])) {
                                if (empty(wc_get_product($item['variation_id']))) {
                                    return false;
                                }
                            } else {
                                if (empty(wc_get_product($item['product_id']))) {
                                    return false;
                                }
                            }
                        }

                        return true;
                    },
                ),
                'shipping_lines' => array(
                    'validate_callback' => function ($lines) {
                        if (!is_array($lines)) {
                            return false;
                        }

                        foreach ($lines as $line) {
                            if (empty($line['method_id'])) {
                                return false;
                            }
                        }

                        return true;
                    },
                ),
                'billing' => array(
                    'required' => true,
                    'validate_callback' => array(__CLASS__, 'validate_address'),
                ),
                'shipping' => array(
                    'required' => true,
                    'validate_callback' => array(__CLASS__, 'validate_address'),
                ),
            ),
        ));

        register_rest_route('mori/v1', 'gateland/create-transaction', array(
            'methods' => 'POST',
            'callback' => array(__CLASS__, 'handle_create_transaction_endpoint'),
            'permission_callback' => array(__CLASS__, 'validate_client_credentials'),
            'args' => array(
                'amount' => array(
                    'required' => true,
                    'type' => 'string',
                    'sanitize_callback' => function ($value) {
                        return str_replace(array(' ', ',', '.'), '', $value);
                    },
                    'validate_callback' => function ($value) {
                        return ctype_digit($value) && intval($value) > 0;
                    },
                ),
                'user_id' => array(
                    'required' => !self::$guest_enabled,
                    'type' => 'integer',
                    'validate_callback' => function ($value) {
                        return $value > 0 && get_user_by('id', $value) !== false;
                    },
                ),
                'callback_link' => array(
                    'required' => true,
                    'type' => 'string',
                    'sanitize_callback' => 'esc_url_raw',
                    'validate_callback' => function ($value) {
                        if (!filter_var($value, FILTER_VALIDATE_URL)) {
                            return false;
                        }

                        $scheme = wp_parse_url($value, PHP_URL_SCHEME);
                        return in_array($scheme, array('http', 'https'), true);
                    },
                ),
                'mobile' => array(
                    'required' => false,
                    'type' => 'string',
                    'sanitize_callback' => function ($value) {
                        return trim($value);
                    },
                    'validate_callback' => function ($value) {
                        $value = str_replace(array(' ', '-', '(', ')'), '', $value);
                        return (bool) preg_match('/^(\+989|989|09)[0-9]{9}$/', $value);
                    },
                ),
                'gateway_id' => array(
                    'required' => false,
                    'type' => 'integer',
                    'sanitize_callback' => function ($value) {
                        return intval($value);
                    },
                    'validate_callback' => function ($value) {
                        $ids = array_column(self::$active_gateways, 'id');
                        return in_array($value, $ids, true);
                    },
                ),
            ),
        ));

        register_rest_route('mori/v1', 'gateland/verify-transaction', array(
            'methods' => 'POST',
            'callback' => array(__CLASS__, 'handle_verify_transaction_endpoint'),
            'permission_callback' => array(__CLASS__, 'validate_client_credentials'),
            'args' => array(
                'authority' => array(
                    'required' => true,
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_text_field',
                    'validate_callback' => function ($value) {
                        $len = strlen($value);
                        if ($len < 3 || $len > 64) {
                            return false;
                        }

                        return sanitize_key($value) === strtolower($value);
                    },
                ),
            ),
        ));

        register_rest_route('mori/v1', 'gateland/gateways', array(
            'methods' => 'GET',
            'callback' => array(__CLASS__, 'gateway_listing_endpoint'),
            'permission_callback' => array(__CLASS__, 'validate_client_credentials'),
        ));
    }

    public static function handle_create_order_endpoint(WP_REST_Request $request): WP_REST_Response
    {
        if (!class_exists('WooCommerce')) {
            return new WP_REST_Response(array(
                'success' => false,
                'error' => 'WooCommerce not active',
            ), 500);
        }

        $data = $request->get_json_params();

        if (empty($data)) {
            return new WP_REST_Response(array(
                'success' => false,
                'error' => 'Invalid JSON body',
            ), 400);
        }

        $customer_id = isset($data['customer_id']) ? intval($data['customer_id']) : 0;

        $order = wc_create_order(array(
            'customer_id' => $customer_id,
        ));

        if (is_wp_error($order)) {
            return new WP_REST_Response(array(
                'success' => false,
                'error' => $order->get_error_message(),
            ), 500);
        }

        $created_via = !empty($data['created_via']) ? $data['created_via'] : self::MORI_CLIENT;
        $order->set_created_via($created_via);
        $order->update_meta_data('_wc_order_attribution_source_type', 'utm');
        $order->update_meta_data('_wc_order_attribution_utm_source', $created_via);
        $order->update_meta_data('_wc_order_attribution_session_entry', 'api');
        $order->update_meta_data('_wc_order_attribution_session_id', $data['dori_session_key'] ?? 'no-session-key');
        $order->update_meta_data('dori_session_key', $data['dori_session_key'] ?? 'no-session-key');

        if (!empty($data['billing'])) {
            $order->set_address($data['billing']);
        }

        if (!empty($data['shipping'])) {
            $order->set_address($data['shipping'], 'shipping');
        }

        foreach ($data['line_items'] as $item) {
            if (!empty($item['variation_id'])) {
                $product = wc_get_product($item['variation_id']);
            } else {
                $product = wc_get_product($item['product_id']);
            }

            if (!$product) {
                return new WP_REST_Response(array(
                    'success' => false,
                    'error' => 'Invalid product ' . $item['product_id'],
                ), 400);
            }

            $order->add_product($product, $item['quantity']);
        }

        if (!empty($data['shipping_lines']) && is_array($data['shipping_lines'])) {
            foreach ($data['shipping_lines'] as $shipping_method) {
                $shipping = new WC_Order_Item_Shipping();
                $shipping->set_method_title($shipping_method['method_title']);
                $shipping->set_method_id($shipping_method['method_id']);
                $shipping->set_total($shipping_method['total']);
                $order->add_item($shipping);
            }
        }

        $order->calculate_totals();
        $order->save();

        Dori_Chatbot_Logger::debug('Gateland order created: order_id=' . $order->get_id());

        return new WP_REST_Response(array(
            'success' => true,
            'payment_link' => $order->get_checkout_payment_url(),
            'order_id' => $order->get_id(),
        ), 201);
    }

    public static function validate_address($address): bool
    {
        if (!is_array($address)) {
            return false;
        }

        if (empty($address['email'])) {
            $address['email'] = 'nomail@invalid.com';
        }

        $required = array('first_name', 'last_name', 'address_1', 'city', 'state', 'postcode', 'phone');

        foreach ($required as $field) {
            if (empty($address[$field])) {
                return false;
            }
        }

        return true;
    }

    public static function handle_create_transaction_endpoint(WP_REST_Request $request): WP_REST_Response
    {
        $amount = intval($request['amount']);
        $user_id = $request['user_id'] ?? null;
        $mobile = $request['mobile'] ?? '';
        $gateway_id = $request['gateway_id'] ?? null;
        $callback = $request['callback_link'];

        $order_id = rand(0, 100000);
        $secret = hash('crc32', $order_id . AUTH_KEY);

        $callback = add_query_arg(array(
            'mori_gw' => 'gateland',
            'order_id' => $order_id,
            'secret' => $secret,
        ), $callback);

        $description = sprintf('سفارش به مبلغ %s تومان از وبسایت %s', number_format_i18n($amount), home_url());

        $args = array(
            'amount' => $amount,
            'callback' => $callback,
            'user_id' => $user_id,
            'client' => self::MORI_CLIENT,
            'description' => $description,
            'currency' => 'IRT',
            'order_id' => $order_id,
            'mobile' => $mobile,
        );

        if (!empty($gateway_id)) {
            $args['gateway'] = $gateway_id;
        }

        try {
            $response = Pay::request($args);
        } catch (Throwable $e) {
            Dori_Chatbot_Logger::debug('Gateland transaction request failed: ' . $e->getMessage());
            $message = 'درخواست پرداخت، با خطا مواجه شد: ' . $e->getMessage();
            return new WP_REST_Response(array(
                'success' => false,
                'message' => $message,
            ), 500);
        }

        if (!is_array($response)) {
            Dori_Chatbot_Logger::debug('Gateland transaction invalid response type');
            return new WP_REST_Response(array(
                'success' => false,
                'message' => 'هنگام درخواست ایجاد پرداخت، پاسخ نامعتبر از درگاه دریافت شد.',
            ), 500);
        }

        if (empty($response['success'])) {
            $response_data = $response['data'] ?? null;
            $message = 'هنگام درخواست ایجاد پرداخت، خطایی رخ داد.';

            if (is_array($response_data)) {
                $flattened = array_map('strval', iterator_to_array(new RecursiveIteratorIterator(new RecursiveArrayIterator($response_data))));
                $flattened = array_filter($flattened, function ($item) {
                    return $item !== '';
                });
                if (!empty($flattened)) {
                    $message .= ' ' . implode(' | ', $flattened);
                }
            } elseif (is_string($response_data) && $response_data !== '') {
                $message .= ' ' . $response_data;
            } elseif (!empty($response['message']) && is_string($response['message'])) {
                $message .= ' ' . $response['message'];
            }

            Dori_Chatbot_Logger::debug('Gateland transaction unsuccessful response: ' . wp_json_encode(array(
                'has_data' => array_key_exists('data', $response),
                'data_type' => gettype($response_data),
                'message' => isset($response['message']) && is_string($response['message']) ? $response['message'] : '',
            )));
            return new WP_REST_Response(array(
                'success' => false,
                'message' => $message,
            ), 500);
        }

        if (
            empty($response['data']) ||
            !is_array($response['data']) ||
            empty($response['data']['payment_link']) ||
            empty($response['data']['authority'])
        ) {
            Dori_Chatbot_Logger::debug('Gateland transaction missing required fields');
            return new WP_REST_Response(array(
                'success' => false,
                'message' => 'پاسخ درگاه پرداخت ناقص است.',
            ), 500);
        }

        $authority = $response['data']['authority'];

        return new WP_REST_Response(array(
            'success' => true,
            'payment_link' => esc_url_raw($response['data']['payment_link']),
            'authority' => $authority,
            'order_id' => $order_id,
            'secret' => $secret,
        ), 200);
    }

    public static function handle_verify_transaction_endpoint(WP_REST_Request $request): WP_REST_Response
    {
        $authority = $request['authority'];
        $secret = sanitize_text_field($request['secret']);
        $order_id = sanitize_text_field($request['order_id']);

        if (empty($request['order_id']) || !hash_equals(hash('crc32', $order_id . AUTH_KEY), $secret)) {
            Dori_Chatbot_Logger::debug('Gateland verify failed because callback secret mismatch');
            return new WP_REST_Response(array(
                'status' => 'failed',
                'message' => 'داده دریافتی، نامعتبر است.',
            ), 500);
        }

        $response = Pay::verify($authority, self::MORI_CLIENT);
        $is_success = $response['success'];
        $gateway_status = $response['data']['status'];

        if ($gateway_status !== 'paid' || empty($response) || !isset($response['success'], $response['data']['status'])) {
            Dori_Chatbot_Logger::debug('Gateland verify failed for authority=' . sanitize_text_field((string) $authority));
            $message = "تراکنش لغو شده و یا خطای غیر منتظره ای رخ داده است.  شماره پیگیری تراکنش: $authority";
            return new WP_REST_Response(array(
                'status' => 'failed',
                'message' => $message,
            ), 500);
        }

        $tags = array(
            '{authority}' => $authority,
            '{gateway}' => $response['data']['gateway'],
            '{trans_id}' => $response['data']['trans_id'],
            '{card_number}' => $response['data']['card_number'],
            '{amount}' => number_format_i18n($response['data']['amount']),
            '{currency_title}' => 'تومان',
        );

        if ($is_success) {
            $lines = array(
                'پرداخت موفقیت آمیز بود.',
                'شناسه پیگیری: {trans_id}',
                'درگاه: {gateway}',
                'مبلغ: {amount} {currency_title}',
            );
        } else {
            $lines = array('تراکنش، قبلا پرداخت شده است.');
        }

        $lines[] = 'شناسه تراکنش: {authority}';

        if ($response['data']['card_number']) {
            $lines[] = 'شماره کارت: {card_number}';
        }

        $message = self::tags(implode(' | ', $lines), $tags);

        return new WP_REST_Response(array(
            'status' => 'success',
            'message' => $message,
        ), 200);
    }

    public static function tags(string $message, array $tags)
    {
        return str_replace(array_keys($tags), array_values($tags), $message);
    }

    public static function gateway_listing_endpoint(): WP_REST_Response
    {
        $gateways = array();
        $activated_mapping = array_column(self::$active_gateways, 'id', 'name');

        foreach (GatewayService::loaded() as $gateway) {
            $name = $gateway->name();

            if (!isset($activated_mapping[$name])) {
                continue;
            }

            $gateways[] = array(
                'id' => $activated_mapping[$name],
                'class' => get_class($gateway),
                'name' => $name,
                'description' => $gateway->description(),
                'url' => $gateway->url(),
                'icon' => $gateway->icon(),
                'features' => GatewayService::get_features($gateway),
            );
        }

        return new WP_REST_Response(array(
            'gateways' => $gateways,
        ));
    }

    public static function validate_client_credentials(WP_REST_Request $request)
    {
        $authorization = $request->get_header('authorization');

        if (empty($authorization)) {
            return new WP_Error('unauthorized', 'توکن احراز هویت شما یافت نشد.', array('status' => 401));
        }

        $credentials = Dori_Chatbot_Cache_Manager::get_api_credentials();

        if (!$credentials) {
            return new WP_Error('forbidden', 'Invalid client credentials', array('status' => 403));
        }

        $secret_string = $credentials['client_id'] . $credentials['client_secret'];

        if (!hash_equals($secret_string, $authorization)) {
            return new WP_Error('forbidden', 'Invalid client credentials', array('status' => 403));
        }

        return true;
    }
}
