package handler

import (
	"errors"
	"io"
	"net/http"
	"strings"

	"juhe-factory/api/internal/service"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

func (h *Creative) PreviewDramaImport(c *gin.Context) {
	projectID, ok := h.projectID(c)
	if !ok {
		return
	}
	c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 4<<20)
	if err := c.Request.ParseMultipartForm(4 << 20); err != nil {
		h.bad(c, errors.New("导入内容无效"))
		return
	}
	if c.Request.MultipartForm != nil {
		defer c.Request.MultipartForm.RemoveAll()
	}
	rawText := strings.TrimSpace(c.PostForm("raw_text"))
	var filename string
	var content []byte
	file, header, err := c.Request.FormFile("file")
	if err == nil {
		defer file.Close()
		filename = header.Filename
		content, err = io.ReadAll(io.LimitReader(file, 3*1024*1024+1))
		if err != nil {
			h.bad(c, errors.New("读取小说文件失败"))
			return
		}
	} else if rawText == "" {
		h.bad(c, errors.New("请选择小说文件或粘贴文本"))
		return
	}
	preview, err := h.service.PreviewDramaImport(currentWebUser(c).ID, projectID, filename, content, rawText)
	if err != nil {
		h.respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": preview})
}

func (h *Creative) ConfirmDramaImport(c *gin.Context) {
	projectID, ok := h.projectID(c)
	if !ok {
		return
	}
	var body struct {
		ImportToken          uuid.UUID `json:"import_token"`
		ChaptersPerEpisode   int       `json:"chapters_per_episode"`
		StartEpisodeNo       int       `json:"start_episode_no"`
		TreatAsSingleEpisode bool      `json:"treat_as_single_episode"`
	}
	if err := c.ShouldBindJSON(&body); err != nil || body.ImportToken == uuid.Nil {
		h.bad(c, errors.New("导入确认参数无效"))
		return
	}
	items, err := h.service.ConfirmDramaImport(currentWebUser(c).ID, projectID, body.ImportToken, body.ChaptersPerEpisode, body.StartEpisodeNo, body.TreatAsSingleEpisode)
	if err != nil {
		h.respondError(c, err)
		return
	}
	c.JSON(http.StatusCreated, gin.H{"data": items})
}

func (h *Creative) GetDramaEpisodeSource(c *gin.Context) {
	projectID, episodeID, ok := h.dramaEpisodeIDs(c)
	if !ok {
		return
	}
	source, err := h.service.EpisodeSource(currentWebUser(c).ID, projectID, episodeID)
	if err != nil {
		h.respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": source})
}

func (h *Creative) SaveDramaEpisodeSource(c *gin.Context) {
	projectID, episodeID, ok := h.dramaEpisodeIDs(c)
	if !ok {
		return
	}
	var body struct {
		Title      string `json:"title"`
		RawContent string `json:"raw_content"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		h.bad(c, err)
		return
	}
	source, err := h.service.SaveEpisodeSource(currentWebUser(c).ID, projectID, episodeID, body.RawContent, body.Title)
	if err != nil {
		h.respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": source})
}

func (h *Creative) QueueDramaParse(c *gin.Context) {
	projectID, episodeID, ok := h.dramaEpisodeIDs(c)
	if !ok {
		return
	}
	task, err := h.service.QueueDramaParse(currentWebUser(c).ID, projectID, episodeID)
	if err != nil {
		h.respondError(c, err)
		return
	}
	c.JSON(http.StatusAccepted, gin.H{"data": task})
}

func (h *Creative) ReparseDrama(c *gin.Context) {
	if !h.objectStorageAvailable(c) {
		return
	}
	projectID, episodeID, ok := h.dramaEpisodeIDs(c)
	if !ok {
		return
	}
	userID := currentWebUser(c).ID
	objectKeys, err := h.service.ResetEpisodeAnalysis(userID, projectID, episodeID)
	if err != nil {
		h.respondError(c, err)
		return
	}
	if !h.deleteStoredObjects(c, objectKeys) {
		return
	}
	task, err := h.service.QueueDramaParse(userID, projectID, episodeID)
	if err != nil {
		h.respondError(c, err)
		return
	}
	c.JSON(http.StatusAccepted, gin.H{"data": task})
}

func (h *Creative) ListDramaParseTasks(c *gin.Context) {
	projectID, ok := h.projectID(c)
	if !ok {
		return
	}
	var episodeID *uuid.UUID
	if raw := strings.TrimSpace(c.Query("episode_id")); raw != "" {
		parsed, err := service.ParseUUID(raw, "剧集")
		if err != nil {
			h.bad(c, err)
			return
		}
		episodeID = &parsed
	}
	items, err := h.service.ListDramaParseTasks(currentWebUser(c).ID, projectID, episodeID)
	if err != nil {
		h.respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": items})
}

func (h *Creative) CancelDramaParse(c *gin.Context) {
	projectID, ok := h.projectID(c)
	if !ok {
		return
	}
	taskID, err := service.ParseUUID(c.Param("task_id"), "解析任务")
	if err != nil {
		h.bad(c, err)
		return
	}
	if err = h.service.CancelDramaParse(currentWebUser(c).ID, projectID, taskID); err != nil {
		h.respondError(c, err)
		return
	}
	c.Status(http.StatusNoContent)
}

func (h *Creative) CreateDramaStoryboard(c *gin.Context) {
	projectID, episodeID, ok := h.dramaEpisodeIDs(c)
	if !ok {
		return
	}
	storyboard, err := h.service.CreateStoryboard(currentWebUser(c).ID, projectID, episodeID)
	if err != nil {
		h.respondError(c, err)
		return
	}
	c.JSON(http.StatusCreated, gin.H{"data": storyboard})
}

func (h *Creative) dramaEpisodeIDs(c *gin.Context) (uuid.UUID, uuid.UUID, bool) {
	projectID, ok := h.projectID(c)
	if !ok {
		return uuid.Nil, uuid.Nil, false
	}
	episodeID, err := service.ParseUUID(c.Param("episode_id"), "剧集")
	if err != nil {
		h.bad(c, err)
		return uuid.Nil, uuid.Nil, false
	}
	return projectID, episodeID, true
}
