package infra

import (
	"database/sql"
	"os"
	"path/filepath"
	"testing"

	_ "github.com/mattn/go-sqlite3"
)

// setupTestDB creates a minimal registry.db with apps and analysis tables.
func setupTestDB(t *testing.T, root string) {
	t.Helper()
	dbPath := filepath.Join(root, "registry.db")
	db, err := sql.Open("sqlite3", dbPath)
	if err != nil {
		t.Fatalf("open test db: %v", err)
	}
	defer db.Close()
	_, err = db.Exec(`
		CREATE TABLE apps (
			id       TEXT PRIMARY KEY,
			name     TEXT NOT NULL DEFAULT '',
			dir_path TEXT NOT NULL DEFAULT ''
		);
		CREATE TABLE analysis (
			id       TEXT PRIMARY KEY,
			name     TEXT NOT NULL DEFAULT '',
			dir_path TEXT NOT NULL DEFAULT ''
		);
	`)
	if err != nil {
		t.Fatalf("create tables: %v", err)
	}
}

func TestArtefactDoctor_DetectsMissingDir(t *testing.T) {
	root := t.TempDir()
	setupTestDB(t, root)

	db, _ := sql.Open("sqlite3", filepath.Join(root, "registry.db"))
	defer db.Close()
	db.Exec("INSERT INTO apps (id, name, dir_path) VALUES ('ghost_app', 'ghost', 'apps/ghost_app')")

	checks, err := ArtefactDoctor(root)
	if err != nil {
		t.Fatalf("ArtefactDoctor error: %v", err)
	}
	if len(checks) != 1 {
		t.Fatalf("expected 1 check, got %d", len(checks))
	}
	c := checks[0]
	if c.OK {
		t.Errorf("expected not OK for missing dir, got OK")
	}
	found := false
	for _, iss := range c.Issues {
		if iss == "directory_missing" {
			found = true
		}
	}
	if !found {
		t.Errorf("expected 'directory_missing' issue, got %v", c.Issues)
	}
}

func TestArtefactDoctor_OKArtefact(t *testing.T) {
	root := t.TempDir()
	setupTestDB(t, root)

	// Create a minimal app dir with .git and app.md
	appDir := filepath.Join(root, "apps", "my_app")
	if err := os.MkdirAll(filepath.Join(appDir, ".git"), 0o755); err != nil {
		t.Fatal(err)
	}
	appMd := "---\nname: my_app\ndescription: test app\n---\n"
	if err := os.WriteFile(filepath.Join(appDir, "app.md"), []byte(appMd), 0o644); err != nil {
		t.Fatal(err)
	}
	// Simulate a git repo with upstream by creating a packed-refs with HEAD
	// We won't actually init git, so no_upstream_branch will fire — that's fine.
	// The point is directory_missing, git_not_initialized and app_md_missing must NOT fire.

	db, _ := sql.Open("sqlite3", filepath.Join(root, "registry.db"))
	defer db.Close()
	db.Exec("INSERT INTO apps (id, name, dir_path) VALUES ('my_app_go_tools', 'my_app', 'apps/my_app')")

	checks, err := ArtefactDoctor(root)
	if err != nil {
		t.Fatalf("ArtefactDoctor error: %v", err)
	}
	if len(checks) != 1 {
		t.Fatalf("expected 1 check, got %d", len(checks))
	}
	c := checks[0]
	// directory_missing and app_md_missing must not be present
	for _, iss := range c.Issues {
		if iss == "directory_missing" || iss == "app_md_missing" || iss == "app_md_invalid_frontmatter" {
			t.Errorf("unexpected issue %q in %v", iss, c.Issues)
		}
	}
}
