package handlers

import (
	"context"
	"net/http"
	"time"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo/options"

	"yh_web/server/config"
	"yh_web/server/models"

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

// GetSites 站点列表
func GetSites(c *gin.Context) {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	coll := config.GetDB(config.DBName).Collection("sites")
	opts := options.Find().SetSort(bson.D{{Key: "created_at", Value: -1}})
	cursor, err := coll.Find(ctx, bson.M{}, opts)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer cursor.Close(ctx)

	var list []models.Site
	if err = cursor.All(ctx, &list); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	total, _ := coll.CountDocuments(ctx, bson.M{})

	c.JSON(http.StatusOK, gin.H{"list": list, "total": total})
}

// GetSiteByID 单个站点
func GetSiteByID(c *gin.Context) {
	idStr := c.Param("site_id")
	oid, err := bson.ObjectIDFromHex(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的站点ID"})
		return
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	var site models.Site
	err = config.GetDB(config.DBName).Collection("sites").FindOne(ctx, bson.M{"_id": oid}).Decode(&site)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "站点不存在"})
		return
	}
	c.JSON(http.StatusOK, site)
}

// CreateSiteInput 创建站点
type CreateSiteInput struct {
	Name        string `json:"name" binding:"required"`
	Domain      string `json:"domain"`
	Description string `json:"description"`
}

// CreateSite 创建站点
func CreateSite(c *gin.Context) {
	var input CreateSiteInput
	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请填写站点名称"})
		return
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	coll := config.GetDB(config.DBName).Collection("sites")
	doc := bson.M{
		"name":        input.Name,
		"domain":      input.Domain,
		"description": input.Description,
		"created_at":  time.Now().Format(time.RFC3339),
	}
	res, err := coll.InsertOne(ctx, doc)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"id": res.InsertedID, "message": "创建成功"})
}

// UpdateSiteInput 更新站点
type UpdateSiteInput struct {
	Name        *string `json:"name"`
	Domain      *string `json:"domain"`
	Description *string `json:"description"`
}

// UpdateSite 更新站点
func UpdateSite(c *gin.Context) {
	idStr := c.Param("site_id")
	oid, err := bson.ObjectIDFromHex(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的站点ID"})
		return
	}

	var input UpdateSiteInput
	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	set := bson.M{}
	if input.Name != nil {
		set["name"] = *input.Name
	}
	if input.Domain != nil {
		set["domain"] = *input.Domain
	}
	if input.Description != nil {
		set["description"] = *input.Description
	}
	if len(set) == 0 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "无有效更新字段"})
		return
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	_, err = config.GetDB(config.DBName).Collection("sites").UpdateOne(ctx, bson.M{"_id": oid}, bson.M{"$set": set})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "更新成功"})
}

// DeleteSite 删除站点
func DeleteSite(c *gin.Context) {
	idStr := c.Param("site_id")
	oid, err := bson.ObjectIDFromHex(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的站点ID"})
		return
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	db := config.GetDB(config.DBName)
	_, err = db.Collection("sites").DeleteOne(ctx, bson.M{"_id": oid})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	db.Collection("pages").DeleteMany(ctx, bson.M{"site_id": idStr})
	db.Collection("site_assets").DeleteMany(ctx, bson.M{"site_id": idStr})

	c.JSON(http.StatusOK, gin.H{"message": "删除成功"})
}
