package service

import (
	"testing"

	"github.com/ez-api/ez-api/internal/model"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

func newTestDB(t *testing.T) *gorm.DB {
	t.Helper()
	db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
	if err != nil {
		t.Fatalf("open sqlite: %v", err)
	}
	if err := db.AutoMigrate(&model.Master{}, &model.Key{}); err != nil {
		t.Fatalf("migrate: %v", err)
	}
	return db
}

func TestMasterService_CreateAndValidateMasterKey(t *testing.T) {
	db := newTestDB(t)
	svc := NewMasterService(db)

	m, raw, err := svc.CreateMaster("m1", "default", 2, 10)
	if err != nil {
		t.Fatalf("CreateMaster: %v", err)
	}
	if raw == "" {
		t.Fatalf("expected raw master key")
	}
	if m.MasterKeyDigest == "" {
		t.Fatalf("expected master key digest to be set")
	}

	got, err := svc.ValidateMasterKey(raw)
	if err != nil {
		t.Fatalf("ValidateMasterKey: %v", err)
	}
	if got.ID != m.ID {
		t.Fatalf("expected master id %d, got %d", m.ID, got.ID)
	}
}

func TestMasterService_IssueChildKey_RespectsLimit(t *testing.T) {
	db := newTestDB(t)
	svc := NewMasterService(db)

	m, _, err := svc.CreateMaster("m1", "default", 1, 10)
	if err != nil {
		t.Fatalf("CreateMaster: %v", err)
	}

	_, raw1, err := svc.IssueChildKey(m.ID, IssueKeyOptions{
		Group:  "default",
		Scopes: "chat:write",
	})
	if err != nil {
		t.Fatalf("IssueChildKey #1: %v", err)
	}
	if raw1 == "" {
		t.Fatalf("expected raw child key")
	}

	_, _, err = svc.IssueChildKey(m.ID, IssueKeyOptions{
		Group:  "default",
		Scopes: "chat:write",
	})
	if err == nil {
		t.Fatalf("expected child key limit error")
	}
}

func TestMasterService_IssueChildKeyAsAdmin_SetsIssuedBy(t *testing.T) {
	db := newTestDB(t)
	svc := NewMasterService(db)

	m, _, err := svc.CreateMaster("m1", "default", 2, 10)
	if err != nil {
		t.Fatalf("CreateMaster: %v", err)
	}

	key, raw, err := svc.IssueChildKeyAsAdmin(m.ID, IssueKeyOptions{
		Scopes: "chat:write",
	})
	if err != nil {
		t.Fatalf("IssueChildKeyAsAdmin: %v", err)
	}
	if raw == "" {
		t.Fatalf("expected raw child key")
	}
	if key.IssuedBy != "admin" {
		t.Fatalf("expected IssuedBy=admin, got %q", key.IssuedBy)
	}

	var stored model.Key
	if err := db.First(&stored, key.ID).Error; err != nil {
		t.Fatalf("load key: %v", err)
	}
	if stored.IssuedBy != "admin" {
		t.Fatalf("expected stored IssuedBy=admin, got %q", stored.IssuedBy)
	}
}
