package models

import (
	"time"

	"github.com/google/uuid"
)

// ── Enums ─────────────────────────────────────────────────────────────────────

type FileKind string

const (
	FileKindVideo     FileKind = "Video"
	FileKindImage     FileKind = "Image"
	FileKindAudio     FileKind = "Audio"
	FileKindVoiceover FileKind = "Voiceover"
	FileKindDocument  FileKind = "Document"
	FileKindOther     FileKind = "Other"
)

type FolderKind string

const (
	FolderKindSystem FolderKind = "System"
	FolderKindUser   FolderKind = "User"
	FolderKindShared FolderKind = "Shared"
	FolderKindTenant FolderKind = "Tenant"
)

type UploadStatus string

const (
	UploadStatusPending      UploadStatus = "Pending"
	UploadStatusUploading    UploadStatus = "Uploading"
	UploadStatusProcessing   UploadStatus = "Processing"
	UploadStatusReady        UploadStatus = "Ready"
	UploadStatusFailed       UploadStatus = "Failed"
	UploadStatusQuarantined  UploadStatus = "Quarantined"
)

type CleanupEntityType string

const (
	CleanupEntityExport           CleanupEntityType = "Export"
	CleanupEntityTempRenderFolder CleanupEntityType = "TempRenderFolder"
	CleanupEntityOrphanedFile     CleanupEntityType = "OrphanedFile"
	CleanupEntityUnusedUpload     CleanupEntityType = "UnusedUpload"
	CleanupEntitySnapshotExpired  CleanupEntityType = "SnapshotExpired"
)

type CleanupStatus string

const (
	CleanupStatusScheduled  CleanupStatus = "Scheduled"
	CleanupStatusNotified   CleanupStatus = "Notified"
	CleanupStatusProcessing CleanupStatus = "Processing"
	CleanupStatusDone       CleanupStatus = "Done"
	CleanupStatusSkipped    CleanupStatus = "Skipped"
	CleanupStatusFailed     CleanupStatus = "Failed"
)

// ── Domain ────────────────────────────────────────────────────────────────────

type UserFolder struct {
	ID             uuid.UUID  `json:"id"`
	TenantID       uuid.UUID  `json:"tenant_id"`
	UserID         uuid.UUID  `json:"user_id"`
	Name           string     `json:"name"`
	FolderType     FolderKind `json:"folder_type"`
	ParentFolderID *uuid.UUID `json:"parent_folder_id,omitempty"`
	FileCount      int        `json:"file_count"`
	TotalSizeBytes int64      `json:"total_size_bytes"`
	Sort           int        `json:"sort"`
	IsShared       bool       `json:"is_shared"`
	ShareToken     *string    `json:"share_token,omitempty"`
	CreatedAt      time.Time  `json:"created_at"`
	UpdatedAt      time.Time  `json:"updated_at"`
	DeletedAt      *time.Time `json:"deleted_at,omitempty"`
}

type UserFile struct {
	ID             uuid.UUID    `json:"id"`
	TenantID       uuid.UUID    `json:"tenant_id"`
	UserID         uuid.UUID    `json:"user_id"`
	UserFolderID   *uuid.UUID   `json:"user_folder_id,omitempty"`
	Name           string       `json:"name"`
	OriginalFilename *string    `json:"original_filename,omitempty"`
	FileExtension  *string      `json:"file_extension,omitempty"`
	MimeType       *string      `json:"mime_type,omitempty"`
	FileType       FileKind     `json:"file_type"`
	MinioBucket    string       `json:"minio_bucket"`
	MinioKey       string       `json:"minio_key"`
	CdnURL         *string      `json:"cdn_url,omitempty"`
	FileAddress    string       `json:"file_address"`
	SizeBytes      int64        `json:"size_bytes"`
	Md5Hash        *string      `json:"md5_hash,omitempty"`
	Sha256Hash     *string      `json:"sha256_hash,omitempty"`
	DurationSec    *float64     `json:"duration_sec,omitempty"`
	Width          *int         `json:"width,omitempty"`
	Height         *int         `json:"height,omitempty"`
	Fps            *float64     `json:"fps,omitempty"`
	BitrateKbps    *int         `json:"bitrate_kbps,omitempty"`
	Codec          *string      `json:"codec,omitempty"`
	HasAudio       *bool        `json:"has_audio,omitempty"`
	HasVideo       *bool        `json:"has_video,omitempty"`
	ThumbnailURL   *string      `json:"thumbnail_url,omitempty"`
	WaveformData   *string      `json:"waveform_data,omitempty"`
	UploadStatus   UploadStatus `json:"upload_status"`
	UploadProgress int          `json:"upload_progress"`
	Source         *string      `json:"source,omitempty"`
	ExportID       *uuid.UUID   `json:"export_id,omitempty"`
	ParentFileID   *uuid.UUID   `json:"parent_file_id,omitempty"`
	LastUsedAt     *time.Time   `json:"last_used_at,omitempty"`
	UseCount       int          `json:"use_count"`
	IsPublic       bool         `json:"is_public"`
	ShareToken     *string      `json:"share_token,omitempty"`
	Metadata       string       `json:"metadata"`
	CreatedAt      time.Time    `json:"created_at"`
	UpdatedAt      time.Time    `json:"updated_at"`
	DeletedAt      *time.Time   `json:"deleted_at,omitempty"`
}

type StorageQuota struct {
	UserID                 uuid.UUID  `json:"user_id"`
	TenantID               uuid.UUID  `json:"tenant_id"`
	PlanQuotaBytes         int64      `json:"plan_quota_bytes"`
	BonusQuotaBytes        int64      `json:"bonus_quota_bytes"`
	UsedBytes              int64      `json:"used_bytes"`
	VideoCount             int        `json:"video_count"`
	ImageCount             int        `json:"image_count"`
	AudioCount             int        `json:"audio_count"`
	VideoBytes             int64      `json:"video_bytes"`
	ImageBytes             int64      `json:"image_bytes"`
	AudioBytes             int64      `json:"audio_bytes"`
	Last90PctNotifiedAt    *time.Time `json:"last_90pct_notified_at,omitempty"`
	Last100PctNotifiedAt   *time.Time `json:"last_100pct_notified_at,omitempty"`
	UpdatedAt              time.Time  `json:"updated_at"`
}

type UploadSession struct {
	ID              uuid.UUID    `json:"id"`
	TenantID        uuid.UUID    `json:"tenant_id"`
	UserID          uuid.UUID    `json:"user_id"`
	MinioBucket     string       `json:"minio_bucket"`
	MinioKey        string       `json:"minio_key"`
	MinioUploadID   string       `json:"minio_upload_id"`
	Filename        string       `json:"filename"`
	MimeType        *string      `json:"mime_type,omitempty"`
	TotalSizeBytes  int64        `json:"total_size_bytes"`
	ChunksReceived  int          `json:"chunks_received"`
	BytesReceived   int64        `json:"bytes_received"`
	ChunkSizeBytes  int          `json:"chunk_size_bytes"`
	TargetFolderID  *uuid.UUID   `json:"target_folder_id,omitempty"`
	TargetFileID    *uuid.UUID   `json:"target_file_id,omitempty"`
	Status          UploadStatus `json:"status"`
	ErrorMessage    *string      `json:"error_message,omitempty"`
	ExpiresAt       time.Time    `json:"expires_at"`
	CompletedAt     *time.Time   `json:"completed_at,omitempty"`
	CreatedAt       time.Time    `json:"created_at"`
	UpdatedAt       time.Time    `json:"updated_at"`
}

type MinioBucket struct {
	ID         uuid.UUID `json:"id"`
	Name       string    `json:"name"`
	Region     string    `json:"region"`
	Endpoint   string    `json:"endpoint"`
	Purpose    string    `json:"purpose"`
	IsPublic   bool      `json:"is_public"`
	CdnBaseURL *string   `json:"cdn_base_url,omitempty"`
	IsActive   bool      `json:"is_active"`
	CreatedAt  time.Time `json:"created_at"`
}

// ── Request / Response ────────────────────────────────────────────────────────

type CreateFolderRequest struct {
	Name           string     `json:"name" binding:"required"`
	ParentFolderID *uuid.UUID `json:"parent_folder_id"`
}

type MoveFolderRequest struct {
	ParentFolderID *uuid.UUID `json:"parent_folder_id"`
}

type RenameFolderRequest struct {
	Name string `json:"name" binding:"required"`
}

type InitiateUploadRequest struct {
	Filename       string     `json:"filename" binding:"required"`
	MimeType       *string    `json:"mime_type"`
	TotalSizeBytes int64      `json:"total_size_bytes" binding:"required,min=1"`
	ChunkSizeBytes int        `json:"chunk_size_bytes"`
	TargetFolderID *uuid.UUID `json:"target_folder_id"`
}

type PresignedUploadRequest struct {
	Filename       string     `json:"filename" binding:"required"`
	MimeType       *string    `json:"mime_type"`
	SizeBytes      int64      `json:"size_bytes" binding:"required,min=1"`
	TargetFolderID *uuid.UUID `json:"target_folder_id"`
}

type PresignedUploadResponse struct {
	UploadURL string    `json:"upload_url"`
	FileID    uuid.UUID `json:"file_id"`
	ExpiresAt time.Time `json:"expires_at"`
}

type FileListRequest struct {
	Page     int        `form:"page,default=1"`
	PageSize int        `form:"page_size,default=20"`
	FolderID *uuid.UUID `form:"folder_id"`
	FileType *FileKind  `form:"file_type"`
	Search   *string    `form:"search"`
}

type PagedResponse[T any] struct {
	Items []T            `json:"items"`
	Meta  PaginationMeta `json:"meta"`
}

type PaginationMeta struct {
	Page       int   `json:"page"`
	PageSize   int   `json:"page_size"`
	Total      int64 `json:"total"`
	TotalPages int   `json:"total_pages"`
}

type APIError struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

type ErrorResponse struct {
	Error APIError `json:"error"`
}

// ── JWT Claims ────────────────────────────────────────────────────────────────

type Claims struct {
	Sub      string `json:"sub"`
	TenantID string `json:"tenant_id"`
	IsAdmin  bool   `json:"is_admin"`
}
