package model

import (
	"encoding/json"
	"time"

	"github.com/google/uuid"
	"gorm.io/gorm"
)

type MediaAsset struct {
	ID              uuid.UUID  `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"`
	OwnerUserID     *uuid.UUID `gorm:"type:uuid" json:"owner_user_id"`
	StorageProvider string     `json:"storage_provider"`
	ObjectKey       string     `json:"object_key"`
	PublicURL       string     `json:"public_url"`
	OriginalName    string     `json:"original_name"`
	DisplayName     string     `json:"display_name"`
	MimeType        string     `json:"mime_type"`
	SizeBytes       int64      `json:"size_bytes"`
	SHA256          string     `json:"sha256"`
	Width           *int       `json:"width"`
	Height          *int       `json:"height"`
	DurationMS      *int64     `json:"duration_ms"`
	CreatedAt       time.Time  `json:"created_at"`
	DeletedAt       *time.Time `json:"-"`
}

type CreativeProject struct {
	ID                 uuid.UUID       `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"`
	UserID             uuid.UUID       `gorm:"type:uuid" json:"user_id"`
	ProjectType        string          `json:"project_type"`
	Name               string          `json:"name"`
	CoverAssetID       *uuid.UUID      `gorm:"type:uuid" json:"cover_asset_id"`
	StyleID            uuid.UUID       `gorm:"type:uuid" json:"style_id"`
	EraType            string          `json:"era_type"`
	CustomEra          *string         `json:"custom_era"`
	AspectRatio        string          `json:"aspect_ratio"`
	Localization       *string         `json:"localization"`
	SourceVideoAssetID *uuid.UUID      `gorm:"type:uuid" json:"source_video_asset_id"`
	SubtitleAssetID    *uuid.UUID      `gorm:"type:uuid" json:"subtitle_asset_id"`
	AudioSource        string          `json:"audio_source"`
	SourceLanguage     *string         `json:"source_language"`
	RedrawStatus       string          `json:"redraw_status"`
	AnalysisMessage    string          `json:"analysis_message"`
	RedrawScript       string          `json:"redraw_script"`
	ShortDramaType     *string         `json:"short_drama_type"`
	PlayCount          *string         `json:"play_count"`
	AudienceProfile    *string         `json:"audience_profile"`
	Producer           *string         `json:"producer"`
	CastMembers        json.RawMessage `gorm:"type:jsonb;not null;default:'[]'" json:"cast_members"`
	CreatedAt          time.Time       `json:"created_at"`
	UpdatedAt          time.Time       `json:"updated_at"`
	DeletedAt          *time.Time      `json:"-"`
}

func (project *CreativeProject) BeforeCreate(_ *gorm.DB) error {
	if len(project.CastMembers) == 0 {
		project.CastMembers = json.RawMessage("[]")
	}
	return nil
}

type ProjectModelConfig struct {
	ID        uuid.UUID  `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"`
	ProjectID uuid.UUID  `gorm:"type:uuid" json:"project_id"`
	Purpose   string     `json:"purpose"`
	ModelType string     `json:"model_type"`
	ModelID   uuid.UUID  `gorm:"type:uuid" json:"model_id"`
	PromptID  *uuid.UUID `gorm:"type:uuid" json:"prompt_id"`
	CreatedAt time.Time  `json:"created_at"`
	UpdatedAt time.Time  `json:"updated_at"`
}

type UserModelConfig struct {
	ID          uuid.UUID       `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"`
	UserID      uuid.UUID       `gorm:"type:uuid" json:"user_id"`
	Purpose     string          `json:"purpose"`
	ProjectType string          `json:"project_type"`
	ModelType   string          `json:"model_type"`
	ModelID     uuid.UUID       `gorm:"type:uuid" json:"model_id"`
	PromptID    *uuid.UUID      `gorm:"type:uuid" json:"prompt_id"`
	Settings    json.RawMessage `gorm:"type:jsonb" json:"settings"`
	CreatedAt   time.Time       `json:"created_at"`
	UpdatedAt   time.Time       `json:"updated_at"`
}

type ProjectEpisode struct {
	ID                 uuid.UUID  `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"`
	ProjectID          uuid.UUID  `gorm:"type:uuid" json:"project_id"`
	EpisodeNo          int        `json:"episode_no"`
	Name               string     `json:"name"`
	CoverAssetID       *uuid.UUID `gorm:"type:uuid" json:"cover_asset_id"`
	SourceVideoAssetID *uuid.UUID `gorm:"type:uuid" json:"source_video_asset_id"`
	SubtitleAssetID    *uuid.UUID `gorm:"type:uuid" json:"subtitle_asset_id"`
	AudioSource        string     `json:"audio_source"`
	SourceLanguage     *string    `json:"source_language"`
	Status             string     `json:"status"`
	AnalysisMessage    string     `json:"analysis_message"`
	RedrawScript       string     `json:"redraw_script"`
	CreatedAt          time.Time  `json:"created_at"`
	UpdatedAt          time.Time  `json:"updated_at"`
	DeletedAt          *time.Time `json:"-"`
}

type ProjectAsset struct {
	ID                uuid.UUID       `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"`
	ProjectID         uuid.UUID       `gorm:"type:uuid" json:"project_id"`
	SourceEpisodeID   *uuid.UUID      `gorm:"type:uuid" json:"source_episode_id"`
	AssetType         string          `json:"asset_type"`
	Name              string          `json:"name"`
	Description       string          `json:"description"`
	ImagePrompt       string          `json:"image_prompt"`
	Appearances       json.RawMessage `gorm:"type:jsonb" json:"appearances"`
	ImageAssetID      *uuid.UUID      `gorm:"type:uuid" json:"image_asset_id"`
	AudioAssetID      *uuid.UUID      `gorm:"type:uuid" json:"audio_asset_id"`
	UserEdited        bool            `json:"user_edited"`
	Aliases           json.RawMessage `gorm:"type:jsonb" json:"aliases"`
	Attributes        json.RawMessage `gorm:"type:jsonb" json:"attributes"`
	AIDescription     string          `gorm:"column:ai_description" json:"ai_description"`
	SourceParseTaskID *uuid.UUID      `gorm:"type:uuid" json:"source_parse_task_id"`
	CreatedAt         time.Time       `json:"created_at"`
	UpdatedAt         time.Time       `json:"updated_at"`
	DeletedAt         *time.Time      `json:"-"`
}

func (asset *ProjectAsset) BeforeCreate(_ *gorm.DB) error {
	if len(asset.Appearances) == 0 {
		asset.Appearances = json.RawMessage("[]")
	}
	if len(asset.Aliases) == 0 {
		asset.Aliases = json.RawMessage("[]")
	}
	if len(asset.Attributes) == 0 {
		asset.Attributes = json.RawMessage("{}")
	}
	return nil
}

type EpisodeStoryboard struct {
	ID                uuid.UUID       `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"`
	EpisodeID         *uuid.UUID      `gorm:"type:uuid" json:"episode_id"`
	ProjectID         *uuid.UUID      `gorm:"type:uuid" json:"project_id"`
	SequenceNo        int             `json:"sequence_no"`
	StableKey         string          `json:"stable_key"`
	StartMS           int64           `json:"start_ms"`
	EndMS             int64           `json:"end_ms"`
	DurationSeconds   int             `json:"duration_seconds"`
	Title             string          `json:"title"`
	ThumbnailAssetID  *uuid.UUID      `gorm:"type:uuid" json:"thumbnail_asset_id"`
	PromptContent     string          `json:"prompt_content"`
	ImagePrompt       string          `json:"image_prompt"`
	ScriptContent     string          `json:"script_content"`
	SourceExcerpt     string          `json:"source_excerpt"`
	Dialogue          json.RawMessage `gorm:"type:jsonb" json:"dialogue"`
	AssetRefs         json.RawMessage `gorm:"type:jsonb" json:"asset_refs"`
	Locked            bool            `json:"locked"`
	ActiveOutputID    *uuid.UUID      `gorm:"type:uuid" json:"active_output_id"`
	Status            string          `json:"status"`
	SourceParseTaskID *uuid.UUID      `gorm:"type:uuid" json:"source_parse_task_id"`
	UserEdited        bool            `json:"user_edited"`
	CreatedAt         time.Time       `json:"created_at"`
	UpdatedAt         time.Time       `json:"updated_at"`
	DeletedAt         *time.Time      `json:"-"`
}

type EpisodeSource struct {
	ID             uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"`
	EpisodeID      uuid.UUID `gorm:"type:uuid;uniqueIndex" json:"episode_id"`
	Title          string    `json:"title"`
	RawContent     string    `json:"raw_content"`
	CharCount      int       `json:"char_count"`
	SourceType     string    `json:"source_type"`
	SourceFilename string    `json:"source_filename"`
	ContentSHA256  string    `gorm:"column:content_sha256" json:"content_sha256"`
	CreatedAt      time.Time `json:"created_at"`
	UpdatedAt      time.Time `json:"updated_at"`
}

type DramaImportSession struct {
	ID             uuid.UUID       `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"`
	UserID         uuid.UUID       `gorm:"type:uuid" json:"user_id"`
	ProjectID      uuid.UUID       `gorm:"type:uuid" json:"project_id"`
	SourceType     string          `json:"source_type"`
	SourceFilename string          `json:"source_filename"`
	RawContent     string          `json:"-"`
	ContentSHA256  string          `gorm:"column:content_sha256" json:"content_sha256"`
	PreviewData    json.RawMessage `gorm:"type:jsonb" json:"preview_data"`
	ExpiresAt      time.Time       `json:"expires_at"`
	ConsumedAt     *time.Time      `json:"consumed_at"`
	CreatedAt      time.Time       `json:"created_at"`
}

type DramaParseBatch struct {
	ID                uuid.UUID  `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"`
	ProjectID         uuid.UUID  `gorm:"type:uuid" json:"project_id"`
	UserID            uuid.UUID  `gorm:"type:uuid" json:"user_id"`
	Mode              string     `json:"mode"`
	Status            string     `json:"status"`
	TotalCount        int        `json:"total_count"`
	CompletedCount    int        `json:"completed_count"`
	FailedCount       int        `json:"failed_count"`
	CurrentEpisodeID  *uuid.UUID `gorm:"type:uuid" json:"current_episode_id"`
	CancelRequestedAt *time.Time `json:"cancel_requested_at"`
	CreatedAt         time.Time  `json:"created_at"`
	FinishedAt        *time.Time `json:"finished_at"`
}

type DramaParseTask struct {
	ID                uuid.UUID       `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"`
	RequestID         string          `json:"request_id"`
	BatchID           *uuid.UUID      `gorm:"type:uuid" json:"batch_id"`
	UserID            uuid.UUID       `gorm:"type:uuid" json:"user_id"`
	ProjectID         uuid.UUID       `gorm:"type:uuid" json:"project_id"`
	EpisodeID         uuid.UUID       `gorm:"type:uuid" json:"episode_id"`
	ChannelID         uuid.UUID       `gorm:"type:uuid" json:"channel_id"`
	ModelID           uuid.UUID       `gorm:"type:uuid" json:"model_id"`
	SourceSHA256      string          `gorm:"column:source_sha256" json:"source_sha256"`
	Status            string          `json:"status"`
	AttemptCount      int             `json:"attempt_count"`
	ModelSnapshot     json.RawMessage `gorm:"type:jsonb" json:"model_snapshot"`
	PromptSnapshot    string          `json:"prompt_snapshot"`
	ContextSnapshot   json.RawMessage `gorm:"type:jsonb" json:"context_snapshot"`
	NormalizedResult  json.RawMessage `gorm:"type:jsonb" json:"normalized_result"`
	InputTokens       *int64          `json:"input_tokens"`
	OutputTokens      *int64          `json:"output_tokens"`
	TotalTokens       *int64          `json:"total_tokens"`
	TokenCountSource  string          `json:"token_count_source"`
	UsageRaw          json.RawMessage `gorm:"type:jsonb" json:"usage_raw"`
	BillingSnapshot   json.RawMessage `gorm:"type:jsonb;not null;default:'{}'" json:"billing_snapshot"`
	EstimatedPoints   string          `gorm:"column:estimated_points" json:"estimated_points"`
	PrepaidPoints     string          `gorm:"column:prepaid_points" json:"prepaid_points"`
	ActualPoints      *string         `gorm:"column:actual_points" json:"actual_points"`
	CostRefunded      bool            `json:"cost_refunded"`
	RequestCharCount  int64           `json:"request_char_count"`
	ResponseCharCount int64           `json:"response_char_count"`
	LeaseOwner        string          `json:"lease_owner"`
	LeaseUntil        *time.Time      `json:"lease_until"`
	CancelRequestedAt *time.Time      `json:"cancel_requested_at"`
	ErrorCode         string          `json:"error_code"`
	ErrorMessage      string          `json:"error_message"`
	CreatedAt         time.Time       `json:"created_at"`
	StartedAt         *time.Time      `json:"started_at"`
	FinishedAt        *time.Time      `json:"finished_at"`
}

type GenerationTask struct {
	ID                uuid.UUID       `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"`
	RequestID         string          `json:"request_id"`
	UserID            uuid.UUID       `gorm:"type:uuid" json:"user_id"`
	ChannelID         *uuid.UUID      `gorm:"type:uuid" json:"channel_id"`
	ModelID           *uuid.UUID      `gorm:"type:uuid" json:"model_id"`
	ProjectID         *uuid.UUID      `gorm:"type:uuid" json:"project_id"`
	EpisodeID         *uuid.UUID      `gorm:"type:uuid" json:"episode_id"`
	StoryboardID      *uuid.UUID      `gorm:"type:uuid" json:"storyboard_id"`
	ScriptAnalysisID  *uuid.UUID      `gorm:"type:uuid" json:"script_analysis_id"`
	TaskType          string          `json:"task_type"`
	Status            string          `json:"status"`
	UpstreamTaskID    string          `json:"upstream_task_id"`
	InputData         json.RawMessage `gorm:"type:jsonb" json:"input_data"`
	BillingSnapshot   json.RawMessage `gorm:"type:jsonb;not null;default:'{}'" json:"billing_snapshot"`
	InputTokens       *int64          `json:"input_tokens"`
	OutputTokens      *int64          `json:"output_tokens"`
	TotalTokens       *int64          `json:"total_tokens"`
	TokenCountSource  *string         `json:"token_count_source"`
	UsageRaw          json.RawMessage `gorm:"type:jsonb" json:"usage_raw"`
	ResultData        json.RawMessage `gorm:"type:jsonb;not null;default:'{}'" json:"result_data"`
	PromptSnapshot    string          `json:"prompt_snapshot"`
	EstimatedPoints   string          `gorm:"column:estimated_points" json:"estimated_points"`
	ActualPoints      *string         `gorm:"column:actual_points" json:"actual_points"`
	PrepaidPoints     string          `gorm:"column:prepaid_points" json:"prepaid_points"`
	CostRefunded      bool            `json:"cost_refunded"`
	SlotReserved      bool            `json:"slot_reserved"`
	SlotReservedAt    *time.Time      `json:"slot_reserved_at"`
	SlotReleasedAt    *time.Time      `json:"slot_released_at"`
	SubmitAttempts    int             `json:"submit_attempts"`
	PollAttempts      int             `json:"poll_attempts"`
	DownloadAttempts  int             `json:"download_attempts"`
	NextSubmitAt      *time.Time      `json:"next_submit_at"`
	NextPollAt        *time.Time      `json:"next_poll_at"`
	LeaseOwner        string          `json:"lease_owner"`
	LeaseUntil        *time.Time      `json:"lease_until"`
	UpstreamResultURL string          `json:"-"`
	ErrorCode         string          `json:"error_code"`
	ErrorMessage      string          `json:"error_message"`
	CreatedAt         time.Time       `json:"created_at"`
	SubmittedAt       *time.Time      `json:"submitted_at"`
	FinishedAt        *time.Time      `json:"finished_at"`
}

type GenerationOutput struct {
	ID           uuid.UUID       `gorm:"type:uuid;default:gen_random_uuid();primaryKey" json:"id"`
	TaskID       uuid.UUID       `gorm:"type:uuid" json:"task_id"`
	MediaAssetID uuid.UUID       `gorm:"type:uuid" json:"media_asset_id"`
	OutputType   string          `json:"output_type"`
	SequenceNo   int             `json:"sequence_no"`
	Metadata     json.RawMessage `gorm:"type:jsonb" json:"metadata"`
	CreatedAt    time.Time       `json:"created_at"`
}
