package decisions

import (
	"context"
	"errors"
	"path/filepath"
	"testing"
	"testing/fstest"

	dbpkg "github.com/operator/command-center/internal/db"
)

func openDecisionsDB(t *testing.T) *Store {
	t.Helper()
	dbPath := filepath.Join(t.TempDir(), "test.db")
	db, err := dbpkg.OpenSQLite(dbPath)
	if err != nil {
		t.Fatalf("OpenSQLite: %v", err)
	}
	t.Cleanup(func() { _ = db.Close() })
	migs, _ := dbpkg.LoadMigrations(fstest.MapFS{
		"008_phase7.sql": {Data: []byte(`
			CREATE TABLE decision_log (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER NOT NULL, decision_type TEXT NOT NULL, subject_type TEXT NOT NULL, subject_id TEXT NOT NULL, recommendation TEXT NOT NULL, confidence REAL, provenance_json TEXT NOT NULL, alternatives_json TEXT, operator_action TEXT, operator_action_at INTEGER);
		`)},
	})
	if _, err := dbpkg.Apply(db, migs); err != nil {
		t.Fatalf("Apply: %v", err)
	}
	return NewStore(db)
}

func TestDecisionInsertListGet(t *testing.T) {
	s := openDecisionsDB(t)
	conf := 0.8
	id, err := s.Insert(context.Background(), InsertParams{
		DecisionType:   "delete_dead_swarms",
		SubjectType:    "system",
		SubjectID:      "3 torrents",
		Recommendation: "Delete 3 dead-swarm torrents (5 GB recoverable)",
		Confidence:     &conf,
		ProvenanceJSON: `{"generated_at":"2026-05-18T12:00:00Z"}`,
	})
	if err != nil {
		t.Fatalf("Insert: %v", err)
	}
	d, err := s.Get(context.Background(), id)
	if err != nil {
		t.Fatalf("Get: %v", err)
	}
	if d.DecisionType != "delete_dead_swarms" || d.Confidence == nil || *d.Confidence != 0.8 {
		t.Errorf("got %+v", d)
	}

	list, err := s.List(context.Background(), "open", 10)
	if err != nil {
		t.Fatalf("List: %v", err)
	}
	if len(list) != 1 {
		t.Fatalf("want 1, got %d", len(list))
	}
}

func TestDecisionSetAction(t *testing.T) {
	s := openDecisionsDB(t)
	id, _ := s.Insert(context.Background(), InsertParams{
		DecisionType: "x", SubjectType: "y", SubjectID: "z",
		Recommendation: "r", ProvenanceJSON: "{}",
	})

	if err := s.SetAction(context.Background(), id, "applied"); err != nil {
		t.Fatalf("SetAction: %v", err)
	}
	d, _ := s.Get(context.Background(), id)
	if d.OperatorAction != "applied" || d.OperatorActionAt == nil {
		t.Errorf("action not set: %+v", d)
	}

	open, _ := s.List(context.Background(), "open", 10)
	if len(open) != 0 {
		t.Errorf("expected 0 open, got %d", len(open))
	}
	applied, _ := s.List(context.Background(), "applied", 10)
	if len(applied) != 1 {
		t.Errorf("expected 1 applied, got %d", len(applied))
	}
}

func TestDecisionSetActionNotFound(t *testing.T) {
	s := openDecisionsDB(t)
	if err := s.SetAction(context.Background(), 999, "applied"); !errors.Is(err, ErrNotFound) {
		t.Errorf("got %v, want ErrNotFound", err)
	}
}
