package internal

import (
	"testing"
)

func facturaValida() *InvoiceInput {
	return &InvoiceInput{
		Tipo: "alta",
		Factura: FacturaInput{
			EmisorNIF:       "A1234567B", // [A-Z0-9] + 7 dígitos + [A-Z]
			EmisorNombre:    "Empresa Test SL",
			NumSerie:        "INV-2026-001",
			FechaExpedicion: "28-05-2026",
			TipoFactura:     "F1",
			Descripcion:     "Servicios",
			IVA:             []IVAInput{{Base: 100, Cuota: 21, Tipo: 21}},
			ImporteTotal:    121.0,
		},
		Sistema: SistemaInput{
			Nombre:       "MiSistema",
			NIFProveedor: "B9876543C",
			Version:      "1.0",
		},
	}
}

func TestValidateInvoiceInput_EntradaValida(t *testing.T) {
	errs := ValidateInvoiceInput(facturaValida())
	if len(errs) != 0 {
		t.Errorf("entrada válida no debería tener errores, obtuvo: %v", errs)
	}
}

func TestValidateInvoiceInput_TipoVacio(t *testing.T) {
	in := facturaValida()
	in.Tipo = ""
	errs := ValidateInvoiceInput(in)
	if !contieneError(errs, "tipo") {
		t.Error("debería fallar con tipo vacío")
	}
}

func TestValidateInvoiceInput_TipoInvalido(t *testing.T) {
	in := facturaValida()
	in.Tipo = "modificacion"
	errs := ValidateInvoiceInput(in)
	if !contieneError(errs, "tipo") {
		t.Error("debería fallar con tipo inválido")
	}
}

func TestValidateInvoiceInput_NIFVacio(t *testing.T) {
	in := facturaValida()
	in.Factura.EmisorNIF = ""
	errs := ValidateInvoiceInput(in)
	if !contieneError(errs, "emisor_nif") {
		t.Error("debería fallar con NIF vacío")
	}
}

func TestValidateInvoiceInput_NIFFormatoInvalido(t *testing.T) {
	casos := []string{
		"12345678",   // 8 dígitos sin letra final
		"ABCDEFGHI",  // todo letras
		"A1234567",   // empresa sin último carácter
		"123456789",  // 9 dígitos sin letra
		"1234567R",   // 7 dígitos + letra (autónomo necesita 8 dígitos)
		"A123456BC",  // empresa con dos letras al final
		"",
	}
	for _, nif := range casos {
		in := facturaValida()
		in.Factura.EmisorNIF = nif
		errs := ValidateInvoiceInput(in)
		if !contieneError(errs, "emisor_nif") {
			t.Errorf("NIF %q debería ser inválido", nif)
		}
	}
}

func TestValidateInvoiceInput_NIFFormatos_Validos(t *testing.T) {
	casos := []string{
		"A1234567B", // empresa, letra final letra
		"B9876543C", // empresa, letra final letra
		"A12345678", // empresa, letra final dígito
		"53950250R", // autónomo (8 dígitos + letra)
		"12345678Z", // autónomo genérico
		"X1234567L", // NIE (letra inicial + 7 dígitos + letra)
	}
	for _, nif := range casos {
		in := facturaValida()
		in.Factura.EmisorNIF = nif
		errs := ValidateInvoiceInput(in)
		if contieneError(errs, "emisor_nif") {
			t.Errorf("NIF %q debería ser válido", nif)
		}
	}
}

func TestValidateInvoiceInput_FechaFormatoInvalido(t *testing.T) {
	casos := []string{"2026-05-28", "28/05/2026", "2026/05/28", "28-5-2026"}
	for _, fecha := range casos {
		in := facturaValida()
		in.Factura.FechaExpedicion = fecha
		errs := ValidateInvoiceInput(in)
		if !contieneError(errs, "fecha_expedicion") {
			t.Errorf("fecha %q debería ser inválida (esperado dd-mm-yyyy)", fecha)
		}
	}
}

func TestValidateInvoiceInput_TipoFacturaInvalido(t *testing.T) {
	in := facturaValida()
	in.Factura.TipoFactura = "X9"
	errs := ValidateInvoiceInput(in)
	if !contieneError(errs, "tipo_factura") {
		t.Error("debería fallar con tipo de factura inválido")
	}
}

func TestValidateInvoiceInput_TiposFacturaValidos(t *testing.T) {
	for _, tipo := range []string{"F1", "F2", "R1", "R2", "R3", "R4", "R5"} {
		in := facturaValida()
		in.Factura.TipoFactura = tipo
		errs := ValidateInvoiceInput(in)
		if contieneError(errs, "tipo_factura") {
			t.Errorf("tipo de factura %q debería ser válido", tipo)
		}
	}
}

func TestValidateInvoiceInput_IVAVacio(t *testing.T) {
	in := facturaValida()
	in.Factura.IVA = nil
	errs := ValidateInvoiceInput(in)
	if !contieneError(errs, "iva") {
		t.Error("debería fallar sin líneas de IVA")
	}
}

func TestValidateInvoiceInput_ImporteNegativo(t *testing.T) {
	in := facturaValida()
	in.Factura.ImporteTotal = -1.0
	errs := ValidateInvoiceInput(in)
	if !contieneError(errs, "importe_total") {
		t.Error("debería fallar con importe negativo")
	}
}

func TestValidateInvoiceInput_SistemaVacio(t *testing.T) {
	in := facturaValida()
	in.Sistema = SistemaInput{}
	errs := ValidateInvoiceInput(in)
	if len(errs) < 3 {
		t.Errorf("debería fallar con sistema vacío, obtuvo %d errores", len(errs))
	}
}

func contieneError(errs []error, campo string) bool {
	for _, e := range errs {
		if ve, ok := e.(*ValidationError); ok && ve.Field != "" {
			if len(ve.Field) >= len(campo) {
				for i := 0; i <= len(ve.Field)-len(campo); i++ {
					if ve.Field[i:i+len(campo)] == campo {
						return true
					}
				}
			}
		}
	}
	return false
}
