<?php

namespace Database\Seeders;

use App\Services\AgentSettlement\AgentSettlementBillAdjustmentService;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

/**
 * 为结算中心「调账 / 冲正」Tab 写入代理账单补差、冲正演示数据。
 *
 * ```bash
 * php artisan db:seed --class="Database\\Seeders\\AgentSettlementAdjustmentDemoSeeder"
 * ```
 */
final class AgentSettlementAdjustmentDemoSeeder extends Seeder
{
    private const DEMO_REASON_PREFIX = '[demo]';

    public function run(): void
    {
        if (app()->environment('production') && ! config('app.debug')) {
            $this->command?->warn('跳过：production 且 APP_DEBUG=false 时不写入演示调账数据。');

            return;
        }

        $adminUserId = (int) (DB::table('admin_users')->where('username', 'admin')->value('id') ?? 0);
        /** @var AgentSettlementBillAdjustmentService $adjustments */
        $adjustments = app(AgentSettlementBillAdjustmentService::class);

        $scenarios = [
            [
                'original_bill_id' => 35,
                'amount' => 12000,
                'adjustment_type' => 'adjustment',
                'reason' => self::DEMO_REASON_PREFIX.' 代理 good 回水漏计，人工补差',
                'confirm' => false,
            ],
            [
                'original_bill_id' => 34,
                'amount' => -5600,
                'adjustment_type' => 'reversal',
                'reason' => self::DEMO_REASON_PREFIX.' 代理 321321 占成分摊复核有误，冲正',
                'confirm' => true,
            ],
            [
                'original_bill_id' => 31,
                'amount' => 800,
                'adjustment_type' => 'adjustment',
                'reason' => self::DEMO_REASON_PREFIX.' 代理 good 平台四舍五入补差',
                'confirm' => false,
            ],
        ];

        DB::transaction(function () use ($scenarios, $adjustments, $adminUserId): void {
            foreach ($scenarios as $scenario) {
                $this->seedScenario($adjustments, $adminUserId, $scenario);
            }
        });

        $this->command?->info('代理结算补差/冲正演示数据已写入（前缀 '.self::DEMO_REASON_PREFIX.'）。');
    }

    /**
     * @param  array{original_bill_id:int,amount:int,adjustment_type:string,reason:string,confirm:bool}  $scenario
     */
    private function seedScenario(
        AgentSettlementBillAdjustmentService $adjustments,
        int $adminUserId,
        array $scenario,
    ): void {
        $originalBillId = (int) $scenario['original_bill_id'];
        $reason = (string) $scenario['reason'];

        if ($this->demoAdjustmentExists($originalBillId, $reason)) {
            $this->command?->line("跳过 bill #{$originalBillId}：已存在相同演示记录。");

            return;
        }

        $original = DB::table('settlement_bills')->where('id', $originalBillId)->first();
        if ($original === null) {
            $this->command?->warn("跳过 bill #{$originalBillId}：原账单不存在。");

            return;
        }

        if ((string) $original->bill_type !== 'agent') {
            $this->command?->warn("跳过 bill #{$originalBillId}：非代理账单。");

            return;
        }

        if ($original->locked_at === null) {
            DB::table('settlement_bills')->where('id', $originalBillId)->update([
                'locked_at' => now(),
                'updated_at' => now(),
            ]);
        }

        if ((string) $original->status === 'pending_confirm') {
            DB::table('settlement_bills')->where('id', $originalBillId)->update([
                'status' => 'confirmed',
                'confirmed_at' => now(),
                'locked_at' => now(),
                'updated_at' => now(),
            ]);
        }

        $newBillId = $adjustments->createAdjustment(
            $originalBillId,
            (int) $scenario['amount'],
            (string) $scenario['adjustment_type'],
            $reason,
            $adminUserId,
        );

        if ($scenario['confirm']) {
            $now = now();
            DB::table('settlement_bills')->where('id', $newBillId)->update([
                'status' => 'confirmed',
                'confirmed_at' => $now,
                'locked_at' => $now,
                'updated_at' => $now,
            ]);
        }

        $this->command?->line(sprintf(
            '已创建 %s bill #%d ← 原代理账单 #%d（%s）',
            (string) $scenario['adjustment_type'],
            $newBillId,
            $originalBillId,
            $reason,
        ));
    }

    private function demoAdjustmentExists(int $originalBillId, string $reason): bool
    {
        return DB::table('settlement_adjustments')
            ->where('original_bill_id', $originalBillId)
            ->where('reason', $reason)
            ->exists();
    }
}
