package bootstrap

import (
	"testing"
)

// TestLoginHistoryAdditiveColumnsC3 asserts the 4 NULL-able columns added in C3
// (design doc §2.2) are present on _System_LoginHistory with the expected types.
// All 4 MUST be nullable. Existing columns must remain unchanged
// (additive-only contract).
//
// Divergence note: §2.2 literal says `LogoutTime DATETIME`; per C2.2 precision
// rule we standardize on DATETIME(6) for new audit-time columns.
func TestLoginHistoryAdditiveColumnsC3(t *testing.T) {
	defs := GetSystemTableDefinitions()
	var loginHist *struct {
		columns map[string]struct {
			colType  string
			nullable bool
		}
	}

	for i := range defs {
		if defs[i].TableName != "_System_LoginHistory" {
			continue
		}
		loginHist = &struct {
			columns map[string]struct {
				colType  string
				nullable bool
			}
		}{columns: map[string]struct {
			colType  string
			nullable bool
		}{}}
		for _, c := range defs[i].Columns {
			loginHist.columns[c.Name] = struct {
				colType  string
				nullable bool
			}{colType: c.Type, nullable: c.Nullable}
		}
		break
	}
	if loginHist == nil {
		t.Fatalf("_System_LoginHistory not found in system_tables.json")
	}

	// C3 additive columns (all NULL-able).
	expected := []struct {
		name    string
		colType string
	}{
		{"SessionId", "VARCHAR(64)"},
		{"LogoutTime", "DATETIME(6)"},
		{"LogoutReason", "VARCHAR(32)"},
		{"AuthenticationMethod", "VARCHAR(32)"},
	}

	for _, e := range expected {
		got, ok := loginHist.columns[e.name]
		if !ok {
			t.Errorf("_System_LoginHistory missing column %q (C3 §2.2)", e.name)
			continue
		}
		if got.colType != e.colType {
			t.Errorf("_System_LoginHistory.%s: type = %q, want %q", e.name, got.colType, e.colType)
		}
		if !got.nullable {
			t.Errorf("_System_LoginHistory.%s: nullable = false, want true (C3 additive-only contract)", e.name)
		}
	}

	// Invariants: existing columns must not be altered.
	invariants := []struct {
		name     string
		colType  string
		nullable bool
	}{
		{"Id", "VARCHAR(255)", false},
		{"UserId", "VARCHAR(255)", false},
		{"LoginTime", "DATETIME", false},
		{"Status", "VARCHAR(255)", false},
	}
	for _, inv := range invariants {
		got, ok := loginHist.columns[inv.name]
		if !ok {
			t.Fatalf("_System_LoginHistory.%s missing — regression", inv.name)
		}
		if got.colType != inv.colType {
			t.Errorf("_System_LoginHistory.%s type = %q, want %q (must not alter existing column)", inv.name, got.colType, inv.colType)
		}
		if got.nullable != inv.nullable {
			t.Errorf("_System_LoginHistory.%s nullable = %v, want %v (additive-only contract violated)", inv.name, got.nullable, inv.nullable)
		}
	}
}
