package bootstrapimpl

import (
	"regexp"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
	"github.com/nexuscrm/kernel/pkg/schema"
	"github.com/nexuscrm/shared/pkg/constants"
)

// liveDBQueryWRP is the regexp pattern for the SELECT issued by the live-DB
// WRP assertion. Different column from liveDBQuery (RequiredWritePermission
// instead of RequiredReadPermission).
var liveDBQueryWRP = regexp.QuoteMeta(
	"SELECT `RequiredWritePermission` FROM `_System_Object` WHERE `ApiName` = ? LIMIT 1",
)

// TestRequestCaptureWriteGatePinned_CorrectValue verifies that the assertion
// passes when _System_RequestCapture carries the canonical pinned WRP.
func TestRequestCaptureWriteGatePinned_CorrectValue(t *testing.T) {
	defs := []schema.TableDefinition{
		{
			TableName:               "_System_RequestCapture",
			TableType:               string(constants.TableTypeSystemCore),
			RequiredWritePermission: requestCaptureRequiredWritePermission,
		},
	}
	result := &AssertionResult{}
	assertRequestCaptureWritePermissionPinned(defs, result)
	if len(result.Violations) != 0 {
		t.Fatalf("expected 0 violations for correct WRP, got %d: %+v",
			len(result.Violations), result.Violations)
	}
}

// TestRequestCaptureWriteGatePinned_RealPermissionDrifted verifies that a
// real named permission (e.g. "ViewAllData") — which would open writes —
// triggers an error-severity violation.
func TestRequestCaptureWriteGatePinned_RealPermissionDrifted(t *testing.T) {
	defs := []schema.TableDefinition{
		{
			TableName:               "_System_RequestCapture",
			TableType:               string(constants.TableTypeSystemCore),
			RequiredWritePermission: "ViewAllData",
		},
	}
	result := &AssertionResult{}
	assertRequestCaptureWritePermissionPinned(defs, result)
	if len(result.Violations) != 1 {
		t.Fatalf("expected 1 violation for drifted WRP, got %d: %+v",
			len(result.Violations), result.Violations)
	}
	v := result.Violations[0]
	if v.Severity != constants.SeverityError {
		t.Errorf("want SeverityError, got %q", v.Severity)
	}
	if v.Category != "AuditWriteGate" {
		t.Errorf("want category AuditWriteGate, got %q", v.Category)
	}
}

// TestRequestCaptureWriteGatePinned_EmptyDenied verifies that an empty WRP
// is also caught (would open the table to generic CRUD writes).
func TestRequestCaptureWriteGatePinned_EmptyDenied(t *testing.T) {
	defs := []schema.TableDefinition{
		{
			TableName:               "_System_RequestCapture",
			TableType:               string(constants.TableTypeSystemCore),
			RequiredWritePermission: "",
		},
	}
	result := &AssertionResult{}
	assertRequestCaptureWritePermissionPinned(defs, result)
	if len(result.Violations) != 1 {
		t.Fatalf("expected 1 violation for empty WRP, got %d: %+v",
			len(result.Violations), result.Violations)
	}
}

// --- Live-DB WRP tests ---

// TestRequestCaptureWriteGateLiveDB_CorrectValue — DB row has the canonical
// "BLOCKED" value → no violations.
func TestRequestCaptureWriteGateLiveDB_CorrectValue(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock.New: %v", err)
	}
	defer db.Close()

	mock.ExpectQuery(liveDBQueryWRP).
		WithArgs("_System_RequestCapture").
		WillReturnRows(sqlmock.NewRows([]string{"RequiredWritePermission"}).
			AddRow(requestCaptureRequiredWritePermission))

	result := &AssertionResult{}
	assertRequestCaptureWritePermissionLiveDB(db, result)
	if len(result.Violations) != 0 {
		t.Fatalf("expected 0 violations for correct DB WRP value, got %d: %+v",
			len(result.Violations), result.Violations)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("sql expectations unmet: %v", err)
	}
}

// TestRequestCaptureWriteGateLiveDB_Drifted — DB row carries "ViewAllData"
// (simulates someone relaxing the BLOCKED lock). Must produce an error-severity
// violation.
func TestRequestCaptureWriteGateLiveDB_Drifted(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock.New: %v", err)
	}
	defer db.Close()

	mock.ExpectQuery(liveDBQueryWRP).
		WithArgs("_System_RequestCapture").
		WillReturnRows(sqlmock.NewRows([]string{"RequiredWritePermission"}).
			AddRow("ViewAllData"))

	result := &AssertionResult{}
	assertRequestCaptureWritePermissionLiveDB(db, result)
	if len(result.Violations) != 1 {
		t.Fatalf("expected 1 violation for drifted WRP, got %d: %+v",
			len(result.Violations), result.Violations)
	}
	v := result.Violations[0]
	if v.Severity != constants.SeverityError {
		t.Errorf("want SeverityError, got %q", v.Severity)
	}
	if v.Category != "AuditWriteGate" {
		t.Errorf("want category AuditWriteGate, got %q", v.Category)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("sql expectations unmet: %v", err)
	}
}
