package packs

import (
	"context"
	"strings"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
	cp "github.com/pingcap-inc/nexuscrm-contract/pkg/controlplane"
)

func TestValidateManagedLifecycleTargetTableRejectsStaleAuditShape(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()
	mock.ExpectQuery("SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, DATETIME_PRECISION, IS_NULLABLE, COLUMN_DEFAULT").
		WithArgs(managedLifecycleTargetTable).
		WillReturnRows(sqlmock.NewRows([]string{"COLUMN_NAME", "DATA_TYPE", "CHARACTER_MAXIMUM_LENGTH", "DATETIME_PRECISION", "IS_NULLABLE", "COLUMN_DEFAULT"}).
			AddRow("TargetDomain", "varbinary", cp.ComponentManagedMaximumTargetDomain, nil, "NO", nil).
			AddRow("PhysicalKey", "varbinary", cp.ComponentManagedMaximumPhysicalKey, nil, "NO", nil).
			AddRow("CreatedAt", "datetime", nil, 6, "NO", "CURRENT_TIMESTAMP(6)"))
	if err := validateManagedLifecycleTargetTable(context.Background(), db); err == nil || !strings.Contains(err.Error(), "target table column shape") {
		t.Fatalf("stale target table error = %v", err)
	}
}

func TestValidateManagedLifecycleTargetTableRejectsMissingAuditDefault(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()
	mock.ExpectQuery("SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, DATETIME_PRECISION, IS_NULLABLE, COLUMN_DEFAULT").
		WithArgs(managedLifecycleTargetTable).
		WillReturnRows(sqlmock.NewRows([]string{"COLUMN_NAME", "DATA_TYPE", "CHARACTER_MAXIMUM_LENGTH", "DATETIME_PRECISION", "IS_NULLABLE", "COLUMN_DEFAULT"}).
			AddRow("TargetDomain", "varbinary", cp.ComponentManagedMaximumTargetDomain, nil, "NO", nil).
			AddRow("PhysicalKey", "varbinary", cp.ComponentManagedMaximumPhysicalKey, nil, "NO", nil).
			AddRow("CreatedDate", "datetime", nil, 6, "NO", nil).
			AddRow("LastModifiedDate", "datetime", nil, 6, "NO", "CURRENT_TIMESTAMP(6)"))
	if err := validateManagedLifecycleTargetTable(context.Background(), db); err == nil || !strings.Contains(err.Error(), "target table column shape") {
		t.Fatalf("target table without audit default error = %v", err)
	}
}

func TestValidateManagedLifecycleEvidenceTableRejectsMissingAuditDefault(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()
	mock.ExpectQuery("SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, DATETIME_PRECISION, IS_NULLABLE, COLUMN_DEFAULT").
		WithArgs(managedLifecycleEvidenceTable).
		WillReturnRows(sqlmock.NewRows([]string{"COLUMN_NAME", "DATA_TYPE", "CHARACTER_MAXIMUM_LENGTH", "DATETIME_PRECISION", "IS_NULLABLE", "COLUMN_DEFAULT"}).
			AddRow("OperationId", "varbinary", 64, nil, "NO", nil).
			AddRow("Attempt", "int", nil, nil, "NO", nil).
			AddRow("ComponentKind", "varchar", 255, nil, "NO", nil).
			AddRow("Scope", "varchar", 16, nil, "NO", nil).
			AddRow("PlanFingerprint", "binary", 32, nil, "NO", nil).
			AddRow("ProjectionIdentityHash", "binary", 32, nil, "NO", nil).
			AddRow("MutationDisposition", "varchar", 32, nil, "NO", nil).
			AddRow("SemanticMutationRows", "int", nil, nil, "NO", nil).
			AddRow("EffectReceiptHash", "binary", 32, nil, "YES", nil).
			AddRow("CreatedDate", "datetime", nil, 6, "NO", nil).
			AddRow("LastModifiedDate", "datetime", nil, 6, "NO", "CURRENT_TIMESTAMP(6)"))
	if err := validateManagedLifecycleEvidenceTable(context.Background(), db); err == nil || !strings.Contains(err.Error(), "evidence table column shape") {
		t.Fatalf("evidence table without audit default error = %v", err)
	}
}
