package serving

import (
	"context"
	"database/sql"
	"errors"
	"fmt"
)

var errAccountServingGateSchemaUnavailable = errors.New(
	"connector serving: account serving gate schema unavailable",
)

var accountServingGateColumns = []expectedServingColumn{
	{name: "Id", columnType: "varchar(255)", collation: "utf8mb4_bin"},
	{name: "ServingScopeDigest", columnType: "char(64)", collation: "utf8mb4_bin"},
	{name: "ConnectorAccountId", columnType: "varchar(255)", collation: "utf8mb4_bin"},
	{name: "Mode", columnType: "varchar(32)", collation: "utf8mb4_bin", hasDefault: true, columnDefault: "v1_serving"},
	{name: "FenceToken", columnType: "bigint(20)", hasDefault: true, columnDefault: "0"},
	{name: "ServingEpochId", columnType: "varchar(255)", nullable: true, collation: "utf8mb4_bin"},
	{name: "ServingEpochDigest", columnType: "char(71)", nullable: true, collation: "utf8mb4_bin"},
	{name: "CreatedDate", columnType: "datetime(6)", hasDefault: true, columnDefault: "CURRENT_TIMESTAMP(6)", allowDefaultGenerated: true},
	{name: "LastModifiedDate", columnType: "datetime(6)", hasDefault: true, columnDefault: "CURRENT_TIMESTAMP(6)", allowDefaultGenerated: true},
}

var accountServingGateIndexes = []expectedServingIndex{
	{name: "PRIMARY", unique: true, columns: []string{"Id"}},
	{name: "ux_connector_account_gate_scope_account", unique: true, columns: []string{"ServingScopeDigest", "ConnectorAccountId"}},
	{name: "idx_connector_account_gate_mode", columns: []string{"ServingScopeDigest", "Mode", "ConnectorAccountId"}},
	{name: "idx_connector_account_gate_epoch", columns: []string{"ServingEpochId", "Mode", "ConnectorAccountId"}},
}

var accountServingGateSchema = servingTableSchema{
	name:    accountServingGateTable,
	columns: accountServingGateColumns,
	indexes: accountServingGateIndexes,
	foreignKeys: []expectedServingForeignKey{
		{column: "ServingEpochId", referencedTable: servingEpochTable, referencedColumn: "Id"},
	},
}

// verifyAccountServingGateSchema is deliberately separate from
// Repository.VerifySchema. ServingEpoch preparation and verification do not
// depend on this distinct mutable gate fact. This check is read-only and never
// creates, alters, repairs, or accepts a compatibility schema.
func verifyAccountServingGateSchema(ctx context.Context, db *sql.DB) error {
	if ctx == nil || db == nil {
		return accountServingGateSchemaError("database or context is unavailable", nil)
	}
	if err := verifyServingColumns(ctx, db, accountServingGateSchema.name, accountServingGateSchema.columns); err != nil {
		return accountServingGateSchemaError("verify columns", err)
	}
	if err := verifyServingIndexes(ctx, db, accountServingGateSchema.name, accountServingGateSchema.indexes); err != nil {
		return accountServingGateSchemaError("verify indexes", err)
	}
	if err := verifyServingForeignKeys(ctx, db, accountServingGateSchema.name, accountServingGateSchema.foreignKeys); err != nil {
		return accountServingGateSchemaError("verify foreign keys", err)
	}
	return nil
}

func accountServingGateSchemaError(operation string, cause error) error {
	if cause == nil {
		return fmt.Errorf(
			"%w: %w: %s",
			ErrSchemaUnavailable,
			errAccountServingGateSchemaUnavailable,
			operation,
		)
	}
	return fmt.Errorf(
		"%w: %w: %s: %w",
		ErrSchemaUnavailable,
		errAccountServingGateSchemaUnavailable,
		operation,
		cause,
	)
}
