<?php

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

use App\Http\Controllers\Controller;
use App\Services\AgentSettlement\SettlementBillDownlineShareBuilder;
use App\Services\AgentSettlement\SettlementPartyEnrichment;
use App\Support\AdminAgentSettlementScope;
use App\Support\ApiResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

final class AgentSettlementBillShowController extends Controller
{
    public function __construct(
        private readonly SettlementPartyEnrichment $partyEnrichment,
        private readonly SettlementBillDownlineShareBuilder $downlineShareBuilder,
    ) {}

    public function __invoke(Request $request, int $settlement_bill): JsonResponse
    {
        $admin = $request->lotteryAdmin();
        abort_if($admin === null, 401);
        abort_if(! AdminAgentSettlementScope::billAccessible($admin, $settlement_bill), 404);

        $bill = DB::table('settlement_bills')->where('id', $settlement_bill)->first();
        abort_if($bill === null, 404);

        $payments = DB::table('payment_records')
            ->where('settlement_bill_id', $settlement_bill)
            ->orderBy('id')
            ->get();

        $rebateAllocations = DB::table('rebate_allocations')
            ->where('settlement_bill_id', $settlement_bill)
            ->orderBy('id')
            ->get();

        $agentIds = $rebateAllocations
            ->filter(static fn (object $row): bool => (string) $row->participant_type === 'agent')
            ->pluck('participant_id')
            ->map(static fn ($id): int => (int) $id)
            ->filter(static fn (int $id): bool => $id > 0)
            ->unique()
            ->values()
            ->all();
        $agents = $this->partyEnrichment->loadAgents($agentIds);
        $rebateAllocations = $rebateAllocations
            ->map(function (object $row) use ($agents): array {
                $type = (string) $row->participant_type;
                $id = (int) $row->participant_id;

                return [
                    'id' => (int) $row->id,
                    'rebate_record_id' => (int) $row->rebate_record_id,
                    'settlement_bill_id' => (int) $row->settlement_bill_id,
                    'participant_type' => $type,
                    'participant_id' => $id,
                    'participant_label' => $this->partyEnrichment->formatCounterpartyLabel($type, $id, $agents),
                    'actual_share_rate' => (float) $row->actual_share_rate,
                    'allocated_amount' => (int) $row->allocated_amount,
                    'allocation_rule' => (string) $row->allocation_rule,
                ];
            })
            ->values()
            ->all();

        $adjustments = DB::table('settlement_adjustments')
            ->where('original_bill_id', $settlement_bill)
            ->orderByDesc('id')
            ->get();

        $meta = $bill->meta_json ?? null;
        $tierSettlements = null;
        if (is_string($meta) && $meta !== '') {
            $decoded = json_decode($meta, true);
            $tierSettlements = is_array($decoded) ? ($decoded['edge'] ?? $decoded['tier_settlements'] ?? null) : null;
        }

        return ApiResponse::success([
            'bill' => $this->partyEnrichment->enrichBillRow($bill),
            'payments' => $payments,
            'rebate_allocations' => $rebateAllocations,
            'adjustments' => $adjustments,
            'tier_edge' => $tierSettlements,
            'downline_shares' => $this->downlineShareBuilder->forBill($bill),
        ]);
    }
}
