<?php

namespace App\Console\Commands;

use App\Models\Player;
use App\Support\PlayerFundingMode;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

final class BackfillCreditSettlementWinsCommand extends Command
{
    protected $signature = 'credit:backfill-settlement-wins
        {--player-id= : 仅回填指定玩家}
        {--ticket-item-id= : 仅回填指定注项}
        {--dry-run : 仅输出将回填的数据，不实际写入}';

    protected $description = '回填历史信用盘中奖但缺失 credit_ledger 中奖流水的数据';

    public function handle(): int
    {
        $playerId = (int) ($this->option('player-id') ?? 0);
        $ticketItemId = (int) ($this->option('ticket-item-id') ?? 0);
        $dryRun = (bool) $this->option('dry-run');

        $query = DB::table('ticket_items as ti')
            ->join('players as p', 'p.id', '=', 'ti.player_id')
            ->leftJoin('credit_ledger as cl', function ($join): void {
                $join->on('cl.ref_id', '=', 'ti.id')
                    ->where('cl.owner_type', '=', 'player')
                    ->where('cl.ref_type', '=', 'ticket_item')
                    ->where('cl.reason', '=', 'game_settlement_win');
            })
            ->where('p.funding_mode', PlayerFundingMode::CREDIT)
            ->where('ti.status', 'settled_win')
            ->where('ti.win_amount', '>', 0)
            ->whereNull('cl.id')
            ->select([
                'ti.id',
                'ti.player_id',
                'ti.win_amount',
                'ti.updated_at',
            ])
            ->orderBy('ti.id');

        if ($playerId > 0) {
            $query->where('ti.player_id', $playerId);
        }

        if ($ticketItemId > 0) {
            $query->where('ti.id', $ticketItemId);
        }

        $rows = $query->get();
        if ($rows->isEmpty()) {
            $this->info('没有发现需要回填的信用盘中奖流水。');

            return self::SUCCESS;
        }

        $this->info('待回填条数：'.$rows->count());

        foreach ($rows as $row) {
            $this->line(sprintf(
                'ticket_item=%d player=%d win=%d',
                (int) $row->id,
                (int) $row->player_id,
                (int) $row->win_amount,
            ));
        }

        if ($dryRun) {
            $this->comment('dry-run 模式，未写入任何数据。');

            return self::SUCCESS;
        }

        DB::transaction(function () use ($rows): void {
            foreach ($rows as $row) {
                $player = Player::query()->find((int) $row->player_id);
                if ($player === null || ! PlayerFundingMode::usesCredit($player)) {
                    continue;
                }

                DB::table('credit_ledger')->insert([
                    'owner_type' => 'player',
                    'owner_id' => (int) $row->player_id,
                    'amount' => (int) $row->win_amount,
                    'reason' => 'game_settlement_win',
                    'ref_type' => 'ticket_item',
                    'ref_id' => (int) $row->id,
                    'created_at' => $row->updated_at ?? now(),
                    'updated_at' => now(),
                ]);
            }
        });

        $this->info('回填完成。');

        return self::SUCCESS;
    }
}
