<?php
/**
 * StablePay 退款管理器
 *
 * @package StablePay_WooCommerce
 */

// 防止直接访问
if (!defined('ABSPATH')) {
    exit;
}

/**
 * StablePay_Refund_Manager 类
 *
 * 负责处理退款请求和退款状态更新
 */
class StablePay_Refund_Manager {
    /**
     * API 客户端
     *
     * @var StablePay_API_Client
     */
    private $api_client;

    /**
     * 日志记录器
     *
     * @var StablePay_Logger
     */
    private $logger;

    /**
     * 构造函数
     *
     * @param StablePay_API_Client $api_client API 客户端
     * @param StablePay_Logger $logger 日志记录器
     */
    public function __construct($api_client, $logger = null) {
        $this->api_client = $api_client;
        $this->logger = $logger ? $logger : new StablePay_Logger();

        // 注册钩子：在退款创建后关联 refund_id
        add_action('woocommerce_order_refunded', array($this, 'link_refund_id_to_refund_record'), 10, 2);

        // 注册钩子：阻止订单状态自动变为 refunded（当有 pending 退款时）
        add_filter('woocommerce_order_fully_refunded_status', array($this, 'prevent_auto_refunded_status'), 10, 2);
    }

    /**
     * 处理退款请求
     *
     * @param WC_Order $order 订单对象
     * @param float $amount 退款金额
     * @param string $reason 退款原因
     * @return bool|WP_Error 成功返回 true，失败返回 WP_Error
     */
    public function process_refund($order, $amount, $reason = '') {
        // 强制写入 error_log 便于调试
        error_log(sprintf('[StablePay] RefundManager.process_refund: order_id=%s, amount=%s', $order->get_id(), $amount));

        // 记录退款请求入口
        $this->logger->info('开始处理退款请求', array(
            'order_id' => $order->get_id(),
            'order_number' => $order->get_order_number(),
            'amount' => $amount,
            'reason' => $reason,
            'order_total' => $order->get_total(),
            'order_status' => $order->get_status(),
            'payment_method' => $order->get_payment_method(),
        ));

        // 验证订单是否可退款
        $validation = $this->validate_refund($order, $amount);
        if (is_wp_error($validation)) {
            $this->logger->warning('退款验证失败', array(
                'order_id' => $order->get_id(),
                'error_code' => $validation->get_error_code(),
                'error_message' => $validation->get_error_message(),
            ));
            return $validation;
        }

        // 获取支付会话 ID
        $session_id = $order->get_meta('_stablepay_session_id');
        if (empty($session_id)) {
            $this->logger->error('订单缺少支付会话 ID', array('order_id' => $order->get_id()));
            return new WP_Error('missing_session_id', __('订单缺少支付会话信息', 'stablepay-woocommerce'));
        }

        // 生成退款 ID
        $refund_id = $this->generate_refund_id($order->get_id());

        // 使用 WooCommerce 订单的原始币种发起退款
        // payplatform 会自动根据订单汇率将原始币种金额换算为实际支付币种金额
        // 例如：订单 0.74 EUR，汇率 1.1738467，实付 0.87 USDT
        //       退款 0.3 EUR → payplatform 自动换算为 0.352 USDT 进行退款
        $currency = $order->get_currency();

        // 构造退款请求参数
        // 注意：API 期望 amount 为字符串类型
        $params = array(
            'charge' => $session_id,
            'refund_id' => $refund_id,
            'amount' => (string)$amount,
            'currency' => $currency,
            'reason' => !empty($reason) ? $reason : 'customer_request',
            'description' => sprintf(__('订单 #%s 退款', 'stablepay-woocommerce'), $order->get_order_number()),
            'metadata' => array(
                'wc_order_id' => $order->get_id(),
                'customer_email' => $order->get_billing_email(),
            ),
        );

        // 记录日志
        $this->logger->info('发起退款请求', array(
            'order_id' => $order->get_id(),
            'amount' => $amount,
            'reason' => $reason,
            'refund_id' => $refund_id,
        ));

        // 调用 API 创建退款
        $response = $this->api_client->create_refund($params);

        // 检查响应
        if (is_wp_error($response)) {
            $this->logger->error('退款请求失败', array(
                'order_id' => $order->get_id(),
                'error' => $response->get_error_message(),
            ));
            return $response;
        }

        // 注意：不在这里调用 wc_create_refund()
        // WooCommerce 的退款流程是：wc_create_refund() -> gateway->process_refund() -> 创建退款记录
        // 如果我们在这里再次调用 wc_create_refund()，会导致重复创建并报 "Invalid refund amount" 错误
        // 退款记录由 WooCommerce 自动创建，我们只需要在订单上保存 StablePay 退款 ID

        // 保存退款 ID 到订单元数据（用于后续 webhook 关联）
        // 同时保存 pending 状态信息，用于阻止订单状态自动变为 refunded
        $order->update_meta_data('_stablepay_last_refund_id', $refund_id);
        $order->update_meta_data('_stablepay_pending_refund_id', $refund_id);
        $order->update_meta_data('_stablepay_pending_refund_amount', (string)$amount);
        $order->save();

        // 添加订单备注
        $order->add_order_note(sprintf(
            __('StablePay 退款已发起（处理中）。退款金额：%s，退款 ID：%s', 'stablepay-woocommerce'),
            wc_price($amount),
            $refund_id
        ));

        $this->logger->info('退款请求成功', array(
            'order_id' => $order->get_id(),
            'refund_id' => $refund_id,
            'amount' => $amount,
        ));

        return true;
    }

    /**
     * 验证订单是否可退款
     *
     * @param WC_Order $order 订单对象
     * @param float $amount 退款金额
     * @return bool|WP_Error 验证通过返回 true，否则返回 WP_Error
     */
    private function validate_refund($order, $amount) {
        $order_id = $order->get_id();

        // 记录验证开始
        $this->logger->debug('开始验证退款条件', array(
            'order_id' => $order_id,
            'amount' => $amount,
            'is_paid' => $order->is_paid(),
            'payment_method' => $order->get_payment_method(),
            'order_date' => $order->get_date_created() ? $order->get_date_created()->format('Y-m-d H:i:s') : null,
        ));

        // 检查订单是否已支付
        if (!$order->is_paid()) {
            $this->logger->debug('验证失败：订单尚未支付', array('order_id' => $order_id));
            return new WP_Error('order_not_paid', __('订单尚未支付', 'stablepay-woocommerce'));
        }

        // 检查订单支付方式
        if ($order->get_payment_method() !== 'stablepay') {
            $this->logger->debug('验证失败：支付方式不是 StablePay', array(
                'order_id' => $order_id,
                'payment_method' => $order->get_payment_method(),
            ));
            return new WP_Error('invalid_payment_method', __('订单支付方式不是 StablePay', 'stablepay-woocommerce'));
        }

        // 检查退款金额
        if ($amount <= 0) {
            $this->logger->debug('验证失败：退款金额无效', array(
                'order_id' => $order_id,
                'amount' => $amount,
            ));
            return new WP_Error('invalid_amount', __('退款金额必须大于 0', 'stablepay-woocommerce'));
        }

        // 注意：不在这里验证可退款金额，因为 WooCommerce 在调用 process_refund 之前
        // 已经验证过了，而且此时退款记录已经创建，get_total_refunded() 已经包含了
        // 当前正在处理的退款金额，会导致验证失败。

        // 检查退款期限（180天）
        $order_date = $order->get_date_created();
        if ($order_date) {
            $days_since_order = (time() - $order_date->getTimestamp()) / (24 * 60 * 60);
            if ($days_since_order > 180) {
                $this->logger->debug('验证失败：超过退款期限', array(
                    'order_id' => $order_id,
                    'days_since_order' => $days_since_order,
                ));
                return new WP_Error('refund_period_expired', __('订单已超过退款期限（180天）', 'stablepay-woocommerce'));
            }
        }

        $this->logger->debug('退款验证通过', array('order_id' => $order_id));
        return true;
    }

    /**
     * 生成退款 ID
     *
     * @param int $order_id 订单 ID
     * @return string 退款 ID
     */
    private function generate_refund_id($order_id) {
        return sprintf('refund_WC%s_%s', $order_id, time());
    }

    /**
     * 获取订单可退款金额
     *
     * @param WC_Order $order 订单对象
     * @return float 可退款金额
     */
    public function get_available_refund_amount($order) {
        $order_total = (float)$order->get_total();
        $refunded_amount = (float)$order->get_total_refunded();
        $available = $order_total - $refunded_amount;

        $this->logger->debug('计算可退款金额', array(
            'order_id' => $order->get_id(),
            'order_total' => $order_total,
            'refunded_amount' => $refunded_amount,
            'available' => $available,
        ));

        return $available;
    }

    /**
     * 检查订单是否可退款
     *
     * @param WC_Order $order 订单对象
     * @return bool 是否可退款
     */
    public function is_refundable($order) {
        $validation = $this->validate_refund($order, 0.01);
        $is_refundable = !is_wp_error($validation);

        $this->logger->debug('检查订单是否可退款', array(
            'order_id' => $order->get_id(),
            'is_refundable' => $is_refundable,
            'validation_error' => is_wp_error($validation) ? $validation->get_error_message() : null,
        ));

        return $is_refundable;
    }

    /**
     * 在退款记录创建后关联 refund_id
     *
     * WooCommerce 的退款流程是：wc_create_refund() 创建退款记录 -> 调用 gateway->process_refund()
     * 此时我们在 process_refund 中已经将 refund_id 保存到订单元数据 _stablepay_last_refund_id
     * 这个钩子在退款流程完成后触发，我们需要将 refund_id 关联到退款记录上
     *
     * @param int $order_id 订单 ID
     * @param int $refund_id WooCommerce 退款记录 ID
     */
    public function link_refund_id_to_refund_record($order_id, $refund_id) {
        $order = wc_get_order($order_id);
        if (!$order) {
            return;
        }

        // 只处理 StablePay 支付方式的订单
        if ($order->get_payment_method() !== 'stablepay') {
            return;
        }

        // 获取最近保存的 StablePay refund_id
        $stablepay_refund_id = $order->get_meta('_stablepay_last_refund_id');
        if (empty($stablepay_refund_id)) {
            $this->logger->warning('无法关联退款记录：找不到 StablePay refund_id', array(
                'order_id' => $order_id,
                'wc_refund_id' => $refund_id,
            ));
            return;
        }

        // 获取退款记录并关联 StablePay refund_id
        $refund = wc_get_order($refund_id);
        if ($refund) {
            $refund->update_meta_data('_stablepay_refund_id', $stablepay_refund_id);
            $refund->update_meta_data('_stablepay_refund_status', 'processing');
            $refund->save();

            $this->logger->info('退款记录已关联 StablePay refund_id', array(
                'order_id' => $order_id,
                'wc_refund_id' => $refund_id,
                'stablepay_refund_id' => $stablepay_refund_id,
            ));
        }
    }

    /**
     * 阻止订单状态自动变为 refunded（当有 pending 退款时）
     *
     * WooCommerce 在退款金额等于订单总额时会自动将订单状态改为 refunded
     * 但 StablePay 的退款是异步处理的，需要等待 webhook 确认
     * 此钩子用于阻止自动状态变更，等待 webhook 处理
     *
     * @param string $status 将要设置的状态
     * @param int $order_id 订单 ID
     * @return string 实际要设置的状态
     */
    public function prevent_auto_refunded_status($status, $order_id) {
        $order = wc_get_order($order_id);
        if (!$order) {
            return $status;
        }

        // 只处理 StablePay 支付方式的订单
        if ($order->get_payment_method() !== 'stablepay') {
            return $status;
        }

        // 检查是否有 pending 的退款
        $pending_refund_id = $order->get_meta('_stablepay_pending_refund_id');
        if (!empty($pending_refund_id)) {
            $this->logger->info('阻止订单状态自动变为 refunded，等待 webhook 确认', array(
                'order_id' => $order_id,
                'pending_refund_id' => $pending_refund_id,
                'original_target_status' => $status,
                'current_status' => $order->get_status(),
            ));
            // 保持当前状态，等待 webhook 确认退款结果
            return $order->get_status();
        }

        return $status;
    }

    /**
     * 清除 pending 退款状态（由 webhook handler 调用）
     *
     * @param WC_Order $order 订单对象
     * @param string $refund_id StablePay 退款 ID
     */
    public static function clear_pending_refund($order, $refund_id) {
        $pending_refund_id = $order->get_meta('_stablepay_pending_refund_id');

        // 验证 refund_id 匹配
        if ($pending_refund_id === $refund_id) {
            $order->delete_meta_data('_stablepay_pending_refund_id');
            $order->delete_meta_data('_stablepay_pending_refund_amount');
            $order->save();
        }
    }

    /**
     * 检查订单是否有 pending 退款
     *
     * @param WC_Order $order 订单对象
     * @return bool 是否有 pending 退款
     */
    public static function has_pending_refund($order) {
        $pending_refund_id = $order->get_meta('_stablepay_pending_refund_id');
        return !empty($pending_refund_id);
    }

    /**
     * 更新订单状态为全额退款（如果适用）
     *
     * 此方法在 webhook 确认退款成功后调用，用于检查是否需要将订单状态更新为 refunded
     *
     * @param WC_Order $order 订单对象
     */
    public static function maybe_update_order_to_refunded($order) {
        // 检查是否还有 pending 退款
        if (self::has_pending_refund($order)) {
            return;
        }

        // 检查是否全额退款
        $order_total = (float)$order->get_total();
        $refunded_amount = (float)$order->get_total_refunded();

        if (abs($order_total - $refunded_amount) < 0.01) {
            // 全额退款，更新订单状态
            $order->update_status('refunded', __('StablePay 全额退款已确认', 'stablepay-woocommerce'));
        }
    }
}
