package repositories

import (
	"encoding/json"
	"errors"
	"log"
	"time"

	"github.com/niangaodev/art-code/config"
	"github.com/niangaodev/art-code/models"
)

const DefaultPptTemplateSlug = "default"

const DefaultPptTemplateConfigJSON = `{"colors":{"bg":"#141414","text":"#f5f5f5","muted":"#a0a0a0","accent":"#c9a962","codeBg":"#1e1e1e","codeText":"#eeeeee","border":"rgba(255, 255, 255, 0.1)"},"animation":{"revealDuration":"0.95s","revealLeaveDuration":"0.65s","slideDuration":"0.85s","layoutDuration":"0.75s","revealOffset":"10px","easing":"cubic-bezier(0.22, 1, 0.36, 1)"},"transitions":{"slide":"crossfade","reveal":"fadeUp"},"ui":{"showThumbnailsDefault":true,"canvasBorderRadius":"0.5rem"}}`

var ErrPptTemplateSystemDelete = errors.New("system ppt template cannot be deleted")

func GetActivePptTemplates() ([]models.PptTemplate, error) {
	var list []models.PptTemplate
	err := config.DB.Model(&models.PptTemplate{}).
		Where("deleted_at = ? AND is_active = ?", 0, true).
		Order("sort_order ASC, id ASC").
		Find(&list).Error
	return list, err
}

func GetAllPptTemplates() ([]models.PptTemplate, error) {
	var list []models.PptTemplate
	err := config.DB.Model(&models.PptTemplate{}).
		Where("deleted_at = ?", 0).
		Order("sort_order ASC, id ASC").
		Find(&list).Error
	return list, err
}

func GetPptTemplateByID(id uint) (*models.PptTemplate, error) {
	var t models.PptTemplate
	err := config.DB.Model(&models.PptTemplate{}).
		Where("id = ? AND deleted_at = ?", id, 0).
		First(&t).Error
	if err != nil {
		return nil, err
	}
	return &t, nil
}

func GetSystemPptTemplate() (*models.PptTemplate, error) {
	var t models.PptTemplate
	err := config.DB.Model(&models.PptTemplate{}).
		Where("slug = ? AND deleted_at = ?", DefaultPptTemplateSlug, 0).
		First(&t).Error
	if err != nil {
		return nil, err
	}
	return &t, nil
}

func CreatePptTemplate(t *models.PptTemplate) error {
	return config.DB.Create(t).Error
}

func UpdatePptTemplate(t *models.PptTemplate) error {
	return config.DB.Model(&models.PptTemplate{}).
		Where("id = ? AND deleted_at = ?", t.ID, 0).
		Updates(map[string]interface{}{
			"name":        t.Name,
			"slug":        t.Slug,
			"description": t.Description,
			"config":      t.Config,
			"is_default":  t.IsDefault,
			"sort_order":  t.SortOrder,
			"is_active":   t.IsActive,
			"updated_at":  time.Now().Unix(),
		}).Error
}

func DeletePptTemplate(id uint) error {
	t, err := GetPptTemplateByID(id)
	if err != nil {
		return err
	}
	if t.IsSystem {
		return ErrPptTemplateSystemDelete
	}
	return config.DB.Model(&models.PptTemplate{}).
		Where("id = ?", id).
		Update("deleted_at", time.Now().Unix()).Error
}

func ClearDefaultPptTemplatesExcept(id uint) error {
	q := config.DB.Model(&models.PptTemplate{}).
		Where("deleted_at = ? AND is_default = ?", 0, true)
	if id > 0 {
		q = q.Where("id <> ?", id)
	}
	return q.Update("is_default", false).Error
}

func EnsureSystemPptTemplate() {
	if !tableExists("ppt_templates") {
		return
	}
	var count int64
	config.DB.Model(&models.PptTemplate{}).
		Where("slug = ? AND deleted_at = ?", DefaultPptTemplateSlug, 0).
		Count(&count)
	if count > 0 {
		return
	}

	now := time.Now().Unix()
	t := models.PptTemplate{
		Name:        "默认模板",
		Slug:        DefaultPptTemplateSlug,
		Description: "系统内置 PPT 演示默认样式",
		Config:      DefaultPptTemplateConfigJSON,
		IsSystem:    true,
		IsDefault:   true,
		SortOrder:   0,
		IsActive:    true,
		CreatedAt:   now,
		UpdatedAt:   now,
	}
	if err := config.DB.Create(&t).Error; err != nil {
		log.Printf("Failed to seed system ppt template: %v", err)
	}
}

func ParsePptTemplateConfigJSON(raw string) (map[string]interface{}, error) {
	var cfg map[string]interface{}
	if raw == "" {
		raw = DefaultPptTemplateConfigJSON
	}
	if err := json.Unmarshal([]byte(raw), &cfg); err != nil {
		return nil, err
	}
	return cfg, nil
}

func SerializePptTemplateConfig(cfg interface{}) (string, error) {
	if cfg == nil {
		return DefaultPptTemplateConfigJSON, nil
	}
	b, err := json.Marshal(cfg)
	if err != nil {
		return "", err
	}
	return string(b), nil
}

func ToPptTemplatePayload(t *models.PptTemplate) (models.PptTemplatePayload, error) {
	cfg, err := ParsePptTemplateConfigJSON(t.Config)
	if err != nil {
		return models.PptTemplatePayload{}, err
	}
	return models.PptTemplatePayload{
		ID:          t.ID,
		Name:        t.Name,
		Slug:        t.Slug,
		Description: t.Description,
		Config:      cfg,
		IsSystem:    t.IsSystem,
		IsDefault:   t.IsDefault,
		SortOrder:   t.SortOrder,
		IsActive:    t.IsActive,
		CreatedAt:   t.CreatedAt,
		UpdatedAt:   t.UpdatedAt,
	}, nil
}
