package infra

import (
	"testing"
)

func TestConfigValidate(t *testing.T) {
	t.Run("struct valido retorna IsValid true", func(t *testing.T) {
		type Cfg struct {
			Host string `required:"true"`
			Port int    `required:"true"`
		}
		got := ConfigValidate(Cfg{Host: "localhost", Port: 8080})
		if !got.IsValid {
			t.Errorf("expected IsValid=true, errors: %v", got.Errors)
		}
		if len(got.Errors) != 0 {
			t.Errorf("expected no errors, got %v", got.Errors)
		}
	})

	t.Run("campo required vacio acumula error", func(t *testing.T) {
		type Cfg struct {
			Host string `required:"true"`
			Key  string `required:"true"`
		}
		got := ConfigValidate(Cfg{})
		if got.IsValid {
			t.Error("expected IsValid=false")
		}
		if len(got.Errors) != 2 {
			t.Errorf("expected 2 errors, got %d: %v", len(got.Errors), got.Errors)
		}
		for _, e := range got.Errors {
			if e.Tag != "required" {
				t.Errorf("expected tag 'required', got %q", e.Tag)
			}
		}
	})

	t.Run("format email invalido produce error", func(t *testing.T) {
		type Cfg struct {
			Email string `format:"email"`
		}
		got := ConfigValidate(Cfg{Email: "not-an-email"})
		if got.IsValid {
			t.Error("expected IsValid=false")
		}
		if len(got.Errors) == 0 || got.Errors[0].Tag != "format" {
			t.Errorf("expected format error, got %v", got.Errors)
		}
	})

	t.Run("format email valido pasa", func(t *testing.T) {
		type Cfg struct {
			Email string `format:"email"`
		}
		got := ConfigValidate(Cfg{Email: "user@example.com"})
		if !got.IsValid {
			t.Errorf("expected IsValid=true, errors: %v", got.Errors)
		}
	})

	t.Run("format url invalido produce error", func(t *testing.T) {
		type Cfg struct {
			BaseURL string `format:"url"`
		}
		got := ConfigValidate(Cfg{BaseURL: "ftp://bad.url"})
		if got.IsValid {
			t.Error("expected IsValid=false")
		}
		if len(got.Errors) == 0 || got.Errors[0].Tag != "format" {
			t.Errorf("expected format error, got %v", got.Errors)
		}
	})

	t.Run("puntero a struct funciona igual", func(t *testing.T) {
		type Cfg struct {
			Name string `required:"true"`
		}
		got := ConfigValidate(&Cfg{Name: "test"})
		if !got.IsValid {
			t.Errorf("expected IsValid=true, errors: %v", got.Errors)
		}
	})

	t.Run("todos los errores acumulados aunque falle el primero", func(t *testing.T) {
		type Cfg struct {
			A string `required:"true"`
			B string `required:"true"`
			C string `required:"true"`
		}
		got := ConfigValidate(Cfg{})
		if len(got.Errors) != 3 {
			t.Errorf("expected 3 errors, got %d", len(got.Errors))
		}
	})
}
