<?php

namespace App\Http\Requests\Documents;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Validation\Validator as ValidationValidator;

class AddMensajeReceptorRequest extends FormRequest
{
    protected $stopOnFirstFailure = true;

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

    protected function prepareForValidation(): void
    {
        $this->merge([
            'tipo_documento' => trim((string) $this->input('tipo_documento')),
            'clave' => preg_replace('/\D+/', '', (string) $this->input('clave')),
            'tipo_identificacion_emisor' => trim((string) $this->input('tipo_identificacion_emisor')),
            'numero_cedula_emisor' => preg_replace('/\D+/', '', (string) $this->input('numero_cedula_emisor')),
            'mensaje' => trim((string) $this->input('mensaje')),
            'detalle_mensaje' => trim((string) $this->input('detalle_mensaje')),
            'codigo_actividad' => trim((string) $this->input('codigo_actividad')),
            'condicion_impuesto' => trim((string) $this->input('condicion_impuesto')),
            'total_factura' => $this->input('total_factura'),
            'monto_total_impuesto' => $this->input('monto_total_impuesto'),
            'monto_total_impuesto_acreditar' => $this->input('monto_total_impuesto_acreditar'),
            'monto_total_de_gasto_aplicable' => $this->input('monto_total_de_gasto_aplicable'),
        ]);
    }

    public function rules(): array
    {
        return [
            'tipo_documento' => ['required', Rule::in(['05', '06', '07'])],

            'clave' => ['required', 'string', 'size:50'],
            'tipo_identificacion_emisor' => ['required', Rule::in(['01', '02', '03', '04', '05', '06'])],
            'numero_cedula_emisor' => ['required', 'string', 'min:9', 'max:20'],

            'fecha_emision_doc' => ['nullable', 'date'],

            'mensaje' => ['required', Rule::in(['1', '2', '3'])],
            'detalle_mensaje' => [
                'nullable',
                'string',
                'min:5',
                'max:160',
                Rule::requiredIf(fn () => in_array((string) $this->input('mensaje'), ['2', '3'], true)),
            ],

            'monto_total_impuesto' => ['nullable', 'numeric', 'min:0'],
            'codigo_actividad' => ['nullable', 'string', 'size:6'],
            'condicion_impuesto' => ['nullable', Rule::in(['01', '02', '03', '04', '05'])],
            'monto_total_impuesto_acreditar' => ['nullable', 'numeric', 'min:0'],
            'monto_total_de_gasto_aplicable' => ['nullable', 'numeric', 'min:0'],
            'total_factura' => ['required', 'numeric', 'min:0.00001'],
        ];
    }

    public function withValidator(ValidationValidator $validator): void
    {
        $validator->after(function (ValidationValidator $validator): void {
            $mensaje = (string) $this->input('mensaje');
            $condicion = (string) $this->input('condicion_impuesto');
            $codigoActividad = trim((string) $this->input('codigo_actividad'));

            $montoImpuesto = $this->toNullableFloat($this->input('monto_total_impuesto'));
            $montoAcreditar = $this->toNullableFloat($this->input('monto_total_impuesto_acreditar'));
            $montoGasto = $this->toNullableFloat($this->input('monto_total_de_gasto_aplicable'));
            $totalFactura = $this->toNullableFloat($this->input('total_factura'));

            if ($condicion === '05' && $codigoActividad !== '') {
                $validator->errors()->add('codigo_actividad', 'codigo_actividad no se debe enviar cuando condicion_impuesto es 05.');
            }

            if ($montoImpuesto !== null && $montoAcreditar !== null && $montoAcreditar > $montoImpuesto) {
                $validator->errors()->add('monto_total_impuesto_acreditar', 'monto_total_impuesto_acreditar no puede ser mayor al monto_total_impuesto.');
            }

            if ($totalFactura !== null && $montoGasto !== null && $montoGasto > $totalFactura) {
                $validator->errors()->add('monto_total_de_gasto_aplicable', 'monto_total_de_gasto_aplicable no puede ser mayor al total_factura.');
            }

            if ($mensaje === '3' && trim((string) $this->input('detalle_mensaje')) === '') {
                $validator->errors()->add('detalle_mensaje', 'detalle_mensaje es obligatorio cuando el mensaje es 3.');
            }
        });
    }

    public function messages(): array
    {
        return [
            'detalle_mensaje.required' => 'detalle_mensaje es obligatorio cuando el mensaje es 2 o 3.',
        ];
    }

    protected function failedValidation(Validator $validator)
    {
        throw new HttpResponseException(response()->json([
            'success' => false,
            'errors' => $validator->errors(),
        ], 422));
    }

    private function toNullableFloat(mixed $value): ?float
    {
        if ($value === null || $value === '') {
            return null;
        }

        return is_numeric($value) ? (float) $value : null;
    }
}
