package db

import "time"

// ImportJob tracks an external forge migration authorized for one target
// repository. Source-forge credentials deliberately never live on this row:
// the external ags-migrate executor retains and uses them locally.
//
// The first supported source is GitHub. Jobs are intentionally modeled as
// durable state before importer execution exists so the API can expose dry-run,
// logs, mappings, retries, and cancellation without overloading normal create
// issue/PR endpoints.
type ImportJob struct {
	ID uint `gorm:"primaryKey;autoIncrement"`

	Source        string `gorm:"size:32;not null;index:idx_import_jobs_source"`
	Status        string `gorm:"size:32;not null;default:'queued';index"`
	Stage         string `gorm:"size:64;not null;default:'queued';index"`
	SourceOwner   string `gorm:"size:255;not null;index:idx_import_jobs_source_repo,priority:1"`
	SourceRepo    string `gorm:"size:255;not null;index:idx_import_jobs_source_repo,priority:2"`
	SourceAPIURL  string `gorm:"size:1024"`
	SourceHTMLURL string `gorm:"size:1024"`
	// SourceTokenRef is retained only so pre-existing internal direct-worker
	// jobs remain readable. New jobs never write it and public importer APIs do
	// not accept it; source credentials stay with ags-migrate.
	SourceTokenRef string `gorm:"size:512"`
	TargetOwner    string `gorm:"size:255;not null;index:idx_import_jobs_target_repo,priority:1"`
	TargetRepo     string `gorm:"size:255;not null;index:idx_import_jobs_target_repo,priority:2"`
	// TargetMode records the safety contract chosen when the job was created:
	// create or existing_empty. Destructive replacement is intentionally not
	// accepted by the public importer API.
	TargetMode       string     `gorm:"size:32;not null;default:'create'"`
	TargetRepoID     *uint      `gorm:"index"`
	TargetRepository Repository `gorm:"foreignKey:TargetRepoID"`

	InitiatorID uint `gorm:"index;not null"`
	Initiator   User `gorm:"foreignKey:InitiatorID"`

	DryRun        bool
	MirrorGit     bool
	OptionsJSON   LargeText
	InventoryJSON LargeText
	ErrorMessage  LargeText

	StartedAt   *time.Time
	CompletedAt *time.Time
	CreatedAt   time.Time
	UpdatedAt   time.Time
}

// ImportTargetReservation serializes imports into one target name. It stops
// two concurrent executors from both accepting an empty repository before
// either begins applying staged collaboration history.
type ImportTargetReservation struct {
	ID uint `gorm:"primaryKey;autoIncrement"`

	TargetOwner string    `gorm:"size:255;not null;uniqueIndex:idx_import_target_reservation,priority:1"`
	TargetRepo  string    `gorm:"size:255;not null;uniqueIndex:idx_import_target_reservation,priority:2"`
	ImportJobID *uint     `gorm:"uniqueIndex"`
	ImportJob   ImportJob `gorm:"foreignKey:ImportJobID"`

	CreatedAt time.Time
	UpdatedAt time.Time
}

// ImportLog is an append-only, user-readable log stream for one import job.
type ImportLog struct {
	ID          uint      `gorm:"primaryKey;autoIncrement"`
	ImportJobID uint      `gorm:"index;not null"`
	ImportJob   ImportJob `gorm:"foreignKey:ImportJobID"`
	Level       string    `gorm:"size:16;not null;default:'info'"`
	Stage       string    `gorm:"size:64;not null"`
	Message     string    `gorm:"size:2048;not null"`
	DetailsJSON LargeText
	CreatedAt   time.Time
}

// ImportItemMapping records source-to-target identity preservation.
// It is the durable answer for "what did GitHub issue/PR/comment X become?"
type ImportItemMapping struct {
	ID          uint      `gorm:"primaryKey;autoIncrement"`
	ImportJobID uint      `gorm:"uniqueIndex:idx_import_mapping_source,priority:1;index"`
	ImportJob   ImportJob `gorm:"foreignKey:ImportJobID"`

	SourceType   string `gorm:"size:64;not null;uniqueIndex:idx_import_mapping_source,priority:2"`
	SourceID     string `gorm:"size:128;not null;uniqueIndex:idx_import_mapping_source,priority:3"`
	SourceNodeID string `gorm:"size:255"`
	SourceNumber *int
	SourceURL    string `gorm:"size:1024"`

	TargetType   string `gorm:"size:64"`
	TargetID     string `gorm:"size:128"`
	TargetNumber *int
	TargetURL    string `gorm:"size:1024"`
	MetadataJSON LargeText

	CreatedAt time.Time
	UpdatedAt time.Time
}

// ImportSourceUser keeps original source attribution even when no AGS user is
// mapped yet. Later importer stages can associate these placeholders with real
// users and reattribute the migrated history after the target user accepts.
type ImportSourceUser struct {
	ID          uint      `gorm:"primaryKey;autoIncrement"`
	ImportJobID uint      `gorm:"uniqueIndex:idx_import_source_user,priority:1;index"`
	ImportJob   ImportJob `gorm:"foreignKey:ImportJobID"`

	SourceLogin string `gorm:"size:255;not null;uniqueIndex:idx_import_source_user,priority:2"`
	SourceID    string `gorm:"size:128"`
	SourceURL   string `gorm:"size:1024"`

	TargetUserID *uint `gorm:"index"`
	TargetUser   User  `gorm:"foreignKey:TargetUserID"`
	// ProposedUserID is the active organization member invited to accept
	// reattribution. It is intentionally separate from TargetUserID: history
	// changes only after the invited member accepts.
	ProposedUserID   *uint  `gorm:"index"`
	ProposedUser     User   `gorm:"foreignKey:ProposedUserID"`
	PlaceholderLogin string `gorm:"size:255"`
	State            string `gorm:"size:32;not null;default:'placeholder';index"`
	InvitationState  string `gorm:"size:32;not null;default:'none';index"`
	InvitedAt        *time.Time
	RespondedAt      *time.Time
	MetadataJSON     LargeText

	CreatedAt time.Time
	UpdatedAt time.Time
}

// ImportBatch is one idempotent bulk payload uploaded by a migration client.
// Batches are the durable boundary between external source extraction and AGS
// native table apply. They let ags-migrate retry uploads without replaying
// GitHub API extraction and let AGS apply staged data independently.
type ImportBatch struct {
	ID          uint      `gorm:"primaryKey;autoIncrement"`
	ImportJobID uint      `gorm:"uniqueIndex:idx_import_batch_job_batch,priority:1;index"`
	ImportJob   ImportJob `gorm:"foreignKey:ImportJobID"`

	BatchID       string `gorm:"size:255;not null;uniqueIndex:idx_import_batch_job_batch,priority:2"`
	ObjectType    string `gorm:"size:64;not null;index"`
	SchemaVersion int    `gorm:"not null;default:1"`
	SourceCursor  string `gorm:"size:1024"`
	ItemCount     int    `gorm:"not null;default:0"`
	Checksum      string `gorm:"size:128"`
	Status        string `gorm:"size:32;not null;default:'staged';index"`
	ErrorMessage  LargeText
	// ApplyClaimToken and ApplyClaimExpiresAt make a batch exclusively owned by
	// one apply worker. They prevent a concurrent worker from turning a batch
	// another worker already applied into a failed batch.
	ApplyClaimToken     string     `gorm:"size:64;index"`
	ApplyClaimExpiresAt *time.Time `gorm:"index"`

	AppliedAt *time.Time
	CreatedAt time.Time
	UpdatedAt time.Time
}

// ImportStagedAsset stores durable metadata for a raw release-asset upload.
// Bytes live under the AGS storage root, keyed by the import and source ID and
// verified by checksum, rather than Base64-embedded in an import-batch JSON
// payload.
type ImportStagedAsset struct {
	ID          uint      `gorm:"primaryKey;autoIncrement"`
	ImportJobID uint      `gorm:"uniqueIndex:idx_import_staged_asset,priority:1;index"`
	ImportJob   ImportJob `gorm:"foreignKey:ImportJobID"`

	SourceID   string `gorm:"size:128;not null;uniqueIndex:idx_import_staged_asset,priority:2"`
	StorageKey string `gorm:"size:128;not null"`
	Size       int64  `gorm:"not null"`
	Checksum   string `gorm:"size:128;not null"`

	CreatedAt time.Time
	UpdatedAt time.Time
}

// ImportStagingItem stores one raw source object from an import batch. The
// payload remains source-shaped until an apply writer converts it into AGS'
// native issue, pull request, wiki, release, or settings tables.
type ImportStagingItem struct {
	ID            uint        `gorm:"primaryKey;autoIncrement"`
	ImportJobID   uint        `gorm:"index;not null"`
	ImportJob     ImportJob   `gorm:"foreignKey:ImportJobID"`
	ImportBatchID uint        `gorm:"uniqueIndex:idx_import_staging_batch_item,priority:1;index"`
	ImportBatch   ImportBatch `gorm:"foreignKey:ImportBatchID"`

	ObjectType   string `gorm:"size:64;not null;index"`
	ItemIndex    int    `gorm:"not null;uniqueIndex:idx_import_staging_batch_item,priority:2"`
	SourceID     string `gorm:"size:128;index"`
	SourceNodeID string `gorm:"size:255"`
	SourceNumber *int
	SourceURL    string `gorm:"size:1024"`
	PayloadJSON  LargeText
	Checksum     string `gorm:"size:128"`
	Status       string `gorm:"size:32;not null;default:'staged';index"`
	ErrorMessage LargeText

	AppliedAt *time.Time
	CreatedAt time.Time
	UpdatedAt time.Time
}
