<?php

namespace Modules\Accounts\Http\Requests\Voucher;

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

class UpdateVoucherRequest extends FormRequest
{
    use FailedValidation;

    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        $voucherId = $this->route('voucher')?->id ?? $this->route('voucher');

        return [
            'voucher_no' => ['sometimes', 'nullable', 'string', 'max:255', Rule::unique('account_vouchers', 'voucher_no')->ignore($voucherId)],
            'voucher_date' => ['sometimes', 'date'],
            'voucher_type' => ['sometimes', Rule::in(['Journal', 'Payment', 'Receipt', 'Contra'])],
            'project_id' => ['sometimes', 'nullable', 'integer', 'exists:projects,id'],
            'reference' => ['sometimes', 'string'],
            'status' => ['sometimes', Rule::in(['draft', 'pending'])],
            'lines' => ['required', 'array', 'min:2'],
            'lines.*.account_id' => ['required', 'integer', 'exists:chart_of_accounts,id'],
            'lines.*.debit' => ['required', 'numeric', 'min:0'],
            'lines.*.credit' => ['required', 'numeric', 'min:0'],
            'lines.*.sl_no' => ['nullable', 'integer', 'min:1'],
        ];
    }

    public function withValidator($validator): void
    {
        $validator->after(function ($validator) {
            $lines = collect($this->input('lines', []));
            $debit = 0.0;
            $credit = 0.0;

            foreach ($lines as $index => $line) {
                $lineDebit = (float) ($line['debit'] ?? 0);
                $lineCredit = (float) ($line['credit'] ?? 0);

                if (($lineDebit > 0 && $lineCredit > 0) || ($lineDebit <= 0 && $lineCredit <= 0)) {
                    $validator->errors()->add("lines.$index", 'Each voucher line must have either debit or credit amount.');
                }

                $account = isset($line['account_id']) ? ChartOfAccount::query()->find($line['account_id']) : null;

                if ($account !== null && $account->is_group) {
                    $validator->errors()->add("lines.$index.account_id", 'Posting is allowed only to ledger accounts.');
                }

                $debit += $lineDebit;
                $credit += $lineCredit;
            }

            if (round($debit, 2) !== round($credit, 2)) {
                $validator->errors()->add('lines', 'Total debit must equal total credit.');
            }
        });
    }
}
