<?php

namespace Modules\Inventory\Http\Requests\Purchase;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Validator;
use Modules\Accounts\Models\ChartOfAccount;
use Modules\Core\Enums\PaymentMethodEnum;
use Modules\Core\Enums\StatusEnum;
use Modules\Core\Traits\FailedValidation;

class UpdatePurchasePaymentRequest extends FormRequest
{
    use FailedValidation;

    protected ?ChartOfAccount $account = null;

    protected function prepareForValidation(): void
    {
        if ($this->filled('account_id')) {
            $this->account = ChartOfAccount::query()
                ->select([
                    'id',
                    'is_group',
                    'is_cash',
                    'is_bank',
                    'status',
                ])
                ->find($this->account_id);
        }
    }

    /**
     * Get the validation rules that apply to the request.
     */

    public function rules(): array
    {
        return [
            'account_id' => [
                'required',
                'integer',
                Rule::exists('chart_of_accounts', 'id')
                    ->where(function ($query) {
                        $query->where('status', StatusEnum::ACTIVE)
                            ->where('is_group', false)
                            ->where(function ($sub) {
                                $sub->where('is_cash', true)
                                    ->orWhere('is_bank', true);
                            });
                    }),
            ],
            'payment_method' => [
                'required',
                Rule::enum(PaymentMethodEnum::class),
            ],
            'payment_date' => ['required','date'],
            'amount' => ['required','numeric','gt:0','decimal:0,2'],
            'reference' => [
                Rule::requiredIf(
                    fn() => $this->payment_method !== PaymentMethodEnum::CASH->value
                ),
                'nullable',
                'string',
                'max:255',
            ],
            'note' => ['nullable','string','max:1000'],
        ];
    }

    public function after(): array
    {
        return [
            function (Validator $validator) {
                if (!$this->account) {
                    return;
                }

                if ($this->payment_method === PaymentMethodEnum::CASH->value && !$this->account->is_cash) {
                    $validator->errors()->add(
                        'account_id',
                        'The selected account must be a cash account for cash payments.'
                    );
                }

                if (
                    in_array(
                        $this->payment_method,
                        [
                            PaymentMethodEnum::BANK->value,
                            PaymentMethodEnum::CHECK->value,
                            PaymentMethodEnum::MOBILE_BANKING->value,
                        ],
                        true
                    )
                    && !$this->account->is_bank
                ) {
                    $validator->errors()->add(
                        'account_id',
                        'The selected account must be a bank account for the selected payment method.'
                    );
                }
            }
        ];
    }

    public function messages(): array
    {
        return [
            'purchase_invoice_id.required' => 'Purchase invoice is required.',
            'purchase_invoice_id.exists' => 'The selected purchase invoice is invalid.',

            'account_id.required' => 'Payment account is required.',
            'account_id.exists' => 'The selected payment account is invalid.',

            'payment_method.required' => 'Payment method is required.',

            'payment_date.required' => 'Payment date is required.',
            'payment_date.date' => 'Please provide a valid payment date.',

            'amount.required' => 'Payment amount is required.',
            'amount.numeric' => 'Payment amount must be numeric.',
            'amount.gt' => 'Payment amount must be greater than zero.',
            'amount.decimal' => 'Payment amount may contain up to 2 decimal places.',

            'reference.required_if' => 'Reference number is required for non-cash payments.',
        ];
    }

    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return true;
    }
}
