<?php

namespace App\Http\Controllers\Api\V1\Admin\AgentSettlement;

use App\Http\Controllers\Controller;
use App\Services\AgentSettlement\AgentSettlementReportQueryService;
use App\Support\AdminAgentScope;
use App\Support\AdminAgentSettlementScope;
use App\Support\AgentSettlementPeriodWindow;
use App\Support\ApiResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
final class AgentSettlementReportShowController extends Controller
{
    private const TYPES = [
        'summary',
        'player_win_loss',
        'agent_share',
        'rebate',
        'credit',
        'unpaid_bills',
        'overdue',
        'platform_pnl',
        'draw_period',
    ];

    public function __invoke(Request $request, AgentSettlementReportQueryService $reports): JsonResponse
    {
        $admin = $request->lotteryAdmin();
        abort_if($admin === null, 401);

        $type = (string) $request->query('type', 'summary');
        abort_unless(in_array($type, self::TYPES, true), 404);

        if ($type === 'platform_pnl' && AdminAgentScope::primaryAgentNode($admin) !== null) {
            abort(403, 'admin.agent_cannot_view_platform_pnl');
        }

        $periodId = (int) $request->query('settlement_period_id', 0);
        if ($periodId > 0) {
            abort_if(! AdminAgentSettlementScope::periodAccessible($admin, $periodId), 403);
        }
        $period = $this->resolvePeriod($periodId, $request);

        $data = match ($type) {
            'summary' => $reports->summary($admin, $periodId),
            'player_win_loss' => [
                'items' => $reports->playerWinLoss($admin, $periodId, $period['start'], $period['end']),
            ],
            'agent_share' => [
                'items' => $reports->agentShare($admin, $period['start'], $period['end']),
            ],
            'rebate' => $reports->rebate($admin, $periodId, $period['start'], $period['end']),
            'credit' => $reports->credit($admin),
            'unpaid_bills' => [
                'items' => $reports->unpaidBills($admin, $periodId),
            ],
            'overdue' => [
                'items' => $reports->overdue($admin),
            ],
            'platform_pnl' => $periodId > 0
                ? $reports->platformPnl($admin, $periodId)
                : ['error' => 'settlement_period_id_required'],
            'draw_period' => [
                'items' => $reports->drawPeriod($admin, $period['start'], $period['end']),
            ],
            default => [],
        };

        return ApiResponse::success([
            'type' => $type,
            'settlement_period_id' => $periodId > 0 ? $periodId : null,
            'period_start' => $period['start'],
            'period_end' => $period['end'],
            'data' => $data,
            'footnote' => $type === 'summary'
                ? null
                : 'agent_credit_line_settlement',
        ]);
    }

    /**
     * @return array{start: string, end: string}
     */
    private function resolvePeriod(int $periodId, Request $request): array
    {
        if ($periodId > 0) {
            $row = DB::table('settlement_periods')->where('id', $periodId)->first();
            abort_if($row === null, 404);

            [$start, $end] = AgentSettlementPeriodWindow::boundStrings(
                (string) $row->period_start,
                (string) $row->period_end,
            );

            return ['start' => $start, 'end' => $end];
        }

        $request->validate([
            'period_start' => ['required_with:period_end', 'date'],
            'period_end' => ['required_with:period_start', 'date', 'after_or_equal:period_start'],
        ]);

        $start = $request->query('period_start');
        $end = $request->query('period_end');
        if ($start && $end) {
            return ['start' => (string) $start, 'end' => (string) $end];
        }

        $now = now();

        return [
            'start' => $now->copy()->subDays(7)->toDateTimeString(),
            'end' => $now->toDateTimeString(),
        ];
    }
}
