package infra

import (
	"testing"
)

func TestConfigFromEnv(t *testing.T) {
	t.Run("populate string field desde env", func(t *testing.T) {
		type Cfg struct {
			Host string `env:"CFE_HOST"`
		}
		t.Setenv("CFE_HOST", "myhost")
		var c Cfg
		if err := ConfigFromEnv(&c); err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if c.Host != "myhost" {
			t.Errorf("expected myhost, got %q", c.Host)
		}
	})

	t.Run("populate int field con conversion", func(t *testing.T) {
		type Cfg struct {
			Port int `env:"CFE_PORT"`
		}
		t.Setenv("CFE_PORT", "9090")
		var c Cfg
		if err := ConfigFromEnv(&c); err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if c.Port != 9090 {
			t.Errorf("expected 9090, got %d", c.Port)
		}
	})

	t.Run("populate bool field con conversion", func(t *testing.T) {
		type Cfg struct {
			Debug bool `env:"CFE_DEBUG"`
		}
		t.Setenv("CFE_DEBUG", "true")
		var c Cfg
		if err := ConfigFromEnv(&c); err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if !c.Debug {
			t.Error("expected Debug=true")
		}
	})

	t.Run("populate float64 field", func(t *testing.T) {
		type Cfg struct {
			Ratio float64 `env:"CFE_RATIO"`
		}
		t.Setenv("CFE_RATIO", "3.14")
		var c Cfg
		if err := ConfigFromEnv(&c); err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if c.Ratio < 3.13 || c.Ratio > 3.15 {
			t.Errorf("expected ~3.14, got %f", c.Ratio)
		}
	})

	t.Run("populate slice string comma-separated", func(t *testing.T) {
		type Cfg struct {
			Tags []string `env:"CFE_TAGS"`
		}
		t.Setenv("CFE_TAGS", "a,b,c")
		var c Cfg
		if err := ConfigFromEnv(&c); err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if len(c.Tags) != 3 || c.Tags[0] != "a" || c.Tags[2] != "c" {
			t.Errorf("unexpected tags: %v", c.Tags)
		}
	})

	t.Run("valor default usado cuando env no seteada", func(t *testing.T) {
		type Cfg struct {
			Port int `env:"CFE_PORT_DEFAULT" default:"8080"`
		}
		var c Cfg
		if err := ConfigFromEnv(&c); err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if c.Port != 8080 {
			t.Errorf("expected default 8080, got %d", c.Port)
		}
	})

	t.Run("required sin valor retorna error", func(t *testing.T) {
		type Cfg struct {
			APIKey string `env:"CFE_API_KEY_REQUIRED" required:"true"`
		}
		var c Cfg
		err := ConfigFromEnv(&c)
		if err == nil {
			t.Error("expected error for missing required var")
		}
	})

	t.Run("int invalido retorna error descriptivo", func(t *testing.T) {
		type Cfg struct {
			Port int `env:"CFE_PORT_BAD"`
		}
		t.Setenv("CFE_PORT_BAD", "not-a-number")
		var c Cfg
		err := ConfigFromEnv(&c)
		if err == nil {
			t.Error("expected error for invalid int")
		}
	})

	t.Run("puntero nil retorna error", func(t *testing.T) {
		var p *struct{ X string }
		err := ConfigFromEnv(p)
		if err == nil {
			t.Error("expected error for nil pointer")
		}
	})
}
