package handlers

import (
	"context"
	"net/http"
	"strings"
	"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"
)

// effectivePagePath 对外访问路径：优先 route_path，否则 /{slug}；index 且无 route_path 时返回空（由首页单独处理）
func effectivePagePath(p models.Page) string {
	if p.RoutePath != "" {
		path := strings.TrimSpace(p.RoutePath)
		if !strings.HasPrefix(path, "/") {
			path = "/" + path
		}
		return path
	}
	if p.Slug == "" || p.Slug == homepageSlug {
		return ""
	}
	return "/" + p.Slug
}

// GetWebRoutes 前台：获取站点已发布页面的动态路由列表（无需鉴权）
func GetWebRoutes(c *gin.Context) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if config.MongoClient == nil {
		c.JSON(http.StatusOK, gin.H{"site_id": "", "routes": []any{}})
		return
	}

	siteID := c.Query("site_id")
	if siteID == "" {
		siteID = getOfficialSiteID(ctx)
	}
	if siteID == "" {
		c.JSON(http.StatusOK, gin.H{"site_id": "", "routes": []any{}})
		return
	}

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

	var pages []models.Page
	if err = cursor.All(ctx, &pages); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	routes := make([]gin.H, 0)
	for _, p := range pages {
		if p.Published != nil && !*p.Published {
			continue
		}
		path := effectivePagePath(p)
		if path == "" {
			continue
		}
		routes = append(routes, gin.H{
			"path":   path,
			"title":  p.Title,
			"slug":   p.Slug,
			"id":     p.ID.Hex(),
			"mode":   p.ContentMode,
		})
	}
	c.JSON(http.StatusOK, gin.H{"site_id": siteID, "routes": routes})
}

// GetWebPageByPath 前台：按路径取单页内容（无需鉴权）
func GetWebPageByPath(c *gin.Context) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if config.MongoClient == nil {
		c.JSON(http.StatusServiceUnavailable, gin.H{"error": "服务暂不可用"})
		return
	}

	siteID := c.Query("site_id")
	if siteID == "" {
		siteID = getOfficialSiteID(ctx)
	}
	path := strings.TrimSpace(c.Query("path"))
	if siteID == "" || path == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "缺少 site_id 或 path"})
		return
	}
	if !strings.HasPrefix(path, "/") {
		path = "/" + path
	}

	coll := config.GetDB(config.DBName).Collection("pages")

	var page models.Page
	tryDecode := func(filter bson.M) bool {
		page = models.Page{}
		err := coll.FindOne(ctx, filter).Decode(&page)
		return err == nil && !page.ID.IsZero()
	}
	if !tryDecode(bson.M{"site_id": siteID, "route_path": path}) {
		alt := strings.TrimPrefix(path, "/")
		if alt != "" {
			tryDecode(bson.M{"site_id": siteID, "route_path": alt})
		}
	}
	if page.ID.IsZero() {
		slug := strings.TrimPrefix(path, "/")
		if slug != "" {
			tryDecode(bson.M{"site_id": siteID, "slug": slug})
		}
	}
	if page.ID.IsZero() {
		c.JSON(http.StatusNotFound, gin.H{"error": "页面不存在"})
		return
	}
	if page.Published != nil && !*page.Published {
		c.JSON(http.StatusNotFound, gin.H{"error": "页面未发布"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"id":           page.ID.Hex(),
		"site_id":      page.SiteID,
		"slug":         page.Slug,
		"title":        page.Title,
		"type":         page.Type,
		"content":      page.Content,
		"content_mode": page.ContentMode,
		"route_path":   page.RoutePath,
		"updated_at":   page.UpdatedAt,
	})
}
