<?php

/**
 * 文件功能：节日福利领取记录批次化迁移
 *
 * 将领取记录与具体发放批次绑定，并为历史待领取数据补建 run 记录。
 */

use Carbon\CarbonImmutable;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * 升级 holiday_claims 表并回填历史批次。
     */
    public function up(): void
    {
        Schema::table('holiday_claims', function (Blueprint $table) {
            $table->unsignedBigInteger('run_id')->nullable()->after('event_id')->comment('关联发放批次 ID');
            $table->index('event_id');
        });

        Schema::table('holiday_claims', function (Blueprint $table) {
            $table->dropUnique('uq_holiday_event_user');
            $table->dateTime('claimed_at')->nullable()->change();
            $table->foreign('run_id')->references('id')->on('holiday_event_runs')->cascadeOnDelete();
            $table->unique(['run_id', 'user_id'], 'uq_holiday_run_user');
        });

        $now = CarbonImmutable::now();

        $events = DB::table('holiday_events')
            ->whereExists(function ($query) {
                $query->selectRaw('1')
                    ->from('holiday_claims')
                    ->whereColumn('holiday_claims.event_id', 'holiday_events.id');
            })
            ->orderBy('id')
            ->get();

        foreach ($events as $event) {
            $audienceCount = (int) DB::table('holiday_claims')->where('event_id', $event->id)->count();
            $scheduledFor = $event->triggered_at ?? $event->send_at ?? $now->toDateTimeString();
            $expiresAt = $event->expires_at;

            $runStatus = $expiresAt !== null && CarbonImmutable::parse($expiresAt)->isPast()
                ? 'expired'
                : 'active';

            $runId = DB::table('holiday_event_runs')->insertGetId([
                'holiday_event_id' => $event->id,
                'event_name' => $event->name,
                'event_description' => $event->description,
                'total_amount' => $event->total_amount,
                'max_claimants' => $event->max_claimants,
                'distribute_type' => $event->distribute_type,
                'min_amount' => $event->min_amount,
                'max_amount' => $event->max_amount,
                'fixed_amount' => $event->fixed_amount,
                'target_type' => $event->target_type,
                'target_value' => $event->target_value,
                'repeat_type' => $event->repeat_type,
                'scheduled_for' => $scheduledFor,
                'triggered_at' => $event->triggered_at ?? $scheduledFor,
                'expires_at' => $expiresAt,
                'status' => $runStatus,
                'audience_count' => $audienceCount,
                'claimed_count' => 0,
                'claimed_amount' => 0,
                'created_at' => $now,
                'updated_at' => $now,
            ]);

            // 旧结构下表里剩余记录全部表示“尚未领取”，统一迁移为未领取状态。
            DB::table('holiday_claims')
                ->where('event_id', $event->id)
                ->update([
                    'run_id' => $runId,
                    'claimed_at' => null,
                ]);

            if (in_array($event->repeat_type, ['daily', 'weekly', 'monthly'], true) && $event->send_at !== null) {
                $currentSendAt = CarbonImmutable::parse($event->send_at);
                $nextSendAt = match ($event->repeat_type) {
                    'daily' => $currentSendAt->addDay(),
                    'weekly' => $currentSendAt->addWeek(),
                    'monthly' => $currentSendAt->addMonth(),
                    default => $currentSendAt,
                };

                DB::table('holiday_events')
                    ->where('id', $event->id)
                    ->update([
                        'send_at' => $nextSendAt->toDateTimeString(),
                        'status' => 'pending',
                    ]);
            }
        }
    }

    /**
     * 回滚 holiday_claims 的批次化关联。
     */
    public function down(): void
    {
        Schema::table('holiday_claims', function (Blueprint $table) {
            $table->dropUnique('uq_holiday_run_user');
            $table->dropForeign(['run_id']);
            $table->dateTime('claimed_at')->nullable(false)->change();
            $table->dropColumn('run_id');
            $table->dropIndex(['event_id']);
            $table->unique(['event_id', 'user_id'], 'uq_holiday_event_user');
        });
    }
};
