package catalognamespaceauthority

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

var schemaStatements = []string{
	fmt.Sprintf(`CREATE TABLE IF NOT EXISTS _System_CatalogNamespaceAuthority (
NamespaceId VARBINARY(128) PRIMARY KEY,
OwnerKind VARBINARY(8) NOT NULL,
OwnerId VARBINARY(128) NOT NULL,
State VARBINARY(16) NOT NULL,
TenantSequenceUpperBound DECIMAL(20,0) NULL,
CreatedDate DATETIME(6) NOT NULL,
LastModifiedDate DATETIME(6) NOT NULL,
CONSTRAINT chk_catalog_namespace_authority_identity CHECK (
OCTET_LENGTH(NamespaceId) > 0 AND OCTET_LENGTH(NamespaceId) <= 128
AND OCTET_LENGTH(OwnerId) > 0 AND OCTET_LENGTH(OwnerId) <= 128),
CONSTRAINT chk_catalog_namespace_authority_shape CHECK (
(OwnerKind = 'SYSTEM'
AND NamespaceId = '%[1]s'
AND OwnerId = '%[1]s'
AND State = 'ACTIVE'
AND TenantSequenceUpperBound IS NULL)
OR
(OwnerKind = 'APP'
AND NamespaceId <> '%[1]s'
AND OwnerId <> '%[1]s'
AND State = 'ACTIVE'
AND TenantSequenceUpperBound IS NULL)
OR
(OwnerKind = 'TENANT'
AND NamespaceId <> '%[1]s'
AND OwnerId = NamespaceId
AND State IN ('ACTIVE','TOMBSTONE')
AND TenantSequenceUpperBound IS NOT NULL
AND TenantSequenceUpperBound >= 0)))`, SystemNamespace),
	fmt.Sprintf(`INSERT IGNORE INTO _System_CatalogNamespaceAuthority
(NamespaceId, OwnerKind, OwnerId, State, TenantSequenceUpperBound,
CreatedDate, LastModifiedDate)
VALUES (
'%[1]s', 'SYSTEM', '%[1]s', 'ACTIVE', NULL,
CURRENT_TIMESTAMP(6), CURRENT_TIMESTAMP(6))`, SystemNamespace),
}

// EnsureSchema creates the dormant namespace authority ledger and its one
// fixed system owner. It does not attach the ledger to a runtime read or write
// path.
func EnsureSchema(ctx context.Context, db *sql.DB) error {
	if db == nil {
		return errors.New("catalog namespace authority: database is required")
	}
	for _, statement := range schemaStatements {
		if _, err := db.ExecContext(ctx, statement); err != nil {
			return err
		}
	}
	return nil
}

// SchemaStatementsForTest returns a defensive copy.
func SchemaStatementsForTest() []string {
	return append([]string(nil), schemaStatements...)
}
