<?php

namespace App\Services\Ticket;

use App\Models\Player;
use App\Support\PlayerFundingMode;

/**
 * 下注行回水：钱包盘立减实扣；信用盘仅展示账期回水预估，实扣仍按全额占用授信。
 */
final class TicketLineInstantRebateApplicator
{
    public function __construct(
        private readonly InstantRebateResolver $instantRebateResolver,
    ) {}

    /**
     * @param  array<string, mixed>  $evaluated
     * @return array<string, mixed>
     */
    public function apply(Player $player, array $evaluated): array
    {
        $resolved = $this->instantRebateResolver->resolveForPlayer(
            $player,
            (string) $evaluated['play_code'],
            (float) $evaluated['rebate_rate_snapshot'],
        );

        $evaluated['rule_snapshot_json']['base_rebate_rate'] = number_format($resolved['base_rebate_rate'], 4, '.', '');
        $evaluated['rule_snapshot_json']['player_addon_rebate_rate'] = number_format($resolved['player_addon_rebate_rate'], 4, '.', '');
        $evaluated['rule_snapshot_json']['rebate_inherited_from_agent'] = $resolved['inherited_from_agent'];
        $evaluated['rule_snapshot_json']['instant_rebate_applied'] = ! PlayerFundingMode::usesCredit($player);

        $finalRate = $resolved['final_rebate_rate'];
        $evaluated['rebate_rate_snapshot'] = number_format($finalRate, 4, '.', '');

        if (PlayerFundingMode::usesCredit($player)) {
            $evaluated['actual_deduct_amount'] = (int) $evaluated['total_bet_amount'];

            return $evaluated;
        }

        $evaluated['actual_deduct_amount'] = max(
            0,
            (int) floor((int) $evaluated['total_bet_amount'] * (1 - $finalRate)),
        );

        return $evaluated;
    }

    /**
     * 确认弹窗展示用回水：信用盘为账期回水预估，钱包盘为下注立减额。
     *
     * @param  array<string, mixed>  $evaluated
     */
    public function displayRebateAmount(Player $player, array $evaluated): int
    {
        $bet = (int) $evaluated['total_bet_amount'];

        if (PlayerFundingMode::usesCredit($player)) {
            $rate = (float) ($evaluated['rebate_rate_snapshot'] ?? 0);

            return (int) floor($bet * max(0.0, min(1.0, $rate)));
        }

        return max(0, $bet - (int) $evaluated['actual_deduct_amount']);
    }

    /** 落库订单/注单上的即时回水合计（信用盘为 0）。 */
    public function persistedInstantRebateAmount(Player $player, array $evaluated): int
    {
        if (PlayerFundingMode::usesCredit($player)) {
            return 0;
        }

        return $this->displayRebateAmount($player, $evaluated);
    }
}
