<?php

namespace App\Http\Requests\Documents;

use App\Enums\CodigoDescuento;
use App\Enums\CodigoImpuesto;
use App\Enums\CodigoTarifaIVA;
use App\Enums\CondicionVenta;
use App\Enums\MedioPago;
use App\Enums\Moneda;
use App\Enums\TipoDocumento;
use App\Enums\TipoIdentificacion;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Enum;

class AddDocRequest extends FormRequest
{
    protected $stopOnFirstFailure = true;

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

    protected function prepareForValidation(): void
    {
        $lineas = collect($this->input('lineas', []))
            ->values()
            ->map(function ($linea) {
                $montoTotal = ((float) ($linea['precio_unitario'] ?? 0)) * ((float) ($linea['cantidad'] ?? 0));
                $linea['ind_boniregalia'] = false;

                if (isset($linea['descuentos']) && is_array($linea['descuentos'])) {
                    foreach ($linea['descuentos'] as $index => $discount) {
                        $codigo = (string) ($discount['codigo_descuento'] ?? '');
                        if (in_array($codigo, [CodigoDescuento::REGALIA->value, CodigoDescuento::BONIFICACION->value], true)) {
                            $linea['descuentos'][$index]['monto_descuento'] = round($montoTotal, 5);
                            $linea['ind_boniregalia'] = true;
                        }
                    }
                }

                return $linea;
            });

        $this->merge(['lineas' => $lineas->toArray()]);
    }

    public function rules(): array
    {
        return [
            'tipo_documento' => ['required', Rule::enum(TipoDocumento::class)->only([
                TipoDocumento::FE,
                TipoDocumento::TE,
                TipoDocumento::NC,
                TipoDocumento::ND,
            ])],

            'cod_act_economica_emisor' => ['required', 'regex:/^[0-9]{6}$/'],
            'cod_act_economica_receptor' => ['nullable', 'regex:/^[0-9]{6}$/'],

            'emisor' => ['required', 'array'],
            'emisor.nombre' => ['required', 'string', 'min:5', 'max:100'],
            'emisor.nombre_comercial' => ['nullable', 'string', 'min:3', 'max:80'],
            'emisor.tipo_identificacion' => ['required', new Enum(TipoIdentificacion::class)],
            'emisor.numero_identificacion' => ['required', 'string', 'max:20'],
            'emisor.ubicacion' => ['required', 'array'],
            'emisor.ubicacion.provincia' => ['required', 'regex:/^[1-7]$/'],
            'emisor.ubicacion.canton' => ['required', 'regex:/^[0-9]{2}$/'],
            'emisor.ubicacion.distrito' => ['required', 'regex:/^[0-9]{2}$/'],
            'emisor.ubicacion.sennas' => ['required', 'string', 'min:5', 'max:250'],
            'emisor.correo' => ['required', 'email', 'max:160'],

            'receptor' => ['nullable', 'array'],
            'receptor.nombre' => ['nullable', 'string', 'min:3', 'max:100'],
            'receptor.nombre_comercial' => ['nullable', 'string', 'min:3', 'max:80'],
            'receptor.tipo_identificacion' => ['nullable', new Enum(TipoIdentificacion::class)],
            'receptor.numero_identificacion' => ['nullable', 'string', 'max:20'],
            'receptor.ubicacion' => ['nullable', 'array'],
            'receptor.ubicacion.provincia' => ['nullable', 'regex:/^[1-7]$/'],
            'receptor.ubicacion.canton' => ['nullable', 'regex:/^[0-9]{2}$/'],
            'receptor.ubicacion.distrito' => ['nullable', 'regex:/^[0-9]{2}$/'],
            'receptor.ubicacion.sennas' => ['nullable', 'string', 'min:5', 'max:160'],
            'receptor.telefono' => ['nullable', 'array'],
            'receptor.telefono.cod_pais' => ['nullable', 'digits_between:1,3'],
            'receptor.telefono.numero' => ['nullable', 'digits_between:8,20'],
            'receptor.correo' => ['nullable', 'email', 'max:160'],

            'moneda' => ['required', new Enum(Moneda::class)],
            'tipo_cambio' => ['nullable', 'numeric', 'min:0'],

            'condicion_venta' => ['required', new Enum(CondicionVenta::class)],
            'condicion_venta_otros' => ['nullable', 'string', 'max:100'],
            'plazo_credito' => ['nullable', 'integer', 'min:0', 'max:99999'],

            'lineas' => ['required', 'array', 'min:1'],
            'lineas.*.numero_linea' => ['nullable', 'integer', 'min:1'],
            'lineas.*.cantidad' => ['required', 'numeric', 'gt:0', 'regex:/^\d{1,13}(\.\d{1,3})?$/'],
            'lineas.*.detalle' => ['required', 'string', 'max:200'],
            'lineas.*.precio_unitario' => ['required', 'numeric', 'min:0'],
            'lineas.*.codigo_cabys' => ['required', 'regex:/^[0-9]{13}$/'],
            'lineas.*.unidad_medida' => ['nullable', 'string', 'max:15'],
            'lineas.*.unidad_medida_comercial' => ['nullable', 'string', 'max:20'],

            'lineas.*.descuentos' => ['nullable', 'array'],
            'lineas.*.descuentos.*' => ['array'],
            'lineas.*.descuentos.*.codigo_descuento' => ['required_with:lineas.*.descuentos.*', Rule::enum(CodigoDescuento::class)],
            'lineas.*.descuentos.*.codigo_descuento_otros' => ['nullable', 'string', 'max:100'],
            'lineas.*.descuentos.*.monto_descuento' => ['required_with:lineas.*.descuentos.*', 'numeric', 'min:0'],
            'lineas.*.descuentos.*.naturaleza_descuento' => ['nullable', 'string', 'max:80'],
            'lineas.*.ind_boniregalia' => ['sometimes', 'boolean'],

            'lineas.*.impuestos' => ['required', 'array', 'min:1'],
            'lineas.*.impuestos.*' => ['array'],
            'lineas.*.impuestos.*.codigo' => ['required_with:lineas.*.impuestos.*', Rule::enum(CodigoImpuesto::class)->only([
                CodigoImpuesto::IMPUESTO_AL_VALOR_AGREGADO,
                CodigoImpuesto::IVA_CALCULO_ESPECIAL,
                CodigoImpuesto::IMPUESTO_SELECTIVO_DE_CONSUMO,
                CodigoImpuesto::IMPUESTO_UNICO_A_LOS_COMBUSTIBLES,
                CodigoImpuesto::IMPUESTO_ESPECIFICO_BEBIDAS_ALCOHOLICAS,
                CodigoImpuesto::IMPUESTO_ESPECIFICO_BEBIDAS_ENVASADAS_SIN_ALCOHOL_Y_JABONES,
                CodigoImpuesto::IMPUESTO_A_LOS_PRODUCTOS_DE_TABACO,
                CodigoImpuesto::IMPUESTO_ESPECIFICO_AL_CEMENTO,
                CodigoImpuesto::OTROS,
            ])],
            'lineas.*.impuestos.*.codigo_impuesto_otros' => ['nullable', 'string', 'max:100'],
            'lineas.*.impuestos.*.codigo_tarifa_iva' => ['nullable', Rule::enum(CodigoTarifaIVA::class)],
            'lineas.*.impuestos.*.tarifa' => ['required_with:lineas.*.impuestos.*', 'numeric', 'min:0', 'max:99.99'],

            'medio_pago' => ['required', 'array', 'min:1', 'max:4'],
            'medio_pago.*' => ['array'],
            'medio_pago.*.medio_pago_tipo' => ['required', 'distinct', new Enum(MedioPago::class)],
            'medio_pago.*.medio_pago_total' => ['nullable', 'numeric', 'min:0'],
            'medio_pago.*.medio_pago_otro' => ['nullable', 'string', 'max:100'],

            'info_referencia' => ['nullable', 'array'],
            'info_referencia.tipo_doc' => ['required_with:info_referencia'],
            'info_referencia.clave' => ['required_with:info_referencia', 'string', 'size:50'],
            'info_referencia.fecha_emision' => ['required_with:info_referencia'],
            'info_referencia.codigo' => ['required_with:info_referencia'],
            'info_referencia.razon' => ['required_with:info_referencia', 'string', 'max:255'],
        ];
    }

    public function messages(): array
    {
        return [
            'lineas.*.cantidad.regex' => 'La cantidad debe usar hasta 13 enteros y 3 decimales.',
            'lineas.*.codigo_cabys.regex' => 'El código CAByS debe usar 13 dígitos.',
            'emisor.ubicacion.provincia.regex' => 'La provincia del emisor no es válida.',
            'receptor.ubicacion.provincia.regex' => 'La provincia del receptor no es válida.',
        ];
    }
}
