<?php

namespace App\Data\Pagarme\Order;

use App\Data\Pagarme\Customer\CustomerRequestData as CustomerData;
use App\Data\Pagarme\PagarmeData;
use App\Data\Pagarme\Order\Parts\Request\CreditCardData;
use App\Data\Pagarme\Order\Parts\Request\ItemData;
use App\Data\Pagarme\Order\Parts\Request\PaymentData;
use App\Data\Pagarme\Order\Parts\Request\PixData;
use App\Data\Pagarme\Order\Parts\Request\SplitData;
use App\Data\Pagarme\Order\Parts\Request\SplitOptionsData;
use App\Models\PaymentSplit;
use Illuminate\Support\Collection;

final readonly class OrderRequestData extends PagarmeData
{
    /**
     * @param ItemData[]    $items
     * @param PaymentData[] $payments
     */
    public function __construct(
        public string  $code,
        public array   $items,
        public array   $payments,
        public array   $metadata,
        public ?string $customerId = null,
        public ?string $channel    = null,
        public bool    $closed     = true,

        public ?CustomerData $customer = null,
    ) {
        self::requireFilled($this->code, 'code');

        if (empty($this->items)) {
            throw new \InvalidArgumentException('items nao pode estar vazio.');
        }

        if (empty($this->payments)) {
            throw new \InvalidArgumentException('payments nao pode estar vazio.');
        }

        if (! $this->customerId && ! $this->customer) {
            throw new \InvalidArgumentException('customer ou customer_id e obrigatorio.');
        }
    }

    //

    public static function amountInCents(float $amount): int
    {
        return (int) round($amount * 100);
    }

    /**
     * @param  SplitData[]|null  $split
     */
    public static function creditCardPaymentMethod(CreditCardData $creditCard, ?array $split = null): PaymentData
    {
        return PaymentData::creditCard($creditCard, $split);
    }

    /**
     * @param  SplitData[]|null  $split
     */
    public static function pixPaymentMethod(PixData $pix, ?array $split = null): PaymentData
    {
        return PaymentData::pix($pix, $split);
    }

    /**
     * @param  Collection<PaymentSplit>  $transfers
     * @return SplitData[]
     */
    public static function splitFromTransfers(Collection $transfers): array
    {
        return $transfers
            ->filter(fn (PaymentSplit $split) => ! empty($split->gateway_transfer_target_reference))
            ->map(function (PaymentSplit $split) {
                return new SplitData(
                    amount:      self::amountInCents((float) $split->gross_amount),
                    recipientId: $split->gateway_transfer_target_reference,
                    type:        'flat',

                    options: new SplitOptionsData(
                        chargeProcessingFee: false,
                        chargeRemainderFee:  false,
                        liable:              false,
                    ),
                );
            })
            ->values()
            ->all();
    }

    //

    public function toArray(): array
    {
        return $this->filterFilledRecursive([
            'code'        => $this->code,
            'items'       => $this->items,
            'payments'    => $this->payments,
            'closed'      => $this->closed,
            'metadata'    => $this->metadata,
            'customer_id' => $this->customerId,
            'channel'     => $this->channel,
            'customer'    => $this->customer,
        ]);
    }
}
