package handlers

import (
	"errors"
	"fmt"
	"strings"

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

func pptTemplatePayloads(list []models.PptTemplate) ([]models.PptTemplatePayload, error) {
	out := make([]models.PptTemplatePayload, 0, len(list))
	for i := range list {
		p, err := repositories.ToPptTemplatePayload(&list[i])
		if err != nil {
			return nil, err
		}
		out = append(out, p)
	}
	return out, nil
}

// GetPptTemplates 公开：获取启用的 PPT 模板
func GetPptTemplates(c *gin.Context) {
	list, err := repositories.GetActivePptTemplates()
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	payloads, err := pptTemplatePayloads(list)
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	if payloads == nil {
		payloads = []models.PptTemplatePayload{}
	}
	utils.Success(c, payloads)
}

// GetDefaultPptTemplate 公开：获取系统默认模板
func GetDefaultPptTemplate(c *gin.Context) {
	t, err := repositories.GetSystemPptTemplate()
	if err != nil {
		utils.Error(c, 404, "Default template not found")
		return
	}
	payload, err := repositories.ToPptTemplatePayload(t)
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.Success(c, payload)
}

// AdminGetPptTemplates 管理：获取全部模板
func AdminGetPptTemplates(c *gin.Context) {
	list, err := repositories.GetAllPptTemplates()
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	payloads, err := pptTemplatePayloads(list)
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	if payloads == nil {
		payloads = []models.PptTemplatePayload{}
	}
	utils.Success(c, payloads)
}

// AdminCreatePptTemplate 管理：创建模板
func AdminCreatePptTemplate(c *gin.Context) {
	var req models.PptTemplatePayload
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.Error(c, 400, "Invalid request")
		return
	}

	req.Name = strings.TrimSpace(req.Name)
	req.Slug = strings.TrimSpace(req.Slug)
	if req.Name == "" || req.Slug == "" {
		utils.Error(c, 400, "Name and slug are required")
		return
	}
	if req.Slug == repositories.DefaultPptTemplateSlug {
		utils.Error(c, 400, "Slug 'default' is reserved for system template")
		return
	}

	configJSON, err := repositories.SerializePptTemplateConfig(req.Config)
	if err != nil {
		utils.Error(c, 400, "Invalid config JSON")
		return
	}

	t := models.PptTemplate{
		Name:        req.Name,
		Slug:        req.Slug,
		Description: strings.TrimSpace(req.Description),
		Config:      configJSON,
		IsSystem:    false,
		IsDefault:   req.IsDefault,
		SortOrder:   req.SortOrder,
		IsActive:    req.IsActive,
	}

	if err := repositories.CreatePptTemplate(&t); err != nil {
		utils.ServerError(c, err)
		return
	}

	if t.IsDefault {
		_ = repositories.ClearDefaultPptTemplatesExcept(t.ID)
	}

	payload, err := repositories.ToPptTemplatePayload(&t)
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.SuccessWithMsg(c, "PPT template created", payload)
}

// AdminUpdatePptTemplate 管理：更新模板
func AdminUpdatePptTemplate(c *gin.Context) {
	idStr := c.Param("id")
	var id uint
	if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
		utils.Error(c, 400, "Invalid ID")
		return
	}

	existing, err := repositories.GetPptTemplateByID(id)
	if err != nil {
		utils.Error(c, 404, "Template not found")
		return
	}

	var req models.PptTemplatePayload
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.Error(c, 400, "Invalid request")
		return
	}

	req.Name = strings.TrimSpace(req.Name)
	if req.Name == "" {
		utils.Error(c, 400, "Name is required")
		return
	}

	configJSON, err := repositories.SerializePptTemplateConfig(req.Config)
	if err != nil {
		utils.Error(c, 400, "Invalid config JSON")
		return
	}

	t := *existing
	t.Name = req.Name
	t.Description = strings.TrimSpace(req.Description)
	t.Config = configJSON
	t.SortOrder = req.SortOrder

	if existing.IsSystem {
		t.Slug = repositories.DefaultPptTemplateSlug
		t.IsSystem = true
		t.IsActive = true
		t.IsDefault = req.IsDefault
	} else {
		req.Slug = strings.TrimSpace(req.Slug)
		if req.Slug == "" {
			utils.Error(c, 400, "Slug is required")
			return
		}
		if req.Slug == repositories.DefaultPptTemplateSlug {
			utils.Error(c, 400, "Slug 'default' is reserved")
			return
		}
		t.Slug = req.Slug
		t.IsDefault = req.IsDefault
		t.IsActive = req.IsActive
	}

	if err := repositories.UpdatePptTemplate(&t); err != nil {
		utils.ServerError(c, err)
		return
	}

	if t.IsDefault {
		_ = repositories.ClearDefaultPptTemplatesExcept(t.ID)
	}

	payload, err := repositories.ToPptTemplatePayload(&t)
	if err != nil {
		utils.ServerError(c, err)
		return
	}
	utils.SuccessWithMsg(c, "PPT template updated", payload)
}

// AdminDeletePptTemplate 管理：删除模板
func AdminDeletePptTemplate(c *gin.Context) {
	idStr := c.Param("id")
	var id uint
	if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
		utils.Error(c, 400, "Invalid ID")
		return
	}

	if err := repositories.DeletePptTemplate(id); err != nil {
		if errors.Is(err, repositories.ErrPptTemplateSystemDelete) {
			utils.Error(c, 400, "System default template cannot be deleted")
			return
		}
		utils.ServerError(c, err)
		return
	}

	utils.SuccessWithMsg(c, "PPT template deleted", nil)
}
