<?php

declare(strict_types=1);

namespace Kylin\Retail\Services;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
 * 退货退款服务
 *
 * 依据《消费者权益保护法》第二十五条：
 * 经营者采用网络、电视、电话、邮购等方式销售商品，消费者有权
 * 自收到商品之日起七日内退货，且无需说明理由。
 *
 * 依据《电子商务法》第六十一条：
 * 消费者在电子商务平台购买商品，有权自收到商品之日起七日内退货。
 *
 * 不可退货商品（消保法第二十五条第一款）：
 *  - 消费者定作的商品
 *  - 鲜活易腐商品
 *  - 在线下载或已拆封的数字化商品
 *  - 交付的报纸、期刊
 *  - 其他根据商品性质不宜退货的商品
 *
 * 使用方式：
 *   $result = ReturnService::requestReturn($orderId, $reason);
 *   $result = ReturnService::isEligibleForReturn($orderId);
 */
final class ReturnService
{
    /**
     * 法定退货期限（天）
     */
    public const RETURN_PERIOD_DAYS = 7;

    /**
     * 不可退货的商品类型
     */
    private const NON_RETURNABLE_CATEGORIES = [
        'customized',      // 定制商品
        'fresh',           // 鲜活易腐
        'digital',         // 数字商品
        'newspaper',       // 报纸期刊
        'underwear',       // 内衣（卫生原因）
        'opened_software', // 已拆封软件
    ];

    /**
     * 退货状态
     */
    public const STATUS_PENDING = 'pending';
    public const STATUS_APPROVED = 'approved';
    public const STATUS_REJECTED = 'rejected';
    public const STATUS_RETURNING = 'returning';
    public const STATUS_RECEIVED = 'received';
    public const STATUS_REFUNDING = 'refunding';
    public const STATUS_COMPLETED = 'completed';

    /**
     * 检查订单是否可退货
     *
     * @param int $orderId 订单 ID
     * @return array 检查结果
     */
    public static function isEligibleForReturn(int $orderId): array
    {
        // 获取订单信息
        $order = DB::table('orders')->where('id', $orderId)->first();
        if (! $order) {
            return ['eligible' => false, 'reason' => '订单不存在'];
        }

        // 检查订单状态
        if (! in_array($order->status, ['completed', 'paid'], true)) {
            return ['eligible' => false, 'reason' => '订单状态不允许退货'];
        }

        // 检查是否超过 7 天
        $completedAt = $order->completed_at ?? $order->paid_at ?? null;
        if ($completedAt && now()->diffInDays($completedAt) > self::RETURN_PERIOD_DAYS) {
            $days = (int) now()->diffInDays($completedAt);
            return [
                'eligible' => false,
                'reason' => "已超过 {$days} 天，超出法定 7 天无理由退货期限",
                'law' => '《消费者权益保护法》第二十五条',
            ];
        }

        // 检查商品是否属于不可退货类型
        $orderItems = DB::table('order_items')->where('order_id', $orderId)->get();
        $nonReturnable = [];
        foreach ($orderItems as $item) {
            $productCategory = DB::table('products')
                ->where('id', $item->product_id)
                ->value('category');
            if (in_array($productCategory, self::NON_RETURNABLE_CATEGORIES, true)) {
                $nonReturnable[] = $item->product_name ?? "商品 {$item->product_id}";
            }
        }

        if (! empty($nonReturnable)) {
            return [
                'eligible' => false,
                'reason' => '以下商品不支持无理由退货：' . implode('、', $nonReturnable),
                'law' => '《消费者权益保护法》第二十五条第一款',
            ];
        }

        return [
            'eligible' => true,
            'reason' => '订单符合七日无理由退货条件',
            'law' => '《消费者权益保护法》第二十五条',
        ];
    }

    /**
     * 发起退货申请
     *
     * @param int $orderId 订单 ID
     * @param string $reason 退货原因
     * @param array $items 退货商品列表（可选，默认全部退货）
     * @return array 退货结果
     */
    public static function requestReturn(int $orderId, string $reason, array $items = []): array
    {
        // 检查是否可退货
        $eligibility = self::isEligibleForReturn($orderId);
        if (! $eligibility['eligible']) {
            return [
                'success' => false,
                'message' => $eligibility['reason'],
                'law' => $eligibility['law'] ?? null,
            ];
        }

        // 获取订单信息
        $order = DB::table('orders')->where('id', $orderId)->first();
        $orderItems = DB::table('order_items')->where('order_id', $orderId)->get();

        // 计算退款金额
        $refundAmount = 0;
        $returnItems = [];
        $itemIds = $items ? array_column($items, 'id') : $orderItems->pluck('id')->toArray();

        foreach ($orderItems as $item) {
            if (in_array($item->id, $itemIds, true)) {
                $refundAmount += $item->price * $item->quantity;
                $returnItems[] = [
                    'order_item_id' => $item->id,
                    'product_id' => $item->product_id,
                    'product_name' => $item->product_name,
                    'quantity' => $item->quantity,
                    'price' => $item->price,
                ];
            }
        }

        // 创建退货记录
        $returnId = DB::table('returns')->insertGetId([
            'order_id' => $orderId,
            'member_id' => $order->member_id,
            'return_no' => 'RT' . date('YmdHis') . str_pad(mt_rand(1, 9999), 4, '0', STR_PAD_LEFT),
            'status' => self::STATUS_PENDING,
            'reason' => $reason,
            'refund_amount' => $refundAmount,
            'items' => json_encode($returnItems, JSON_UNESCAPED_UNICODE),
            'return_type' => 'no_reason', // 无理由退货
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        // 更新订单状态
        DB::table('orders')->where('id', $orderId)->update([
            'status' => 'refunding',
            'updated_at' => now(),
        ]);

        // 记录审计日志
        Log::info('退货申请已创建', [
            'return_id' => $returnId,
            'order_id' => $orderId,
            'member_id' => $order->member_id,
            'refund_amount' => $refundAmount,
            'reason' => $reason,
            'return_type' => 'no_reason',
            'law' => '《消费者权益保护法》第二十五条',
            'operator' => auth()->user()?->name ?? '用户本人',
            'timestamp' => now()->toDateTimeString(),
        ]);

        self::audit('return_requested', $returnId, [
            'order_id' => $orderId,
            'member_id' => $order->member_id,
            'refund_amount' => $refundAmount,
            'reason' => $reason,
        ]);

        return [
            'success' => true,
            'message' => '退货申请已提交，请等待审核',
            'return_id' => $returnId,
            'refund_amount' => $refundAmount,
            'status' => self::STATUS_PENDING,
            'law' => '《消费者权益保护法》第二十五条',
        ];
    }

    /**
     * 获取退货剩余天数
     *
     * @param int $orderId 订单 ID
     * @return int 剩余天数，-1 表示已过期
     */
    public static function remainingDays(int $orderId): int
    {
        $order = DB::table('orders')->where('id', $orderId)->first();
        if (! $order) {
            return -1;
        }

        $completedAt = $order->completed_at ?? $order->paid_at ?? null;
        if (! $completedAt) {
            return -1;
        }

        $elapsed = (int) now()->diffInDays($completedAt);
        return max(-1, self::RETURN_PERIOD_DAYS - $elapsed);
    }

    /**
     * 合规声明
     */
    public static function complianceNotice(): string
    {
        return '退货服务遵循《消费者权益保护法》第二十五条和《电子商务法》第六十一条。';
    }

    /**
     * 记录退货审计日志
     *
     * 依据《消费者权益保护法》和《电子商务法》，
     * 退货申请、审批、退款等操作需记录审计日志。
     */
    private static function audit(string $event, int $returnId, array $extra = []): void
    {
        if (! class_exists(\Kylin\AuditLog\Models\AuditLog::class)) {
            return;
        }

        try {
            \Kylin\AuditLog\Models\AuditLog::create([
                'event' => $event,
                'model_type' => 'returns',
                'model_id' => $returnId,
                'new_values' => $extra,
                'old_values' => null,
                'user_id' => auth()->id(),
                'ip' => request()?->ip(),
                'url' => request()?->fullUrl(),
                'tag' => 'retail-return',
            ]);
        } catch (\Throwable $e) {
            Log::warning('退货审计日志写入失败', [
                'error' => $e->getMessage(),
                'return_id' => $returnId,
                'event' => $event,
            ]);
        }
    }
}