<?php

/**
 * 文件功能：商店控制器
 * 提供商品列表查询、商品购买（含赠送特效广播）、改名卡使用 三个接口
 */

namespace App\Http\Controllers;

use App\Events\EffectBroadcast;
use App\Events\MessageSent;
use App\Models\Room;
use App\Models\ShopItem;
use App\Models\UserPurchase;
use App\Services\ChatStateService;
use App\Services\ShopService;
use App\Support\ChatContentSanitizer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class ShopController extends Controller
{
    /**
     * 注入商店服务
     */
    public function __construct(
        private readonly ShopService $shopService,
        private readonly ChatStateService $chatState,
    ) {}

    /**
     * 获取商店商品列表及当前用户状态
     *
     * 返回字段：items（商品列表）、user_jjb（当前金币）、
     *           active_week_effect（当前周卡）、has_rename_card（是否持有改名卡）
     */
    public function items(): JsonResponse
    {
        $user = Auth::user();
        $items = ShopItem::active()->map(fn ($item) => [
            'id' => $item->id,
            'name' => $item->name,
            'slug' => $item->slug,
            'description' => $item->description,
            'icon' => $item->icon,
            'price' => $item->price,
            'type' => $item->type,
            'duration_days' => $item->duration_days,
            'duration_minutes' => $item->duration_minutes,
            'intimacy_bonus' => $item->intimacy_bonus,
            'charm_bonus' => $item->charm_bonus,
        ]);

        $signRepairCard = $items->firstWhere('type', ShopItem::TYPE_SIGN_REPAIR);

        // 统计背包中各戒指持有数量
        $ringCounts = UserPurchase::query()
            ->where('user_id', $user->id)
            ->where('status', 'active')
            ->whereHas('item', fn ($q) => $q->where('type', 'ring'))
            ->selectRaw('shop_item_id, count(*) as qty')
            ->groupBy('shop_item_id')
            ->pluck('qty', 'shop_item_id')
            ->toArray();

        return response()->json([
            'items' => $items,
            'user_jjb' => $user->jjb ?? 0,
            'active_week_effect' => $this->shopService->getActiveWeekEffect($user),
            'has_rename_card' => $this->shopService->hasRenameCard($user),
            'ring_counts' => $ringCounts,
            'auto_fishing_minutes_left' => $this->shopService->getActiveAutoFishingMinutesLeft($user),
            'sign_repair_card_count' => $this->shopService->getSignRepairCardCount($user),
            'sign_repair_card_item' => $signRepairCard,
        ]);
    }

    /**
     * 购买商品
     *
     * 单次特效卡额外支持：
     *   - recipient  接收者用户名（传 "all" 或留空则全员可见）
     *   - message    公屏赠言（可选）
     *
     * @param  Request  $request  含 item_id, recipient?, message?, quantity?
     */
    public function buy(Request $request): JsonResponse
    {
        $request->validate([
            'item_id' => 'required|integer|exists:shop_items,id',
            'room_id' => 'required|integer|exists:rooms,id',
            'recipient' => 'nullable|string|max:50',
            'message' => 'nullable|string|max:120',
            'quantity' => 'nullable|integer|min:1|max:99',
        ]);

        $user = Auth::user();
        $roomId = (int) $request->input('room_id');
        $room = Room::query()->findOrFail($roomId);
        if (! $room->canUserEnter($user) || ! $this->chatState->isUserInRoom($roomId, $user->username)) {
            return response()->json(['status' => 'error', 'message' => '请先进入当前房间后再购买聊天室道具。'], 403);
        }

        $item = ShopItem::find($request->item_id);
        if (! $item->is_active) {
            return response()->json(['status' => 'error', 'message' => '该商品已下架。'], 400);
        }

        $quantity = (int) $request->input('quantity', 1);
        $result = $this->shopService->buyItem($user, $item, $quantity);

        if (! $result['ok']) {
            return response()->json(['status' => 'error', 'message' => $result['message']], 400);
        }

        $response = [
            'status' => 'success',
            'message' => $result['message'],
            'quantity' => $result['quantity'] ?? 1,
            'total_price' => $result['total_price'] ?? $item->price,
        ];

        // ── 单次特效卡：广播给指定用户或全员 ────────────────────────
        if (isset($result['play_effect'])) {
            $recipient = trim($request->input('recipient', ''));     // 空字符串 = 全员
            $message = ChatContentSanitizer::htmlText($request->input('message', ''));

            // recipient 为空或 "all" 表示全员
            $targetUsername = ($recipient === '' || $recipient === 'all') ? null : $recipient;
            $safeTargetUsername = $targetUsername ? ChatContentSanitizer::htmlText($targetUsername) : null;

            // 广播特效事件时保留原始用户名标识，前端需要用它和当前登录名做精确比较。
            broadcast(new EffectBroadcast(
                roomId: $roomId,
                type: $result['play_effect'],
                operator: $user->username,
                targetUsername: $targetUsername,
                giftMessage: $message ?: null,
            ))->toOthers();

            // 同时前端也需要播放（自己也要看到）
            $response['play_effect'] = $result['play_effect'];
            $response['target_username'] = $targetUsername;
            $response['gift_message'] = $message ?: null;

            // 公屏系统消息
            if ($roomId > 0) {
                $icons = [
                    'fireworks' => '🎆',
                    'rain' => '🌧',
                    'lightning' => '⚡',
                    'snow' => '❄️',
                    'sakura' => '🌸',
                    'meteors' => '🌠',
                    'gold-rain' => '🪙',
                    'hearts' => '💖',
                    'confetti' => '🎊',
                    'fireflies' => '✨',
                ];
                // 赠礼消息文案（改成"为XX触发了一场特效"）
                $icon = $icons[$result['play_effect']] ?? '✨';
                $safeBuyer = ChatContentSanitizer::htmlText($user->username);
                $safeItemName = ChatContentSanitizer::htmlText($item->name);
                $toStr = $safeTargetUsername ? "【{$safeTargetUsername}】" : '全体聊友';
                $remarkPart = $message ? " 「{$message}」" : '';
                $sysContent = "{$icon} {$safeBuyer} 为 {$toStr} 燃放了一场【{$safeItemName}】特效！{$remarkPart}";

                // 广播系统消息到公屏（字段名与前端 appendMessage() 保持一致）
                $sysMsgEvent = new MessageSent(
                    roomId: $roomId,
                    message: [
                        'id' => 0,
                        'room_id' => $roomId,
                        'from_user' => '系统传音',   // 触发金色左边框样式（已有处理分支）
                        'to_user' => '大家',
                        'content' => $sysContent,
                        'font_color' => '#cc6600',
                        'sent_at' => now()->format('H:i:s'),
                        'is_secret' => false,
                        'action' => null,
                    ]
                );
                broadcast($sysMsgEvent);
            }
        } else {
            // ── 其他类型：广播购买通知到公屏 ────────────────────────────
            if ($roomId > 0) {
                // auto_fishing 有效期文案（提前算好，避免在 match 内写复杂三元表达式）
                $fishDuration = '';
                if ($item->type === 'auto_fishing') {
                    $mins = (int) ($item->duration_minutes ?? 0);
                    $fishDuration = $mins >= 60 ? floor($mins / 60).'小时' : $mins.'分钟';
                }

                // 自动钓鱼卡购买通知要真正归属到“钓鱼播报”，这样前端屏蔽规则才能直接命中。
                $broadcastFromUser = $item->type === 'auto_fishing' ? '钓鱼播报' : '系统传音';

                // 根据商品类型生成不同通知文案
                $safeBuyer = ChatContentSanitizer::htmlText($user->username);
                $safeItemName = ChatContentSanitizer::htmlText($item->name);
                $sysContent = match ($item->type) {
                    'duration' => "📅 【{$safeBuyer}】购买了全屏特效周卡「{$safeItemName}」，登录时将自动触发！",
                    'one_time' => "🎫 【{$safeBuyer}】购买了「{$safeItemName}」道具！",
                    'ring' => "💍 【{$safeBuyer}】在商店购买了一枚「{$safeItemName}」，不知道打算送给谁呢？",
                    'auto_fishing' => "🎣 【{$safeBuyer}】购买了「{$safeItemName}」，开启了 {$fishDuration} 的自动钓鱼模式！",
                    ShopItem::TYPE_SIGN_REPAIR => "🗓️ 【{$safeBuyer}】购买了 {$quantity} 张「{$safeItemName}」，准备把漏掉的签到补回来！",
                    default => "🛒 【{$safeBuyer}】购买了「{$safeItemName}」。",
                };

                broadcast(new MessageSent(
                    roomId: $roomId,
                    message: [
                        'id' => 0,
                        'room_id' => $roomId,
                        'from_user' => $broadcastFromUser,
                        'to_user' => '大家',
                        'content' => $sysContent,
                        'font_color' => '#7c3aed',
                        'sent_at' => now()->format('H:i:s'),
                        'is_secret' => false,
                        'action' => null,
                    ]
                ));
            }
        }

        // 返回最新金币余额
        $response['jjb'] = $user->fresh()->jjb;

        return response()->json($response);
    }

    /**
     * 使用改名卡修改昵称
     *
     * @param  Request  $request  含 new_name
     */
    public function rename(Request $request): JsonResponse
    {
        $request->validate([
            'new_name' => 'required|string|min:1|max:10',
        ]);

        $result = $this->shopService->useRenameCard(Auth::user(), $request->new_name);

        if (! $result['ok']) {
            return response()->json(['status' => 'error', 'message' => $result['message']], 400);
        }

        return response()->json(['status' => 'success', 'message' => $result['message']]);
    }
}
