// 创作媒体服务，封装媒体上传前的所有权检查、关联更新和旧媒体清理事务。
package service

import (
	"strings"

	"juhe-factory/api/internal/model"

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

// MediaUploadTarget 汇总上传前需要的业务对象及待替换媒体信息。
type MediaUploadTarget struct {
	Project      *model.CreativeProject
	Episode      *model.ProjectEpisode
	Asset        *model.ProjectAsset
	OldMediaID   *uuid.UUID
	OldObjectKey string
}

// MediaObject 查询当前用户有权播放或下载的媒体对象键。
func (s *Creative) MediaObject(userID, mediaID uuid.UUID) (string, error) {
	var objectKey string
	err := s.DB.Table("media_assets").
		Where("id=? AND owner_user_id=? AND deleted_at IS NULL", mediaID, userID).
		Pluck("object_key", &objectKey).Error
	if err != nil {
		return "", err
	}
	if strings.TrimSpace(objectKey) == "" {
		return "", gorm.ErrRecordNotFound
	}
	return objectKey, nil
}

// PrepareRedrawMediaUpload 校验重绘项目所有权，并返回指定媒体类型的替换信息。
func (s *Creative) PrepareRedrawMediaUpload(userID, projectID uuid.UUID, kind string) (MediaUploadTarget, error) {
	var project model.CreativeProject
	if err := s.DB.Where("id=? AND user_id=? AND project_type='video_redraw' AND deleted_at IS NULL", projectID, userID).Take(&project).Error; err != nil {
		return MediaUploadTarget{}, err
	}
	oldMediaID := project.SourceVideoAssetID
	if kind == "subtitle" {
		oldMediaID = project.SubtitleAssetID
	}
	oldObjectKey, err := s.mediaObjectKey(oldMediaID)
	if err != nil {
		return MediaUploadTarget{}, err
	}
	return MediaUploadTarget{Project: &project, OldMediaID: oldMediaID, OldObjectKey: oldObjectKey}, nil
}

// PersistRedrawMediaUpload 在事务中保存新媒体、更新项目关联并删除旧媒体记录。
func (s *Creative) PersistRedrawMediaUpload(projectID uuid.UUID, kind, currentStatus string, media *model.MediaAsset, oldMediaID *uuid.UUID) error {
	column, status := "source_video_asset_id", "uploaded"
	if kind == "subtitle" {
		column, status = "subtitle_asset_id", currentStatus
	}
	return s.DB.Transaction(func(tx *gorm.DB) error {
		if err := tx.Create(media).Error; err != nil {
			return err
		}
		updates := map[string]any{column: media.ID, "redraw_status": status}
		if err := tx.Table("creative_projects").Where("id=?", projectID).Updates(updates).Error; err != nil {
			return err
		}
		return deleteReplacedMedia(tx, oldMediaID)
	})
}

// PrepareEpisodeMediaUpload 校验剧集与项目所有权，并返回指定媒体类型的替换信息。
func (s *Creative) PrepareEpisodeMediaUpload(userID, projectID, episodeID uuid.UUID, kind string) (MediaUploadTarget, error) {
	var episode model.ProjectEpisode
	err := s.DB.Table("project_episodes e").Joins("JOIN creative_projects p ON p.id=e.project_id").
		Where("e.id=? AND e.project_id=? AND e.deleted_at IS NULL AND p.user_id=? AND p.deleted_at IS NULL", episodeID, projectID, userID).
		Select("e.*").First(&episode).Error
	if err != nil {
		return MediaUploadTarget{}, err
	}
	oldMediaID := episode.SourceVideoAssetID
	if kind == "subtitle" {
		oldMediaID = episode.SubtitleAssetID
	}
	oldObjectKey, err := s.mediaObjectKey(oldMediaID)
	if err != nil {
		return MediaUploadTarget{}, err
	}
	return MediaUploadTarget{Episode: &episode, OldMediaID: oldMediaID, OldObjectKey: oldObjectKey}, nil
}

// PersistEpisodeMediaUpload 在事务中保存新媒体、更新剧集关联并删除旧媒体记录。
func (s *Creative) PersistEpisodeMediaUpload(episodeID uuid.UUID, kind string, status string, media *model.MediaAsset, oldMediaID *uuid.UUID) error {
	column := "source_video_asset_id"
	if kind == "subtitle" {
		column = "subtitle_asset_id"
	}
	return s.DB.Transaction(func(tx *gorm.DB) error {
		if err := tx.Create(media).Error; err != nil {
			return err
		}
		if err := tx.Table("project_episodes").Where("id=?", episodeID).Updates(map[string]any{column: media.ID, "status": status}).Error; err != nil {
			return err
		}
		return deleteReplacedMedia(tx, oldMediaID)
	})
}

// PrepareAssetMediaUpload 校验普通创作项目中的资产所有权并返回资产信息。
func (s *Creative) PrepareAssetMediaUpload(userID, projectID, assetID uuid.UUID) (MediaUploadTarget, error) {
	var asset model.ProjectAsset
	err := s.DB.Table("project_assets a").Joins("JOIN creative_projects p ON p.id=a.project_id").
		Where("a.id=? AND a.project_id=? AND a.deleted_at IS NULL AND p.user_id=? AND p.project_type<>'video_redraw' AND p.deleted_at IS NULL", assetID, projectID, userID).
		Select("a.*").First(&asset).Error
	if err != nil {
		return MediaUploadTarget{}, err
	}
	return MediaUploadTarget{Asset: &asset}, nil
}

// AttachUploadedAssetAudio 在事务中保存上传音频并更新资产关联。
func (s *Creative) AttachUploadedAssetAudio(assetID uuid.UUID, media *model.MediaAsset) error {
	return s.DB.Transaction(func(tx *gorm.DB) error {
		if err := tx.Create(media).Error; err != nil {
			return err
		}
		return tx.Table("project_assets").Where("id=?", assetID).Update("audio_asset_id", media.ID).Error
	})
}

// mediaObjectKey 查询待替换媒体的对象键；空媒体标识表示无需清理。
func (s *Creative) mediaObjectKey(mediaID *uuid.UUID) (string, error) {
	if mediaID == nil {
		return "", nil
	}
	var objectKey string
	if err := s.DB.Table("media_assets").Where("id=?", *mediaID).Pluck("object_key", &objectKey).Error; err != nil {
		return "", err
	}
	return objectKey, nil
}

// deleteReplacedMedia 删除旧媒体的渠道缓存和媒体记录，供上传事务复用。
func deleteReplacedMedia(tx *gorm.DB, mediaID *uuid.UUID) error {
	if mediaID == nil {
		return nil
	}
	if err := tx.Exec("DELETE FROM channel_asset_cache WHERE media_asset_id=?", *mediaID).Error; err != nil {
		return err
	}
	return tx.Exec("DELETE FROM media_assets WHERE id=?", *mediaID).Error
}
