<?php

namespace App\Support\Marketplace;

use App\Enums\MarketplaceFeeScope;
use App\Enums\MarketplaceFeeValueType;

class MarketplaceFeeCalculator
{
    /**
     * @param  array<string, array{scope: string, value_type: string, value: float|int}>  $fees
     * @param  list<array{quantity: int, subtotal: int}>  $lineItems
     * @return array{
     *     results: array<string, array{amount: int, balance_after: int}>,
     *     total_fee_amount: int,
     *     net_amount: int
     * }
     */
    public function calculate(array $fees, int $totalAmount, array $lineItems): array
    {
        $results = [];
        $balance = $totalAmount;
        $totalFeeAmount = 0;

        foreach ($fees as $key => $ruleData) {
            $amount = $this->calculateFeeAmount(
                MarketplaceFeeRule::fromArray($ruleData),
                $totalAmount,
                $lineItems,
            );

            $balance = max($balance - $amount, 0);
            $totalFeeAmount += $amount;

            $results[$key] = [
                'amount' => $amount,
                'balance_after' => $balance,
            ];
        }

        return [
            'results' => $results,
            'total_fee_amount' => $totalFeeAmount,
            'net_amount' => max($totalAmount - $totalFeeAmount, 0),
        ];
    }

    /**
     * @param  list<array{quantity: int, subtotal: int}>  $lineItems
     */
    private function calculateFeeAmount(MarketplaceFeeRule $rule, int $totalAmount, array $lineItems): int
    {
        if ($rule->scope === MarketplaceFeeScope::TRANSACTION) {
            return $this->calculateFromBasis(
                $rule,
                $totalAmount,
            );
        }

        return (int) collect($lineItems)->sum(function (array $item) use ($rule): int {
            if ($rule->valueType === MarketplaceFeeValueType::FLAT) {
                return (int) round($rule->value * $item['quantity']);
            }

            return (int) round($item['subtotal'] * $rule->value / 100);
        });
    }

    private function calculateFromBasis(MarketplaceFeeRule $rule, int $basis): int
    {
        if ($rule->valueType === MarketplaceFeeValueType::FLAT) {
            return (int) round($rule->value);
        }

        return (int) round($basis * $rule->value / 100);
    }
}
