<?php

namespace App\Support;

use App\Models\Player;
use App\Models\AgentNode;
use App\Models\AgentProfile;
use App\Models\PlayerWallet;
use Illuminate\Support\Facades\DB;

/** 玩家 API 统一 JSON 形状（列表行 / 详情）。 */
final class PlayerApiPresenter
{
    /** @return array<string, mixed> */
    public static function listItem(Player $player): array
    {
        $wallets = $player->relationLoaded('wallets')
            ? $player->wallets
            : $player->wallets()->get();

        $walletRows = $wallets->map(static fn (PlayerWallet $w): array => [
            'wallet_type' => $w->wallet_type,
            'currency_code' => $w->currency_code,
            'balance' => (int) $w->balance,
            'frozen_balance' => (int) $w->frozen_balance,
            'available_balance' => max(0, (int) $w->balance - (int) $w->frozen_balance),
            'status' => (int) $w->status,
        ])->values()->all();

        $agent = $player->relationLoaded('agentNode')
            ? $player->agentNode
            : ($player->agent_node_id ? $player->agentNode()->first() : null);

        $usesCredit = PlayerFundingMode::usesCredit($player);
        $credit = DB::table('player_credit_accounts')->where('player_id', $player->id)->first();
        $creditLimit = $credit !== null ? (int) $credit->credit_limit : ($usesCredit ? 0 : null);
        $usedCredit = $credit !== null ? (int) $credit->used_credit : ($usesCredit ? 0 : null);
        $availableCredit = $credit !== null
            ? max(0, (int) $credit->credit_limit - (int) $credit->used_credit - (int) $credit->frozen_credit)
            : ($usesCredit ? 0 : null);

        [$rebateRate, $rebateInherited] = self::resolveListRebate($player, $agent);

        return [
            'id' => (int) $player->id,
            ...AgentNodeApiPresenter::embed($agent),
            'site_code' => $player->site_code,
            'site_player_id' => $player->site_player_id,
            'auth_source' => $player->auth_source,
            'funding_mode' => $player->funding_mode,
            'username' => $player->username,
            'nickname' => $player->nickname,
            'default_currency' => $player->default_currency,
            'status' => (int) $player->status,
            'last_login_at' => $player->last_login_at?->toIso8601String(),
            'created_at' => $player->created_at?->toIso8601String(),
            'wallets' => $walletRows,
            'uses_credit' => $usesCredit,
            'credit_limit' => $creditLimit,
            'used_credit' => $usedCredit,
            'available_credit' => $availableCredit,
            'rebate_rate' => $rebateRate,
            'rebate_inherited' => $rebateInherited,
            'risk_tags' => $player->risk_tags ?? [],
            'rebate_profiles' => DB::table('player_rebate_profiles')
                ->where('player_id', $player->id)
                ->orderBy('game_type')
                ->get()
                ->map(static fn (object $row): array => [
                    'game_type' => (string) $row->game_type,
                    'rebate_rate' => round((float) $row->rebate_rate * 100, 4),
                    'extra_rebate_rate' => round((float) $row->extra_rebate_rate * 100, 4),
                    'inherit_from_agent' => (bool) $row->inherit_from_agent,
                ])
                ->all(),
        ];
    }

    /**
     * @return array{0: ?float, 1: bool} rebate rate (ratio) and whether inherited from agent
     */
    private static function resolveListRebate(Player $player, ?AgentNode $agent): array
    {
        $row = DB::table('player_rebate_profiles')
            ->where('player_id', $player->id)
            ->where('game_type', '*')
            ->first();

        if ($row !== null && ! (bool) $row->inherit_from_agent) {
            return [round((float) $row->rebate_rate * 100, 4), false];
        }

        if ($agent !== null) {
            $profile = AgentProfile::query()->where('agent_node_id', $agent->id)->first();

            return [round((float) ($profile?->default_player_rebate ?? 0) * 100, 4), true];
        }

        return [null, false];
    }
}
