<?php

namespace App\Http\Requests;

use App\Models\CurrencyExchange;
use App\Models\Saraf;
use App\Support\SarafAccountLedger;
use App\Support\SarafPaymentType;
use App\Support\SupplierPaymentMethod;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Validator;

class StoreSarafPaymentRequest extends FormRequest
{
    public function authorize(): bool
    {
        return $this->user()?->can('sarafs.create') === true;
    }

    /**
     * @return array<string, mixed>
     */
    public function rules(): array
    {
        /** @var Saraf $saraf */
        $saraf = $this->route('saraf');

        return [
            'payment_type' => ['required', 'string', Rule::in(SarafPaymentType::values())],
            'currency_exchange_id' => [
                Rule::requiredIf(fn (): bool => $this->input('payment_type') === SarafPaymentType::EXCHANGE),
                'nullable',
                'integer',
                Rule::exists(CurrencyExchange::class, 'id')->where('saraf_id', $saraf->id),
            ],
            'amount' => ['required', 'numeric', 'gt:0'],
            'paid_at' => ['required', 'date'],
            'payment_method' => ['nullable', 'string', Rule::in(SupplierPaymentMethod::values())],
            'reference' => ['nullable', 'string', 'max:255'],
            'notes' => ['nullable', 'string', 'max:2000'],
        ];
    }

    public function withValidator(Validator $validator): void
    {
        $validator->after(function (Validator $validator): void {
            if ($validator->errors()->isNotEmpty()) {
                return;
            }

            /** @var Saraf $saraf */
            $saraf = $this->route('saraf');
            $paymentType = (string) $this->input('payment_type');
            $amount = round((float) $this->input('amount'), 2);

            if ($paymentType === SarafPaymentType::EXCHANGE) {
                /** @var CurrencyExchange|null $exchange */
                $exchange = CurrencyExchange::query()->find((int) $this->input('currency_exchange_id'));

                if ($exchange === null) {
                    return;
                }

                if ($amount > SarafAccountLedger::remainForExchange($exchange) + 0.001) {
                    $validator->errors()->add(
                        'amount',
                        __('Payment cannot exceed the remaining USD on this exchange.'),
                    );
                }

                return;
            }

            if ($amount > SarafAccountLedger::totalRemainForSaraf($saraf) + 0.001) {
                $validator->errors()->add(
                    'amount',
                    __('Payment cannot exceed the total remaining USD on saraf.'),
                );
            }
        });
    }

    /**
     * @return array<string, mixed>
     */
    public function validated($key = null, $default = null): array
    {
        $validated = parent::validated($key, $default);

        return [
            ...$validated,
            'amount' => round((float) $validated['amount'], 2),
        ];
    }
}
