package persistence

import (
	"database/sql"
	"testing"
	"time"

	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/permissionstatev1"
)

var (
	permissionStateCreated  = time.Date(2026, 7, 23, 1, 2, 3, 0, time.UTC)
	permissionStateModified = permissionStateCreated.Add(time.Second)
	permissionStateLineage  = []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
)

type permissionStateSchemaRow struct {
	name         string
	columnType   string
	nullable     string
	defaultValue any
	extra        string
}

func permissionStateSchemaRows() []permissionStateSchemaRow {
	return []permissionStateSchemaRow{
		{name: "SingletonKey", columnType: "tinyint(4)", nullable: "NO"},
		{name: "Lineage", columnType: "binary(16)", nullable: "NO"},
		{name: "Revision", columnType: "decimal(20,0)", nullable: "NO"},
		{name: "EnforcementMode", columnType: "varchar(8)", nullable: "NO"},
		{name: "CreatedDate", columnType: "datetime(6)", nullable: "NO", defaultValue: "CURRENT_TIMESTAMP(6)"},
		{name: "LastModifiedDate", columnType: "datetime(6)", nullable: "NO", defaultValue: "current_timestamp(6)"},
	}
}

func newPermissionStateRepositoryForTest(t *testing.T, db *sql.DB, lineageBytes []byte) *PermissionStateRepository {
	t.Helper()
	lineage, err := permissionstatev1.LineageFromBytes(lineageBytes)
	if err != nil {
		t.Fatal(err)
	}
	repository, err := newPermissionStateRepository(db, func() (permissionstatev1.Lineage, error) {
		return lineage, nil
	})
	if err != nil {
		t.Fatal(err)
	}
	return repository
}

func assertPermissionState(
	t *testing.T,
	state PermissionState,
	lineage []byte,
	revision uint64,
	mode PermissionStateEnforcementMode,
) {
	t.Helper()
	if err := state.Validate(); err != nil {
		t.Fatalf("state.Validate(): %v", err)
	}
	if got := state.Version.Lineage().Bytes(); string(got) != string(lineage) {
		t.Fatalf("lineage = %v, want %v", got, lineage)
	}
	if state.Version.Revision() != revision || state.EnforcementMode != mode {
		t.Fatalf("state = revision %d mode %q, want %d/%q", state.Version.Revision(), state.EnforcementMode, revision, mode)
	}
}
