<?php

namespace App\Services\AgentSettlement;

use App\Models\AdminUser;
use App\Support\AdminAgentSettlementScope;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

/** 账期维度账单笔数与待办汇总（结算中心看板）。 */
final class AgentSettlementPeriodSummaryService
{
    public function __construct(
        private readonly AgentSettlementPeriodPipelineService $pipelineService,
        private readonly ShareLedgerScopedProfitAggregator $scopedProfitAggregator,
    ) {}
    /**
     * @param  list<int>  $periodIds
     * @return array<int, array<string, int>>
     */
    public function summariesForPeriodIds(array $periodIds, ?AdminUser $admin = null): array
    {
        if ($periodIds === []) {
            return [];
        }

        $query = DB::table('settlement_bills')
            ->whereIn('settlement_period_id', $periodIds);

        if ($admin !== null) {
            AdminAgentSettlementScope::applySubtreeToBillsQuery($query, $admin);
        }

        $rows = $query
            ->groupBy('settlement_period_id')
            ->selectRaw('settlement_period_id')
            ->selectRaw("SUM(CASE WHEN bill_type = 'player' THEN 1 ELSE 0 END) as player_bills")
            ->selectRaw("SUM(CASE WHEN bill_type = 'agent' THEN 1 ELSE 0 END) as agent_bills")
            ->selectRaw("SUM(CASE WHEN bill_type IN ('adjustment', 'reversal') THEN 1 ELSE 0 END) as adjustment_bills")
            ->selectRaw("SUM(CASE WHEN status = 'pending_confirm' THEN 1 ELSE 0 END) as pending_confirm")
            ->selectRaw("SUM(CASE WHEN status IN ('confirmed', 'partial_paid', 'overdue') AND unpaid_amount > 0 THEN 1 ELSE 0 END) as awaiting_payment")
            ->selectRaw("SUM(CASE WHEN status = 'settled' THEN 1 ELSE 0 END) as settled")
            ->selectRaw('COALESCE(SUM(unpaid_amount), 0) as total_unpaid')
            ->selectRaw('COALESCE(SUM(net_amount), 0) as total_net')
            ->get();

        $out = [];
        foreach ($rows as $row) {
            $periodId = (int) $row->settlement_period_id;
            $out[$periodId] = [
                'player_bills' => (int) $row->player_bills,
                'agent_bills' => (int) $row->agent_bills,
                'adjustment_bills' => (int) $row->adjustment_bills,
                'pending_confirm' => (int) $row->pending_confirm,
                'awaiting_payment' => (int) $row->awaiting_payment,
                'settled' => (int) $row->settled,
                'total_unpaid' => (int) $row->total_unpaid,
                'total_net' => (int) $row->total_net,
            ];
        }

        return $out;
    }

    /**
     * @param  Collection<int, object>  $periods
     * @return list<array<string, mixed>>
     */
    public function attachToPeriodRows(Collection $periods, ?AdminUser $admin = null): array
    {
        $ids = $periods->pluck('id')->map(static fn ($id): int => (int) $id)->all();
        $summaries = $this->summariesForPeriodIds($ids, $admin);
        $pipelines = $this->pipelineService->countsForPeriods($periods, $admin);
        $empty = [
            'player_bills' => 0,
            'agent_bills' => 0,
            'adjustment_bills' => 0,
            'pending_confirm' => 0,
            'awaiting_payment' => 0,
            'settled' => 0,
            'total_unpaid' => 0,
            'total_net' => 0,
        ];
        $viewerScope = $this->scopedProfitAggregator->resolveViewer($admin)['scope'];
        $emptyPipeline = [
            'credit_ledger_count' => 0,
            'share_ledger_count' => 0,
            'game_win_loss_total' => 0,
            'win_loss_scope' => $viewerScope,
            'basic_rebate_total' => 0,
            'unsettled_ticket_count' => 0,
        ];

        $items = [];
        foreach ($periods as $period) {
            $row = (array) $period;
            $row['summary'] = $summaries[(int) $period->id] ?? $empty;
            $row['pipeline'] = $pipelines[(int) $period->id] ?? $emptyPipeline;
            $items[] = $row;
        }

        return $items;
    }
}
