package entity

import "time"

type AuditLogScheduleState string

const (
	AuditLogScheduleStateEnabled  AuditLogScheduleState = "enabled"
	AuditLogScheduleStateDisabled AuditLogScheduleState = "disabled"
	AuditLogScheduleStateDeleted  AuditLogScheduleState = "deleted"
)

type AuditLogCloudStorageType string

const (
	AuditLogCloudStorageTypeTiDBCloud AuditLogCloudStorageType = "TiDBCloud"
	AuditLogCloudStorageTypeS3        AuditLogCloudStorageType = "S3"
	AuditLogCloudStorageTypeOSS       AuditLogCloudStorageType = "OSS"
	AuditLogCloudStorageTypeGCS       AuditLogCloudStorageType = "GCS"
	AuditLogCloudStorageTypeAzureBlob AuditLogCloudStorageType = "AzureBlob"
)

const (
	defaultMaxFileSize = 100 * 1024 * 1024 // 100 MB
	defaultInterval    = 3600              // seconds
)

type AuditLogSchedule struct {
	OrgId                   string                   `gorm:"type:varchar(255);not_null"`
	ProjectId               string                   `gorm:"type:varchar(255);not_null"`
	ClusterId               string                   `gorm:"type:varchar(255);not_null;primary_key"`
	State                   AuditLogScheduleState    `gorm:"type:enum('enabled','disabled','deleted');not_null"`
	CreatedAt               time.Time                `gorm:"type:timestamp;not_null;default:CURRENT_TIMESTAMP"`
	UpdatedAt               *time.Time               `gorm:"type:timestamp;default:null;on_update:CURRENT_TIMESTAMP"`
	DeleteTime              *time.Time               `gorm:"type:timestamp;default:null"`
	DisableTime             *time.Time               `gorm:"type:timestamp;default:null"`
	RotationTime            time.Time                `gorm:"type:timestamp;default:CURRENT_TIMESTAMP"`
	S3StartAfter            string                   `gorm:"type:varchar(255);default:not null;default:''"`
	LastFileName            string                   `gorm:"type:varchar(255);default:not null;default:''"`
	CloudStorageType        AuditLogCloudStorageType `gorm:"type:varchar(64);default:null"`
	CloudStorage            *AuditLogCloudStorage    `gorm:"type:json;serializer:json;default:null"`
	RotationIntervalSeconds int64                    `gorm:"type:bigint;default:3600"`      // default 1 hour
	RotationSizeBytes       int64                    `gorm:"type:bigint;default:104857600"` // default 100 MB
	Unredacted              bool                     `gorm:"type:boolean;default:false"`
}

type AuditLogCloudStorage struct {
	S3        *AuditLogCloudStorageS3        `json:"s3,omitempty"`
	OSS       *AuditLogCloudStorageOSS       `json:"oss,omitempty"`
	GCS       *AuditLogCloudStorageGCS       `json:"gcs,omitempty"`
	AzureBlob *AuditLogCloudStorageAzureBlob `json:"azure_blob,omitempty"`
}

type AuditLogCloudStorageS3 struct {
	Uri             string `json:"uri,omitempty"`
	Region          string `json:"region,omitempty"`
	AccessKeyId     string `json:"access_key_id,omitempty"`
	SecretAccessKey string `json:"secret_access_key,omitempty"`
	RoleArn         string `json:"role_arn,omitempty"`
	ExternalId      string `json:"external_id,omitempty"`
}

type AuditLogCloudStorageOSS struct {
	Uri             string `json:"uri,omitempty"`
	Region          string `json:"region,omitempty"`
	AccessKeyId     string `json:"access_key_id,omitempty"`
	AccessKeySecret string `json:"access_key_secret,omitempty"`
	RoleArn         string `json:"role_arn,omitempty"`
	ExternalId      string `json:"external_id,omitempty"`
}

type AuditLogCloudStorageGCS struct {
	Uri               string `json:"uri,omitempty"`
	Region            string `json:"region,omitempty"`
	ServiceAccountKey string `json:"service_account_key,omitempty"`
}

type AuditLogCloudStorageAzureBlob struct {
	Uri      string `json:"uri,omitempty"`
	Region   string `json:"region,omitempty"`
	SASToken string `json:"sas_token,omitempty"`
}

func (b *AuditLogSchedule) ExceedMaxFileSize(fileSize int64) bool {
	if b.RotationSizeBytes > 0 {
		return fileSize > b.RotationSizeBytes
	}
	return fileSize > defaultMaxFileSize
}

func (b *AuditLogSchedule) ResetRotationTime() {
	if b.RotationIntervalSeconds > 0 {
		b.RotationTime = time.Now().Add(time.Duration(b.RotationIntervalSeconds) * time.Second)
	} else {
		b.RotationTime = time.Now().Add(time.Duration(defaultInterval) * time.Second)
	}
}

type ListAuditLogScheduleOptions struct {
	State AuditLogScheduleState
}

func (b *AuditLogSchedule) TableName() string {
	return "audit_log_schedules"
}

type AuditLogTaskState string

const (
	AuditLogTaskStatePending   AuditLogTaskState = "pending"
	AuditLogTaskStateRunning   AuditLogTaskState = "running"
	AuditLogTaskStateFailed    AuditLogTaskState = "failed"
	AuditLogTaskStateSucceeded AuditLogTaskState = "succeeded"
	AuditLogTaskStateCorrupted AuditLogTaskState = "corrupted"
)

type AuditLogTask struct {
	TaskId           string                   `gorm:"type:varchar(255);not_null;primary_key"`
	OrgId            string                   `gorm:"type:varchar(255);not_null"`
	ProjectId        string                   `gorm:"type:varchar(255);not_null"`
	ClusterId        string                   `gorm:"type:varchar(255);not_null"`
	State            AuditLogTaskState        `gorm:"type:enum('pending','running','failed','succeeded');not_null"`
	CreatedAt        time.Time                `gorm:"type:timestamp;not_null;default:CURRENT_TIMESTAMP"`
	UpdatedAt        *time.Time               `gorm:"type:timestamp;default:null;on_update:CURRENT_TIMESTAMP"`
	FileName         string                   `gorm:"type:varchar(255);not_null"`
	StartObjectKey   string                   `gorm:"type:varchar(255);not_null"`
	EndObjectKey     string                   `gorm:"type:varchar(255);not_null"`
	ErrorMsg         string                   `gorm:"type:text;default:null"`
	ExecuteCount     int                      `gorm:"type:int;not_null;default:0"`
	ObjectCount      int                      `gorm:"type:int;not_null;default:0"`
	CloudStorageType AuditLogCloudStorageType `gorm:"type:varchar(64);default:null"`
	CloudStorage     *AuditLogCloudStorage    `gorm:"type:json;serializer:json;default:null"`
}

func (b *AuditLogTask) TableName() string {
	return "audit_log_tasks"
}

type ListAuditLogTaskOptions struct {
	States  []AuditLogTaskState
	TaskIds []string
}
