package bootstrapimpl

import (
	"database/sql"
	"testing"

	"github.com/nexuscrm/kernel/pkg/schema"
)

// TestColumnShapeMatchesIgnoresDefaultDriftOnNoDefaultTypes locks in the
// invariant that JSON / TEXT / BLOB columns never report DEFAULT-clause drift,
// because MySQL/TiDB rejects DEFAULT on these types (Error 1101) and the apply
// path skips emitting it. The metadata default is value-shipping at insert
// time, not a physical-shape fact.
func TestColumnShapeMatchesIgnoresDefaultDriftOnNoDefaultTypes(t *testing.T) {
	cases := []struct {
		name        string
		desiredType string
	}{
		{"json", "JSON"},
		{"text", "TEXT"},
		{"longtext", "LONGTEXT"},
		{"blob", "BLOB"},
		{"longblob", "LONGBLOB"},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			existing := PhysicalColumnShape{
				ColumnType: tc.desiredType,
				Nullable:   true,
				DefaultVal: sql.NullString{}, // physical default cannot exist
			}
			desired := schema.ColumnDefinition{
				Name:     "Body",
				Type:     tc.desiredType,
				Nullable: true,
				Default:  "'{}'", // metadata default — used at insert time only
			}
			if !ColumnShapeMatches(existing, desired) {
				t.Fatalf("ColumnShapeMatches reported drift on %s with metadata default but no physical default; expected no-drift", tc.desiredType)
			}
		})
	}
}

// TestColumnShapeMatchesStillDetectsDefaultDriftOnAllowedTypes guards against
// over-suppression: VARCHAR/INT/etc. must continue to report DEFAULT drift so
// that admins see real divergence between metadata and physical schema.
func TestColumnShapeMatchesStillDetectsDefaultDriftOnAllowedTypes(t *testing.T) {
	existing := PhysicalColumnShape{
		ColumnType: "varchar(255)",
		Nullable:   true,
		DefaultVal: sql.NullString{}, // no physical default
	}
	desired := schema.ColumnDefinition{
		Name:     "Status",
		Type:     "VARCHAR(255)",
		Nullable: true,
		Default:  "'pending'",
	}
	if ColumnShapeMatches(existing, desired) {
		t.Fatal("ColumnShapeMatches accepted DEFAULT drift on VARCHAR; expected drift to be reported")
	}
}

func TestColumnShapeMatchesDetectsRequestedCollationDrift(t *testing.T) {
	existing := PhysicalColumnShape{
		ColumnType:    "char(3)",
		Nullable:      false,
		CollationName: sql.NullString{String: "utf8mb4_unicode_ci", Valid: true},
	}
	desired := schema.ColumnDefinition{
		Name:          "KeyPrefix",
		Type:          "CHAR(3)",
		CollationName: "utf8mb4_bin",
	}
	if ColumnShapeMatches(existing, desired) {
		t.Fatal("ColumnShapeMatches accepted collation drift; expected drift to be reported")
	}
}
