<?php

namespace App\Console\Commands;

use App\Models\AgentNode;
use App\Services\Agent\AgentNodeService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

/**
 * 清空信用占成盘代理业务数据，并删除所有非根代理节点（保留各站点 depth=0 根节点）。
 *
 * 不删：期号、注单、钱包玩家、站点财务账号。
 */
final class PurgeAgentDataCommand extends Command
{
    protected $signature = 'lottery:purge-agent-data
                            {--dry-run : 只预览，不写入}
                            {--force : 跳过交互确认（危险）}';

    protected $description = '清空代理账期/授信流水，删除全部非根代理（保留站点根节点）';

    public function handle(AgentNodeService $agentNodeService): int
    {
        $dryRun = (bool) $this->option('dry-run');
        $force = (bool) $this->option('force');

        $connection = (string) config('database.default');
        $database = (string) config('database.connections.'.$connection.'.database');
        $environment = (string) config('app.env');

        $nonRootAgents = AgentNode::query()
            ->where('depth', '>', 0)
            ->orderByDesc('depth')
            ->orderByDesc('id')
            ->get();

        $nonRootIds = $nonRootAgents->pluck('id')->map(static fn ($id): int => (int) $id)->all();

        $rootBySite = DB::table('agent_nodes')
            ->where('depth', 0)
            ->get(['id', 'admin_site_id'])
            ->groupBy('admin_site_id')
            ->map(static fn ($rows) => (int) $rows->first()->id);

        $playersToReassign = $nonRootIds === []
            ? 0
            : (int) DB::table('players')->whereIn('agent_node_id', $nonRootIds)->count();

        $metrics = [
            ['Database', $connection.' / '.$database],
            ['Environment', $environment],
            ['Non-root agents', (string) count($nonRootIds)],
            ['Players to reassign to root', (string) $playersToReassign],
            ['settlement_periods', (string) DB::table('settlement_periods')->count()],
            ['settlement_bills', (string) DB::table('settlement_bills')->count()],
            ['payment_records', (string) DB::table('payment_records')->count()],
            ['settlement_adjustments', (string) DB::table('settlement_adjustments')->count()],
            ['rebate_records', (string) DB::table('rebate_records')->count()],
            ['share_ledger', (string) DB::table('share_ledger')->count()],
            ['credit_ledger', (string) DB::table('credit_ledger')->count()],
            ['agent_delegation_grants', (string) DB::table('agent_delegation_grants')->count()],
        ];

        $this->table(['Metric', 'Value'], $metrics);

        if ($nonRootAgents->isNotEmpty()) {
            $this->line('Non-root agents to delete:');
            foreach ($nonRootAgents as $node) {
                $this->line(sprintf(
                    '  - #%d depth=%d %s (%s)',
                    (int) $node->id,
                    (int) $node->depth,
                    (string) $node->code,
                    (string) $node->name,
                ));
            }
        }

        if ($dryRun) {
            $this->info('Dry run only — no changes written.');

            return self::SUCCESS;
        }

        if (! $force && ! $this->confirm('This permanently deletes agent settlement data and non-root agents. Continue?', false)) {
            $this->warn('Aborted.');

            return self::FAILURE;
        }

        DB::transaction(function () use ($agentNodeService, $nonRootAgents, $nonRootIds, $rootBySite): void {
            DB::table('settlement_adjustments')->delete();
            DB::table('payment_records')->delete();
            DB::table('rebate_allocations')->delete();
            DB::table('rebate_records')->delete();
            DB::table('share_ledger')->delete();
            DB::table('settlement_bills')->delete();
            DB::table('settlement_periods')->delete();
            DB::table('credit_ledger')->delete();

            DB::table('player_credit_accounts')->update([
                'used_credit' => 0,
                'frozen_credit' => 0,
                'updated_at' => now(),
            ]);

            DB::table('agent_profiles')->update([
                'allocated_credit' => 0,
                'used_credit' => 0,
                'updated_at' => now(),
            ]);

            if ($nonRootIds !== []) {
                DB::table('agent_delegation_grants')
                    ->whereIn('parent_agent_id', $nonRootIds)
                    ->orWhereIn('child_agent_id', $nonRootIds)
                    ->delete();

                $players = DB::table('players')
                    ->whereIn('agent_node_id', $nonRootIds)
                    ->get(['id', 'agent_node_id', 'site_code']);

                foreach ($players as $player) {
                    $agentNodeId = (int) $player->agent_node_id;
                    $siteId = (int) (DB::table('agent_nodes')->where('id', $agentNodeId)->value('admin_site_id') ?? 0);
                    $rootId = $rootBySite->get($siteId);
                    if ($rootId === null) {
                        continue;
                    }

                    DB::table('players')
                        ->where('id', (int) $player->id)
                        ->update(['agent_node_id' => $rootId]);
                }

                foreach ($nonRootAgents as $node) {
                    $agentNodeService->destroy($node);
                }
            }
        });

        $this->info('Agent settlement data cleared; non-root agents removed. Root nodes kept.');

        return self::SUCCESS;
    }
}
