// 本文件负责按创作项目类型筛选当前剧集可下载的视频，并生成 ZIP 文件清单。
package service

import (
	"errors"
	"fmt"
	"path"
	"strings"

	"juhe-factory/api/internal/videoarchive"

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

// episodeVideoArchiveRow 描述生成视频查询结果及其在分镜中的业务状态。
type episodeVideoArchiveRow struct {
	ObjectKey  string
	MimeType   string
	SequenceNo int
	Active     bool
}

// EpisodeVideoArchive 查询当前剧集视频：短剧创作仅包含主视频和备选视频，视频转绘包含主视频和历史视频。
func (s *Creative) EpisodeVideoArchive(userID, projectID, episodeID uuid.UUID) (videoarchive.Manifest, error) {
	// 校验项目归属并获取项目类型，当前剧集视频 ZIP 仅对短剧创作和视频转绘开放。
	var project struct {
		ProjectType string
	}
	if err := s.DB.Table("creative_projects").Select("project_type").
		Where("id=? AND user_id=? AND deleted_at IS NULL", projectID, userID).
		Take(&project).Error; err != nil {
		return videoarchive.Manifest{}, err
	}
	if project.ProjectType != "premium_drama" && project.ProjectType != "video_redraw" {
		return videoarchive.Manifest{}, gorm.ErrRecordNotFound
	}
	var episode struct {
		ProjectName string
		EpisodeName string
	}
	if err := s.DB.Table("project_episodes episode").
		Select("project.name AS project_name,episode.name AS episode_name").
		Joins("JOIN creative_projects project ON project.id=episode.project_id AND project.deleted_at IS NULL").
		Where("episode.id=? AND episode.project_id=? AND episode.deleted_at IS NULL", episodeID, projectID).
		Take(&episode).Error; err != nil {
		return videoarchive.Manifest{}, err
	}

	rows := make([]episodeVideoArchiveRow, 0)
	query := s.DB.Table("generation_outputs output").
		Select(`media.object_key,media.mime_type,storyboard.sequence_no,
			storyboard.active_output_id=output.id AS active`).
		Joins("JOIN generation_tasks task ON task.id=output.task_id AND task.task_type='video_generation'").
		Joins("JOIN episode_storyboards storyboard ON storyboard.id=task.storyboard_id AND storyboard.deleted_at IS NULL").
		Joins("JOIN media_assets media ON media.id=output.media_asset_id AND media.deleted_at IS NULL").
		Where("storyboard.episode_id=?", episodeID)
	if project.ProjectType == "premium_drama" {
		query = query.Where("storyboard.active_output_id=output.id OR coalesce(output.metadata->>'candidate','false')='true'")
	}
	if err := query.Order("storyboard.sequence_no ASC,(storyboard.active_output_id=output.id) DESC,output.created_at DESC").Find(&rows).Error; err != nil {
		return videoarchive.Manifest{}, err
	}
	if len(rows) == 0 {
		return videoarchive.Manifest{}, errors.New("当前剧集暂无可下载视频")
	}

	entries := make([]videoarchive.Entry, 0, len(rows))
	versions := make(map[int]int)
	for _, row := range rows {
		label := "主视频"
		if !row.Active {
			versions[row.SequenceNo]++
			if project.ProjectType == "premium_drama" {
				label = fmt.Sprintf("备选视频%d", versions[row.SequenceNo])
			} else {
				label = fmt.Sprintf("历史视频%d", versions[row.SequenceNo])
			}
		}
		name := fmt.Sprintf("分镜%03d-%s%s", row.SequenceNo, label, videoArchiveExtension(row.ObjectKey, row.MimeType))
		entries = append(entries, videoarchive.Entry{ObjectKey: row.ObjectKey, Name: videoarchive.SafeFilename(name, "视频.mp4")})
	}
	archiveName := videoarchive.SafeFilename(episode.ProjectName+episode.EpisodeName, "剧集视频") + ".zip"
	return videoarchive.Manifest{Name: archiveName, Entries: entries}, nil
}

// videoArchiveExtension 根据已保存的媒体类型和对象键生成稳定的视频扩展名。
func videoArchiveExtension(objectKey, mimeType string) string {
	switch strings.ToLower(strings.TrimSpace(strings.Split(mimeType, ";")[0])) {
	case "video/webm":
		return ".webm"
	case "video/quicktime":
		return ".mov"
	case "video/x-m4v":
		return ".m4v"
	case "video/x-matroska":
		return ".mkv"
	case "video/x-msvideo":
		return ".avi"
	case "video/mp4":
		return ".mp4"
	}
	extension := strings.ToLower(path.Ext(objectKey))
	if map[string]bool{".mp4": true, ".webm": true, ".mov": true, ".m4v": true, ".mkv": true, ".avi": true}[extension] {
		return extension
	}
	return ".mp4"
}
