package content

import "time"

const (
	ModelTree     = "tree"
	ModelDocument = "document"

	OutboxVersionCommitted = "content_version_committed"
	OutboxStatusPending    = "pending"
	OutboxStatusDelivered  = "delivered"
	OutboxStatusFailed     = "failed"

	GCStatusPending  = "pending"
	GCStatusDeleting = "deleting"
	GCStatusRetained = "retained"
	GCStatusDeleted  = "deleted"
	GCStatusFailed   = "failed"

	AuthorityStateLegacyActive = "legacy_active"
	AuthorityStateNativeActive = "native_active"

	// AuthorityDomainDefaultBinding is a reserved wildcard sentinel. Product
	// routing and activation require exact binding keys and must reject it.
	AuthorityDomainDefaultBinding = "*"
)

// Authority selects exactly one remote writer for a product binding during
// AGS removal. A missing row intentionally means legacy_active; callers must
// not materialize default rows from read paths.
type Authority struct {
	ID          string    `gorm:"primaryKey;size:64"`
	WorkspaceID string    `gorm:"size:64;not null;uniqueIndex:uk_content_authority_binding"`
	Domain      string    `gorm:"size:64;not null;uniqueIndex:uk_content_authority_binding"`
	BindingKey  string    `gorm:"size:255;not null;uniqueIndex:uk_content_authority_binding"`
	State       string    `gorm:"size:32;not null;index:idx_content_authority_state"`
	Generation  uint64    `gorm:"not null"`
	Checkpoint  string    `gorm:"size:255;not null;default:''"`
	UpdatedBy   string    `gorm:"size:64;not null"`
	CreatedAt   time.Time `gorm:"not null"`
	UpdatedAt   time.Time `gorm:"not null"`
}

func (Authority) TableName() string { return "content_authorities" }

// VersionedContent is the only transactional owner of a content lineage.
// Payload backends own bytes only and never advance HeadVersionID.
type VersionedContent struct {
	ID                    string    `gorm:"primaryKey;size:64"`
	WorkspaceID           string    `gorm:"size:64;not null;index:idx_versioned_content_workspace_updated;uniqueIndex:uk_versioned_content_binding"`
	Domain                string    `gorm:"size:64;not null;index;uniqueIndex:uk_versioned_content_binding"`
	BindingKey            string    `gorm:"size:255;not null;uniqueIndex:uk_versioned_content_binding"`
	Model                 string    `gorm:"size:32;not null;index"`
	HeadVersionID         string    `gorm:"size:64;not null;default:'';index"`
	Revision              uint64    `gorm:"not null;default:0"`
	Generation            uint64    `gorm:"not null;default:1"`
	RetainedVersionCount  uint64    `gorm:"not null;default:0"`
	StoredPayloadBytes    int64     `gorm:"not null;default:0"`
	MaxRetainedVersions   uint64    `gorm:"not null"`
	MaxStoredPayloadBytes int64     `gorm:"not null"`
	MaxPins               uint64    `gorm:"not null"`
	CreatedBy             string    `gorm:"size:64;not null"`
	UpdatedBy             string    `gorm:"size:64;not null"`
	CreatedAt             time.Time `gorm:"not null"`
	UpdatedAt             time.Time `gorm:"not null;index:idx_versioned_content_workspace_updated"`
}

func (VersionedContent) TableName() string { return "versioned_content" }

// ContentVersion is immutable after insertion.
type ContentVersion struct {
	ID              string    `gorm:"primaryKey;size:64"`
	WorkspaceID     string    `gorm:"size:64;not null;index:idx_content_versions_workspace_created"`
	ContentID       string    `gorm:"size:64;not null;index:idx_content_versions_content_created"`
	ParentVersionID string    `gorm:"size:64;not null;default:''"`
	Generation      uint64    `gorm:"not null"`
	Model           string    `gorm:"size:32;not null"`
	PayloadRef      string    `gorm:"size:512;not null;uniqueIndex"`
	RootDigest      string    `gorm:"size:64;not null"`
	SizeBytes       int64     `gorm:"not null"`
	FileCount       int       `gorm:"not null"`
	SummaryBytes    int64     `gorm:"not null"`
	Checkpoint      bool      `gorm:"not null;default:false;index"`
	CreatedBy       string    `gorm:"size:64;not null"`
	CreatedAt       time.Time `gorm:"not null;index:idx_content_versions_content_created;index:idx_content_versions_workspace_created"`
}

func (ContentVersion) TableName() string { return "content_versions" }

// VersionOperation is the durable idempotency authority for one completed
// Content Store publication. It is written in the same transaction as the
// immutable version, live-head fence, quota accounting, outbox, and GC
// retention. Ordinary publication advances the head; detached migration does
// not.
// Operation keys are server-owned namespaced identifiers, never credentials.
type VersionOperation struct {
	ID                    string    `gorm:"primaryKey;size:64"`
	WorkspaceID           string    `gorm:"size:64;not null;uniqueIndex:uk_content_version_operation,priority:1"`
	ContentID             string    `gorm:"size:64;not null;uniqueIndex:uk_content_version_operation,priority:2;index"`
	OperationKey          string    `gorm:"size:255;not null;uniqueIndex:uk_content_version_operation,priority:3"`
	RequestDigest         string    `gorm:"size:64;not null"`
	OperationNamespace    string    `gorm:"size:64;not null"`
	OperationVersion      uint64    `gorm:"not null"`
	BoundsPolicyNamespace string    `gorm:"size:64;not null"`
	BoundsPolicyVersion   uint64    `gorm:"not null"`
	MaxFiles              int       `gorm:"not null"`
	MaxFileBytes          int64     `gorm:"not null"`
	MaxTotalBytes         int64     `gorm:"not null"`
	MaxManifestBytes      int64     `gorm:"not null"`
	ExpectedHeadVersionID string    `gorm:"size:64;not null;default:''"`
	ExpectedGeneration    uint64    `gorm:"not null"`
	Actor                 string    `gorm:"size:64;not null"`
	Model                 string    `gorm:"size:32;not null"`
	Checkpoint            bool      `gorm:"not null;default:false"`
	VersionID             string    `gorm:"size:64;not null;index"`
	RootDigest            string    `gorm:"size:64;not null"`
	SizeBytes             int64     `gorm:"not null"`
	FileCount             int       `gorm:"not null"`
	SummaryBytes          int64     `gorm:"not null"`
	ContentRevision       uint64    `gorm:"not null"`
	RetainedVersionCount  uint64    `gorm:"not null"`
	StoredPayloadBytes    int64     `gorm:"not null"`
	CreatedAt             time.Time `gorm:"not null"`
}

func (VersionOperation) TableName() string { return "content_version_operations" }

// VersionPath stores the bounded path/digest projection committed with a
// version. PathKey is SHA-256(path), allowing exact history lookup without an
// oversized path index.
type VersionPath struct {
	ID          string    `gorm:"primaryKey;size:64"`
	WorkspaceID string    `gorm:"size:64;not null;index:idx_content_version_paths_lookup,priority:1"`
	ContentID   string    `gorm:"size:64;not null;index:idx_content_version_paths_lookup,priority:2"`
	VersionID   string    `gorm:"size:64;not null;uniqueIndex:uk_content_version_path;index"`
	PathKey     string    `gorm:"size:64;not null;uniqueIndex:uk_content_version_path;index:idx_content_version_paths_lookup,priority:3"`
	Path        string    `gorm:"type:text;not null"`
	Digest      string    `gorm:"size:64;not null"`
	Kind        string    `gorm:"size:16;not null"`
	SizeBytes   int64     `gorm:"not null"`
	CreatedAt   time.Time `gorm:"not null"`
}

func (VersionPath) TableName() string { return "content_version_paths" }

type VersionPin struct {
	ID          string    `gorm:"primaryKey;size:64"`
	WorkspaceID string    `gorm:"size:64;not null;index"`
	ContentID   string    `gorm:"size:64;not null;index;uniqueIndex:uk_content_version_pin"`
	VersionID   string    `gorm:"size:64;not null;index;uniqueIndex:uk_content_version_pin"`
	Label       string    `gorm:"size:255;not null;uniqueIndex:uk_content_version_pin"`
	CreatedBy   string    `gorm:"size:64;not null"`
	CreatedAt   time.Time `gorm:"not null"`
}

func (VersionPin) TableName() string { return "content_version_pins" }

// Outbox records content events in the same transaction as version publication.
type Outbox struct {
	ID            string     `gorm:"primaryKey;size:64"`
	WorkspaceID   string     `gorm:"size:64;not null;index"`
	ContentID     string     `gorm:"size:64;not null;index"`
	VersionID     string     `gorm:"size:64;not null;uniqueIndex:uk_content_outbox_version_event"`
	EventType     string     `gorm:"size:64;not null;uniqueIndex:uk_content_outbox_version_event"`
	Status        string     `gorm:"size:32;not null;default:'pending';index:idx_content_outbox_status_next"`
	Attempts      int        `gorm:"not null;default:0"`
	NextAttemptAt time.Time  `gorm:"not null;index:idx_content_outbox_status_next"`
	LeaseOwner    string     `gorm:"size:128;not null;default:''"`
	LeaseUntil    *time.Time `gorm:"index"`
	LastError     string     `gorm:"type:text;not null"`
	CreatedAt     time.Time  `gorm:"not null"`
	UpdatedAt     time.Time  `gorm:"not null"`
}

func (Outbox) TableName() string { return "content_outbox" }

// StagedPayloadGC retains staged payloads until reconciliation proves them
// reachable or eligible for bounded asynchronous deletion.
type StagedPayloadGC struct {
	ID          string     `gorm:"primaryKey;size:64"`
	WorkspaceID string     `gorm:"size:64;not null;index"`
	ContentID   string     `gorm:"size:64;not null;index"`
	VersionID   string     `gorm:"size:64;not null;uniqueIndex"`
	Model       string     `gorm:"size:32;not null;default:'tree'"`
	PayloadRef  string     `gorm:"size:512;not null;uniqueIndex"`
	Status      string     `gorm:"size:32;not null;default:'pending';index:idx_content_gc_status_after"`
	DeleteAfter time.Time  `gorm:"not null;index:idx_content_gc_status_after"`
	Attempts    int        `gorm:"not null;default:0"`
	LeaseOwner  string     `gorm:"size:128;not null;default:''"`
	LeaseUntil  *time.Time `gorm:"index"`
	LastError   string     `gorm:"type:text;not null"`
	CreatedAt   time.Time  `gorm:"not null"`
	UpdatedAt   time.Time  `gorm:"not null"`
	CompletedAt *time.Time `gorm:"index"`
}

func (StagedPayloadGC) TableName() string { return "content_staged_payload_gc" }
