<?php

/**
 * 文件功能：聊天室座驾业务服务。
 *
 * 统一管理座驾商品列表、购买续期、当前激活座驾、购买记录和入场欢迎语载荷。
 */

namespace App\Services;

use App\Enums\CurrencySource;
use App\Models\Ride;
use App\Models\User;
use App\Models\UserRidePurchase;
use App\Support\ChatContentSanitizer;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;

/**
 * 聊天室座驾服务
 * 负责通过 rides 与 user_ride_purchases 完成座驾购买、续期、替换与进房展示。
 */
class RideService
{
    /**
     * 构造座驾服务依赖。
     */
    public function __construct(
        private readonly UserCurrencyService $currencyService,
        private readonly ChatUserPresenceService $chatUserPresenceService,
    ) {}

    /**
     * 获取全部上架座驾商品。
     *
     * @return Collection<int, Ride>
     */
    public function activeItems(): Collection
    {
        return Ride::active();
    }

    /**
     * 格式化座驾商品，供前端页面直接渲染。
     *
     * @return array<string, mixed>
     */
    public function formatItem(Ride $item): array
    {
        return [
            'id' => $item->id,
            'name' => $item->name,
            'slug' => $item->slug,
            'ride_key' => $item->rideKey(),
            'description' => $item->description,
            'icon' => $item->icon,
            'price' => $item->price,
            'duration_days' => (int) ($item->duration_days ?? 0),
            'welcome_message' => $item->welcome_message,
        ];
    }

    /**
     * 获取用户当前有效座驾，若已过期则自动标记为 expired。
     */
    public function currentRide(User $user): ?UserRidePurchase
    {
        $purchase = UserRidePurchase::query()
            ->with('ride')
            ->where('user_id', $user->id)
            ->where('status', 'active')
            ->orderByDesc('expires_at')
            ->first();

        if (! $purchase) {
            return null;
        }

        if ($purchase->expires_at && $purchase->expires_at->isPast()) {
            // 过期座驾必须及时落库，避免后续进房继续播放旧特效。
            $purchase->update(['status' => 'expired']);

            return null;
        }

        return $purchase;
    }

    /**
     * 格式化用户当前座驾。
     *
     * @return array<string, mixed>|null
     */
    public function formatCurrentRide(User $user): ?array
    {
        $purchase = $this->currentRide($user);
        if (! $purchase || ! $purchase->ride) {
            return null;
        }

        return $this->formatPurchase($purchase);
    }

    /**
     * 获取用户最近座驾购买记录。
     *
     * @return array<int, array<string, mixed>>
     */
    public function purchaseRecords(User $user, int $limit = 20): array
    {
        return UserRidePurchase::query()
            ->with('ride')
            ->where('user_id', $user->id)
            ->latest()
            ->limit($limit)
            ->get()
            ->map(fn (UserRidePurchase $purchase) => $this->formatPurchase($purchase))
            ->values()
            ->all();
    }

    /**
     * 购买座驾：同款续期，不同款替换旧座驾且不退款。
     *
     * @return array{ok:bool, message:string, current_ride?:array<string, mixed>}
     */
    public function buy(User $user, Ride $item, ?int $roomId = null): array
    {
        if (! $item->is_active) {
            return ['ok' => false, 'message' => '该座驾暂未上架。'];
        }

        $days = (int) ($item->duration_days ?? 0);
        if ($days <= 0) {
            return ['ok' => false, 'message' => '该座驾使用天数配置异常，请联系管理员。'];
        }

        if ($user->jjb < $item->price) {
            return ['ok' => false, 'message' => "金币不足，购买【{$item->name}】需要 {$item->price} 金币，当前仅有 {$user->jjb} 金币。"];
        }

        $purchased = DB::transaction(function () use ($user, $item, $days, $roomId): bool {
            $now = Carbon::now();

            // 先清理已过期的 active 座驾，避免旧状态影响替换判断。
            UserRidePurchase::query()
                ->where('user_id', $user->id)
                ->where('status', 'active')
                ->whereNotNull('expires_at')
                ->where('expires_at', '<=', $now)
                ->update(['status' => 'expired']);

            $activeRide = UserRidePurchase::query()
                ->with('ride')
                ->where('user_id', $user->id)
                ->where('status', 'active')
                ->orderByDesc('expires_at')
                ->first();

            $balanceAfter = $this->currencyService->deductGoldIfEnough(
                $user,
                (int) $item->price,
                CurrencySource::RIDE_BUY,
                "购买聊天室座驾：{$item->name}",
                $roomId,
            );

            if ($balanceAfter === null) {
                return false;
            }

            if ($activeRide && (int) $activeRide->ride_id === (int) $item->id) {
                $baseTime = $activeRide->expires_at && $activeRide->expires_at->greaterThan($now)
                    ? $activeRide->expires_at
                    : $now;

                // 同款续购先取消旧 active，再创建新 active，既保留购买记录，又保持当前座驾唯一。
                $activeRide->update(['status' => 'cancelled']);
                UserRidePurchase::create([
                    'user_id' => $user->id,
                    'ride_id' => $item->id,
                    'status' => 'active',
                    'price_paid' => $item->price,
                    'expires_at' => $baseTime->copy()->addDays($days),
                ]);

                return true;
            }

            if ($activeRide) {
                // 不同座驾替换旧座驾，旧记录保留为 cancelled 供后台追溯。
                $activeRide->update(['status' => 'cancelled']);
            }

            UserRidePurchase::create([
                'user_id' => $user->id,
                'ride_id' => $item->id,
                'status' => 'active',
                'price_paid' => $item->price,
                'expires_at' => $now->copy()->addDays($days),
            ]);

            return true;
        });

        if (! $purchased) {
            return ['ok' => false, 'message' => "金币不足，购买【{$item->name}】需要 {$item->price} 金币，当前仅有 {$user->fresh()->jjb} 金币。"];
        }

        return [
            'ok' => true,
            'message' => "购买成功！{$item->icon} {$item->name} 已激活（{$days}天有效）。",
            'current_ride' => $this->formatCurrentRide($user->fresh()),
        ];
    }

    /**
     * 构建进房座驾欢迎语与特效载荷。
     *
     * @return array<string, string>|null
     */
    public function buildPresencePayload(User $user): ?array
    {
        $purchase = $this->currentRide($user);
        $item = $purchase?->ride;
        $rideKey = $item?->rideKey();

        if (! $purchase || ! $item || ! $rideKey) {
            return null;
        }

        $template = trim((string) ($item->welcome_message ?: '【{name}】驾驶【{ride}】震撼入场，全场请注意！'));
        $rendered = strtr($template, [
            '{name}' => $user->username,
            '{ride}' => $item->name,
        ]);
        $identitySummary = $this->chatUserPresenceService->buildIdentitySummary($user);
        $effectUserInfo = "用户 {$user->username} · {$identitySummary['inline']}";

        return [
            'ride_key' => $rideKey,
            'ride_name' => $item->name,
            'ride_icon' => (string) ($item->icon ?? '🚘'),
            'effect_title' => "乘坐【{$item->name}】闪亮登场",
            'effect_user_info' => $effectUserInfo,
            'identity_text' => ChatContentSanitizer::htmlText($identitySummary['inline']),
            'welcome_text' => ChatContentSanitizer::htmlText($rendered),
        ];
    }

    /**
     * 格式化单条座驾购买记录。
     *
     * @return array<string, mixed>
     */
    private function formatPurchase(UserRidePurchase $purchase): array
    {
        $item = $purchase->ride;

        return [
            'id' => $purchase->id,
            'status' => $purchase->status,
            'price_paid' => (int) $purchase->price_paid,
            'expires_at' => $purchase->expires_at?->toDateTimeString(),
            'used_at' => $purchase->used_at?->toDateTimeString(),
            'created_at' => $purchase->created_at?->toDateTimeString(),
            'item' => $item ? $this->formatItem($item) : null,
        ];
    }
}
