package schema

import (
	"time"

	"gorm.io/gorm"
)

// ExportState represents the state of an export task.
type ExportState string

const (
	ExportStateUnspecified ExportState = "unspecified"
	ExportStateRunning     ExportState = "running"
	ExportStateSucceeded   ExportState = "succeeded"
	ExportStateFailed      ExportState = "failed"
	ExportStateCanceled    ExportState = "canceled"
	ExportStateDeleted     ExportState = "deleted"
)

// Export stores export task metadata. ExportOptions and CloudStorage are stored as JSON.
type Export struct {
	Versioned
	gorm.Model

	// ExportId is the unique string ID generated by our ID generator and exposed to API.
	ExportId string `gorm:"type:VARCHAR(64);not null;uniqueIndex:idx_export_export_id"`

	// DisplayName is the display name of the export task.
	DisplayName string `gorm:"type:VARCHAR(255);not null"`

	// ClusterId (tidb_id) is the cluster this export belongs to.
	ClusterId string `gorm:"not null;index:idx_export_cluster"`

	// OrganizationId is the tenant/organization this export belongs to.
	OrganizationId uint64 `gorm:"not null;index:idx_export_organization"`

	RegionId uint64 `gorm:"not null"`

	// CreatedBy is the email or identifier of the user who created the export.
	CreatedBy string `gorm:"type:VARCHAR(255);not null"`

	// State of the export task.
	State ExportState `gorm:"type:VARCHAR(32);not null;index:idx_export_state"`

	// ExportOptions stores export options (proto ExportOptions) as JSON.
	ExportOptions *ExportOptions `gorm:"serializer:json;type:JSON"`

	// CloudStorage stores cloud storage config (proto CloudStorage) as JSON.
	CloudStorage *CloudStorage `gorm:"serializer:json;type:JSON"`

	// Reason is the error message when the export failed.
	Reason string `gorm:"type:VARCHAR(1024)"`

	// SnapshotTso is the snapshot TSO of the export.
	SnapshotTso uint64 `gorm:""`

	// SnapshotTime is when the snapshot was taken.
	SnapshotTime *time.Time `gorm:""`

	// Username is the database username used for export.
	Username string `gorm:"type:VARCHAR(255);not null"`

	// TidbGroupId is the internal TiDBGroup ID used for export execution.
	TidbGroupId string `gorm:"type:VARCHAR(64);index:idx_export_tidb_group_id"`

	// EncryptedPassword stores the encrypted password; not returned in API responses.
	EncryptedPassword string `gorm:"type:VARCHAR(1024)"`

	// CompleteTime is when the export finished (success, failed, or canceled).
	CompleteTime *time.Time `gorm:""`
}

// ExportOptions mirrors proto ExportOptions for JSON storage (camelCase matches protojson).
type ExportOptions struct {
	FileType        string                      `json:"fileType,omitempty"`
	Compression     string                      `json:"compression,omitempty"`
	Filter          *ExportOptionsFilter        `json:"filter,omitempty"`
	CSVFormat       *ExportOptionsCSVFormat     `json:"csvFormat,omitempty"`
	EscapeBackslash *bool                       `json:"escapeBackslash,omitempty"`
	ParquetFormat   *ExportOptionsParquetFormat `json:"parquetFormat,omitempty"`
}

// ExportOptionsFilter is the oneof (sql or table) for ExportOptions.Filter.
type ExportOptionsFilter struct {
	Sql   *string                   `json:"sql,omitempty"`
	Table *ExportOptionsFilterTable `json:"table,omitempty"`
}

// ExportOptionsFilterTable is ExportOptions.Filter.Table.
type ExportOptionsFilterTable struct {
	Patterns   []string `json:"patterns"`
	Where      string   `json:"where,omitempty"`
	Partitions []string `json:"partitions,omitempty"`
}

// ExportOptionsCSVFormat is ExportOptions.CSVFormat.
type ExportOptionsCSVFormat struct {
	Separator  string  `json:"separator,omitempty"`
	Delimiter  *string `json:"delimiter,omitempty"`
	NullValue  *string `json:"nullValue,omitempty"`
	SkipHeader bool    `json:"skipHeader,omitempty"`
	Dialect    *string `json:"dialect,omitempty"`
}

// ExportOptionsParquetFormat is ExportOptions.ParquetFormat.
type ExportOptionsParquetFormat struct {
	Compression string `json:"compression,omitempty"`
}

// CloudStorage mirrors proto CloudStorage for JSON storage (camelCase matches protojson).
type CloudStorage struct {
	Type      string                 `json:"type,omitempty"`
	S3        *S3CloudStorage        `json:"s3,omitempty"`
	Gcs       *GCSCloudStorage       `json:"gcs,omitempty"`
	AzureBlob *AzureBlobCloudStorage `json:"azureBlob,omitempty"`
	Oss       *OSSCloudStorage       `json:"oss,omitempty"`
}

// S3CloudStorage mirrors proto S3CloudStorage.
type S3CloudStorage struct {
	Uri       string       `json:"uri,omitempty"`
	AuthType  string       `json:"authType,omitempty"`
	AccessKey *S3AccessKey `json:"accessKey,omitempty"`
	RoleArn   string       `json:"roleArn,omitempty"`
}

// S3AccessKey mirrors S3CloudStorage.AccessKey.
type S3AccessKey struct {
	Id     string `json:"id,omitempty"`
	Secret string `json:"secret,omitempty"`
}

// GCSCloudStorage mirrors proto GCSCloudStorage.
type GCSCloudStorage struct {
	Uri               string `json:"uri,omitempty"`
	AuthType          string `json:"authType,omitempty"`
	ServiceAccountKey string `json:"serviceAccountKey,omitempty"`
}

// AzureBlobCloudStorage mirrors proto AzureBlobCloudStorage.
type AzureBlobCloudStorage struct {
	Uri      string `json:"uri,omitempty"`
	AuthType string `json:"authType,omitempty"`
	SasToken string `json:"sasToken,omitempty"`
}

// OSSCloudStorage mirrors proto OSSCloudStorage.
type OSSCloudStorage struct {
	Uri       string        `json:"uri,omitempty"`
	AuthType  string        `json:"authType,omitempty"`
	AccessKey *OSSAccessKey `json:"accessKey,omitempty"`
	RoleArn   string        `json:"roleArn,omitempty"`
}

// OSSAccessKey mirrors OSSCloudStorage.AccessKey.
type OSSAccessKey struct {
	Id     string `json:"id,omitempty"`
	Secret string `json:"secret,omitempty"`
}
