<?php

/**
 * 文件功能：节日福利前台领取控制器
 *
 * 用户通过聊天室内弹窗点击"立即领取"调用此接口，
 * 完成金币入账并返回领取结果。
 *
 * @author  ChatRoom Laravel
 *
 * @version 1.0.0
 */

namespace App\Http\Controllers;

use App\Enums\CurrencySource;
use App\Models\HolidayClaim;
use App\Models\HolidayEventRun;
use App\Services\UserCurrencyService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

/**
 * 类功能：处理节日福利批次的前台领取与状态查询。
 */
class HolidayController extends Controller
{
    /**
     * 注入用户金币服务。
     */
    public function __construct(
        private readonly UserCurrencyService $currency,
    ) {}

    /**
     * 用户领取节日福利红包。
     *
     * 从 holiday_claims 中查找当前用户在指定批次下的待领取记录，
     * 入账金币并更新批次统计数据。
     */
    public function claim(Request $request, HolidayEventRun $run): JsonResponse
    {
        $user = $request->user();

        // 批次是否在领取有效期内。
        if (! $run->isClaimable()) {
            return response()->json(['ok' => false, 'message' => '活动已结束或已过期。']);
        }

        return DB::transaction(function () use ($run, $user): JsonResponse {
            /** @var HolidayEventRun|null $lockedRun */
            $lockedRun = HolidayEventRun::query()
                ->whereKey($run->id)
                ->lockForUpdate()
                ->first();

            if (! $lockedRun || ! $lockedRun->isClaimable()) {
                return response()->json(['ok' => false, 'message' => '活动已结束或已过期。']);
            }

            /** @var HolidayClaim|null $claim */
            $claim = HolidayClaim::query()
                ->where('run_id', $lockedRun->id)
                ->where('user_id', $user->id)
                ->lockForUpdate()
                ->first();

            if (! $claim) {
                return response()->json(['ok' => false, 'message' => '您不在本次福利名单内，或活动已结束。']);
            }

            // claimed_at 不为空代表本轮已领过，直接返回幂等提示。
            if ($claim->claimed_at !== null) {
                return response()->json([
                    'ok' => false,
                    'message' => '您已领取过本轮福利。',
                    'amount' => $claim->amount,
                ]);
            }

            // 金币入账。
            $this->currency->change(
                $user,
                'gold',
                $claim->amount,
                CurrencySource::HOLIDAY_BONUS,
                "节日福利：{$lockedRun->event_name}",
            );

            // 领取成功后只更新 claimed_at，不再删除记录，便于幂等和历史追踪。
            $claim->update(['claimed_at' => now()]);

            // 批次领取统计按成功领取次数累计。
            $lockedRun->increment('claimed_count');
            $lockedRun->increment('claimed_amount', $claim->amount);

            $remainingPendingClaims = HolidayClaim::query()
                ->where('run_id', $lockedRun->id)
                ->whereNull('claimed_at')
                ->count();

            if ($remainingPendingClaims === 0) {
                $lockedRun->update(['status' => 'completed']);
            }

            return response()->json([
                'ok' => true,
                'message' => "🎉 恭喜！已领取 {$claim->amount} 金币！",
                'amount' => $claim->amount,
            ]);
        });
    }

    /**
     * 查询当前用户在指定批次中的待领取状态。
     */
    public function status(Request $request, HolidayEventRun $run): JsonResponse
    {
        $user = $request->user();

        $claim = HolidayClaim::query()
            ->where('run_id', $run->id)
            ->where('user_id', $user->id)
            ->first();

        return response()->json([
            'claimable' => $claim !== null && $claim->claimed_at === null && $run->isClaimable(),
            'claimed' => $claim?->claimed_at !== null,
            'amount' => $claim?->amount ?? 0,
            'status' => $run->status,
            'expires_at' => $run->expires_at?->toIso8601String(),
        ]);
    }
}
