package verify

import (
	"bytes"
	"strings"
	"testing"

	"github.com/salvacybersec/keyhunter/pkg/storage"
)

func newTestDB(t *testing.T) *storage.DB {
	t.Helper()
	db, err := storage.Open(":memory:")
	if err != nil {
		t.Fatalf("storage.Open(:memory:): %v", err)
	}
	t.Cleanup(func() { _ = db.Close() })
	return db
}

func TestEnsureConsent_GrantedPrevious(t *testing.T) {
	db := newTestDB(t)
	if err := db.SetSetting(ConsentSettingKey, ConsentGranted); err != nil {
		t.Fatalf("seed: %v", err)
	}
	var out bytes.Buffer
	ok, err := EnsureConsent(db, strings.NewReader(""), &out)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !ok {
		t.Errorf("want true, got false")
	}
	if out.Len() != 0 {
		t.Errorf("expected no prompt when previously granted, got %q", out.String())
	}
}

func TestEnsureConsent_TypeYes(t *testing.T) {
	db := newTestDB(t)
	var out bytes.Buffer
	ok, err := EnsureConsent(db, strings.NewReader("yes\n"), &out)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !ok {
		t.Errorf("want true, got false")
	}
	if !strings.Contains(out.String(), "legal implications") {
		t.Errorf("prompt missing 'legal implications': %q", out.String())
	}
	if !strings.Contains(out.String(), "keyhunter legal") {
		t.Errorf("prompt missing 'keyhunter legal': %q", out.String())
	}
	val, found, err := db.GetSetting(ConsentSettingKey)
	if err != nil || !found || val != ConsentGranted {
		t.Errorf("setting not persisted: val=%q found=%v err=%v", val, found, err)
	}
}

func TestEnsureConsent_TypeYesUppercase(t *testing.T) {
	db := newTestDB(t)
	var out bytes.Buffer
	ok, err := EnsureConsent(db, strings.NewReader("YES\n"), &out)
	if err != nil || !ok {
		t.Fatalf("want (true,nil), got (%v,%v)", ok, err)
	}
}

func TestEnsureConsent_TypeNo(t *testing.T) {
	db := newTestDB(t)
	var out bytes.Buffer
	ok, err := EnsureConsent(db, strings.NewReader("no\n"), &out)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if ok {
		t.Errorf("want false, got true")
	}
	val, _, _ := db.GetSetting(ConsentSettingKey)
	if val != ConsentDeclined {
		t.Errorf("want declined, got %q", val)
	}
}

func TestEnsureConsent_Empty(t *testing.T) {
	db := newTestDB(t)
	var out bytes.Buffer
	ok, err := EnsureConsent(db, strings.NewReader("\n"), &out)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if ok {
		t.Errorf("want false, got true")
	}
}

func TestEnsureConsent_DeclinedNotSticky(t *testing.T) {
	db := newTestDB(t)
	if err := db.SetSetting(ConsentSettingKey, ConsentDeclined); err != nil {
		t.Fatalf("seed: %v", err)
	}
	var out bytes.Buffer
	ok, err := EnsureConsent(db, strings.NewReader("yes\n"), &out)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !ok {
		t.Errorf("want true (re-prompted & granted), got false")
	}
	if out.Len() == 0 {
		t.Errorf("expected re-prompt after declined, got no output")
	}
	val, _, _ := db.GetSetting(ConsentSettingKey)
	if val != ConsentGranted {
		t.Errorf("want granted after re-prompt, got %q", val)
	}
}
