package sshconf

import (
	"os"
	"path/filepath"
	"testing"
)

func TestParseWithIncludeAndTags(t *testing.T) {
	dir := t.TempDir()
	incDir := filepath.Join(dir, "conf.d")
	if err := os.MkdirAll(incDir, 0o755); err != nil {
		t.Fatal(err)
	}

	main := `# global defaults
Host *
    ServerAliveInterval 60

# tag: prod, riedel
Host web1 web2
    HostName 10.0.0.5
    User deploy
    Port 2222
    ProxyJump bastion

Include conf.d/*.conf

Host bastion
    HostName bastion.example.com
    User admin
`
	inc := `# tag: staging
Host stage
    HostName stage.example.com
    User dev = ignored
Host = eqform
    HostName eq.example.com
`
	if err := os.WriteFile(filepath.Join(dir, "config"), []byte(main), 0o644); err != nil {
		t.Fatal(err)
	}
	if err := os.WriteFile(filepath.Join(incDir, "a.conf"), []byte(inc), 0o644); err != nil {
		t.Fatal(err)
	}

	hosts, err := Parse(filepath.Join(dir, "config"))
	if err != nil {
		t.Fatal(err)
	}

	byAlias := map[string]Host{}
	for _, h := range hosts {
		byAlias[h.Alias] = h
	}

	// Wildcard "Host *" must not appear as a connectable target.
	if _, ok := byAlias["*"]; ok {
		t.Error("wildcard host * should be skipped")
	}

	// Multiple aliases in one block share settings and tags.
	for _, a := range []string{"web1", "web2"} {
		h, ok := byAlias[a]
		if !ok {
			t.Fatalf("missing host %s", a)
		}
		if h.HostName != "10.0.0.5" || h.User != "deploy" || h.Port != "2222" || h.ProxyJump != "bastion" {
			t.Errorf("%s wrong fields: %+v", a, h)
		}
		if len(h.Tags) != 2 || h.Tags[0] != "prod" || h.Tags[1] != "riedel" {
			t.Errorf("%s wrong tags: %v", a, h.Tags)
		}
	}

	// Included file's host and its tag.
	stage, ok := byAlias["stage"]
	if !ok {
		t.Fatal("included host 'stage' missing")
	}
	if len(stage.Tags) != 1 || stage.Tags[0] != "staging" {
		t.Errorf("stage tags wrong: %v", stage.Tags)
	}

	// "Host = eqform" equals-form should parse the alias.
	if _, ok := byAlias["eqform"]; !ok {
		t.Error("equals-form Host 'eqform' missing")
	}

	// Ordering: web1 before included stage before bastion.
	order := []string{}
	for _, h := range hosts {
		order = append(order, h.Alias)
	}
	t.Logf("order: %v", order)
}

func TestParseMissingConfig(t *testing.T) {
	hosts, err := Parse(filepath.Join(t.TempDir(), "does-not-exist"))
	if err != nil {
		t.Fatalf("missing config should not error: %v", err)
	}
	if hosts != nil {
		t.Errorf("expected nil hosts, got %v", hosts)
	}
}
