package handlers

import (
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/niangaodev/art-code/models"
	"github.com/niangaodev/art-code/repositories"
	"github.com/niangaodev/art-code/utils"
)

// ========== 公开 API ==========

// GetVideoCategories 获取视频分类列表
func GetVideoCategories(c *gin.Context) {
	list, err := repositories.GetVideoCategories()
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.Success(c, repositories.BuildVideoCategoriesResponse(list))
}

// GetVideoAlbums 获取视频专辑列表
func GetVideoAlbums(c *gin.Context) {
	categoryID, _ := strconv.ParseUint(c.Query("categoryId"), 10, 32)
	list, err := repositories.GetActiveVideoAlbums(uint(categoryID))
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.Success(c, repositories.BuildVideoAlbumsResponse(list, true))
}

// GetVideoAlbumByID 获取专辑详情
func GetVideoAlbumByID(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		utils.Error(c, 400, "Invalid album ID")
		return
	}
	album, err := repositories.GetVideoAlbumByID(uint(id))
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	if album == nil || album.IsActive != 1 {
		utils.Error(c, 404, "Album not found")
		return
	}
	utils.Success(c, repositories.BuildVideoAlbumResponse(album, true))
}

// GetAlbumVideos 获取专辑内视频
func GetAlbumVideos(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		utils.Error(c, 400, "Invalid album ID")
		return
	}
	list, err := repositories.GetVideosByAlbumID(uint(id), true)
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.Success(c, repositories.BuildVideosResponse(list))
}

// GetVideos 获取视频列表
func GetVideos(c *gin.Context) {
	categoryID, _ := strconv.ParseUint(c.Query("categoryId"), 10, 32)
	list, err := repositories.GetVideos(uint(categoryID), true)
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.Success(c, repositories.BuildVideosResponse(list))
}

// GetVideoByID 获取视频详情
func GetVideoByID(c *gin.Context) {
	id := c.Param("id")
	video, err := repositories.GetVideoByID(id)
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	if video == nil || video.IsPublished != 1 {
		utils.Error(c, 404, "Video not found")
		return
	}
	utils.Success(c, repositories.BuildVideoDetailResponse(video))
}

// ========== 管理 API — 分类 ==========

func AdminGetVideoCategories(c *gin.Context) {
	list, err := repositories.GetVideoCategories()
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.Success(c, repositories.BuildVideoCategoriesResponse(list))
}

func AdminCreateVideoCategory(c *gin.Context) {
	var item models.VideoCategory
	if err := c.ShouldBindJSON(&item); err != nil {
		utils.Error(c, 400, err.Error())
		return
	}
	if err := repositories.CreateVideoCategory(&item); err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.Success(c, repositories.BuildVideoCategoryResponse(&item))
}

func AdminUpdateVideoCategory(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		utils.Error(c, 400, "Invalid category ID")
		return
	}
	var item models.VideoCategory
	if err := c.ShouldBindJSON(&item); err != nil {
		utils.Error(c, 400, err.Error())
		return
	}
	item.ID = uint(id)
	if err := repositories.UpdateVideoCategory(&item); err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.Success(c, repositories.BuildVideoCategoryResponse(&item))
}

func AdminDeleteVideoCategory(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		utils.Error(c, 400, "Invalid category ID")
		return
	}
	if err := repositories.DeleteVideoCategory(uint(id)); err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.SuccessWithMsg(c, "Category deleted", nil)
}

// ========== 管理 API — 专辑 ==========

func AdminGetVideoAlbums(c *gin.Context) {
	categoryID, _ := strconv.ParseUint(c.Query("categoryId"), 10, 32)
	list, err := repositories.GetVideoAlbums(uint(categoryID))
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.Success(c, repositories.BuildVideoAlbumsResponse(list, false))
}

func AdminCreateVideoAlbum(c *gin.Context) {
	var item models.VideoAlbum
	if err := c.ShouldBindJSON(&item); err != nil {
		utils.Error(c, 400, err.Error())
		return
	}
	if err := repositories.CreateVideoAlbum(&item); err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.Success(c, repositories.BuildVideoAlbumResponse(&item, false))
}

func AdminUpdateVideoAlbum(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		utils.Error(c, 400, "Invalid album ID")
		return
	}
	var req struct {
		models.VideoAlbum
		VideoIDs []string `json:"videoIds"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.Error(c, 400, err.Error())
		return
	}
	req.VideoAlbum.ID = uint(id)
	if err := repositories.UpdateVideoAlbum(&req.VideoAlbum); err != nil {
		utils.ServerError(c, err)
		return
	}
	if req.VideoIDs != nil {
		if err := repositories.SyncAlbumVideos(uint(id), req.VideoIDs); err != nil {
			utils.ServerError(c, err)
			return
		}
	}
	utils.Success(c, repositories.BuildVideoAlbumResponse(&req.VideoAlbum, false))
}

func AdminDeleteVideoAlbum(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		utils.Error(c, 400, "Invalid album ID")
		return
	}
	if err := repositories.DeleteVideoAlbum(uint(id)); err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.SuccessWithMsg(c, "Album deleted", nil)
}

func AdminAddVideoToAlbum(c *gin.Context) {
	albumID, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		utils.Error(c, 400, "Invalid album ID")
		return
	}
	var req struct {
		VideoID   string `json:"videoId"`
		SortOrder uint   `json:"sortOrder"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.Error(c, 400, err.Error())
		return
	}
	if err := repositories.AddVideoToAlbum(uint(albumID), req.VideoID, req.SortOrder); err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.SuccessWithMsg(c, "Video added to album", nil)
}

func AdminRemoveVideoFromAlbum(c *gin.Context) {
	albumID, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		utils.Error(c, 400, "Invalid album ID")
		return
	}
	videoID := c.Param("videoId")
	if err := repositories.RemoveVideoFromAlbum(uint(albumID), videoID); err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.SuccessWithMsg(c, "Video removed from album", nil)
}

func AdminGetAlbumVideoIDs(c *gin.Context) {
	albumID, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		utils.Error(c, 400, "Invalid album ID")
		return
	}
	videos, err := repositories.GetVideosByAlbumID(uint(albumID), false)
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	ids := make([]string, 0, len(videos))
	for _, v := range videos {
		ids = append(ids, v.ID)
	}
	utils.Success(c, ids)
}

// ========== 管理 API — 视频 ==========

func AdminGetVideos(c *gin.Context) {
	categoryID, _ := strconv.ParseUint(c.Query("categoryId"), 10, 32)
	list, err := repositories.GetVideos(uint(categoryID), false)
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.Success(c, repositories.BuildAdminVideosResponse(list))
}

func AdminCreateVideo(c *gin.Context) {
	var req struct {
		models.Video
		AlbumIDs []uint `json:"albumIds"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.Error(c, 400, err.Error())
		return
	}
	if req.Video.ID == "" {
		req.Video.ID = "video_" + strconv.FormatInt(time.Now().UnixNano(), 10)
	}
	if err := repositories.CreateVideo(&req.Video); err != nil {
		utils.ServerError(c, err)
		return
	}
	if req.AlbumIDs != nil {
		if err := repositories.SyncVideoAlbums(req.Video.ID, req.AlbumIDs); err != nil {
			utils.ServerError(c, err)
			return
		}
	}
	utils.Success(c, repositories.BuildAdminVideoResponse(&req.Video))
}

func AdminUpdateVideo(c *gin.Context) {
	id := c.Param("id")
	var req struct {
		models.Video
		AlbumIDs []uint `json:"albumIds"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.Error(c, 400, err.Error())
		return
	}
	req.Video.ID = id
	if err := repositories.UpdateVideo(&req.Video); err != nil {
		utils.ServerError(c, err)
		return
	}
	if req.AlbumIDs != nil {
		if err := repositories.SyncVideoAlbums(id, req.AlbumIDs); err != nil {
			utils.ServerError(c, err)
			return
		}
	}
	video, _ := repositories.GetVideoByID(id)
	if video == nil {
		utils.Error(c, 404, "Video not found")
		return
	}
	utils.Success(c, repositories.BuildAdminVideoResponse(video))
}

func AdminDeleteVideo(c *gin.Context) {
	id := c.Param("id")
	if err := repositories.DeleteVideo(id); err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.SuccessWithMsg(c, "Video deleted", nil)
}

func AdminGetVideoByID(c *gin.Context) {
	id := c.Param("id")
	video, err := repositories.GetVideoByID(id)
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	if video == nil {
		utils.Error(c, 404, "Video not found")
		return
	}
	utils.Success(c, repositories.BuildAdminVideoResponse(video))
}
