package handlers

import (
	"context"
	"encoding/json"
	"net/http"
	"strings"
	"time"

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

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

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

const homepageSlug = "index"
const officialSiteConfigID = "official_site_id"

type officialSiteDoc struct {
	ID     string `bson:"_id"`
	SiteID string `bson:"site_id"`
}

// getOfficialSiteID 从 system_config 读取官网站点 ID；未设置则返回第一个站点的 ID
func getOfficialSiteID(ctx context.Context) string {
	coll := config.GetDB(config.DBName).Collection("system_config")
	var doc officialSiteDoc
	err := coll.FindOne(ctx, bson.M{"_id": officialSiteConfigID}).Decode(&doc)
	if err == nil && doc.SiteID != "" {
		return doc.SiteID
	}
	sitesColl := config.GetDB(config.DBName).Collection("sites")
	opts := options.FindOne().SetSort(bson.D{{Key: "created_at", Value: -1}})
	var site models.Site
	if err := sitesColl.FindOne(ctx, bson.M{}, opts).Decode(&site); err == nil {
		return site.ID.Hex()
	}
	return ""
}

// GetWebHomepage 前台：获取官网站点首页数据（无需鉴权）
func GetWebHomepage(c *gin.Context) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	siteID := getOfficialSiteID(ctx)
	if siteID == "" {
		c.JSON(http.StatusOK, defaultHomepageData())
		return
	}

	coll := config.GetDB(config.DBName).Collection("pages")
	var page models.Page
	err := coll.FindOne(ctx, bson.M{"site_id": siteID, "slug": homepageSlug}).Decode(&page)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			c.JSON(http.StatusOK, defaultHomepageData())
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	var data models.HomepageData
	if page.Content != "" {
		if err := json.Unmarshal([]byte(page.Content), &data); err != nil {
			c.JSON(http.StatusOK, defaultHomepageData())
			return
		}
	} else {
		data = defaultHomepageData()
	}
	c.JSON(http.StatusOK, data)
}

// GetHomepage 获取站点首页数据
func GetHomepage(c *gin.Context) {
	siteID := c.Param("site_id")
	if siteID == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请提供 site_id"})
		return
	}

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

	coll := config.GetDB(config.DBName).Collection("pages")
	var page models.Page
	err := coll.FindOne(ctx, bson.M{"site_id": siteID, "slug": homepageSlug}).Decode(&page)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			c.JSON(http.StatusOK, defaultHomepageData())
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	var data models.HomepageData
	if page.Content != "" {
		if err := json.Unmarshal([]byte(page.Content), &data); err != nil {
			c.JSON(http.StatusOK, defaultHomepageData())
			return
		}
	} else {
		data = defaultHomepageData()
	}
	c.JSON(http.StatusOK, data)
}

// UpdateHomepage 更新站点首页数据
func UpdateHomepage(c *gin.Context) {
	siteID := c.Param("site_id")
	if siteID == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请提供 site_id"})
		return
	}

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

	body, err := json.Marshal(data)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

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

	coll := config.GetDB(config.DBName).Collection("pages")
	now := time.Now().Format(time.RFC3339)
	filter := bson.M{"site_id": siteID, "slug": homepageSlug}
	update := bson.M{
		"$set": bson.M{
			"site_id":    siteID,
			"slug":       homepageSlug,
			"title":      data.Title,
			"type":       "homepage",
			"content":    string(body),
			"updated_at": now,
		},
	}
	opts := options.UpdateOne().SetUpsert(true)
	_, err = coll.UpdateOne(ctx, filter, update, opts)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "保存成功"})
}

// DownloadHomepage 下载首页 HTML
func DownloadHomepage(c *gin.Context) {
	siteID := c.Param("site_id")
	if siteID == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请提供 site_id"})
		return
	}

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

	coll := config.GetDB(config.DBName).Collection("pages")
	var page models.Page
	var data models.HomepageData
	err := coll.FindOne(ctx, bson.M{"site_id": siteID, "slug": homepageSlug}).Decode(&page)
	if err == nil && page.Content != "" {
		_ = json.Unmarshal([]byte(page.Content), &data)
	}
	if err != nil || page.Content == "" {
		data = defaultHomepageData()
	}

	html := renderHomepageHTML(&data)
	c.Header("Content-Disposition", "attachment; filename=index.html")
	c.Data(http.StatusOK, "text/html; charset=utf-8", []byte(html))
}

func defaultHomepageData() models.HomepageData {
	return models.HomepageData{
		LogoText:     "YUHENG ONE",
		NavLinks:     []models.NavLink{{Label: "MISSION", URL: "#"}, {Label: "DOWNLOAD", URL: "#"}, {Label: "CONTACT", URL: "#"}},
		Title:        "宇恒一号",
		Subtitle:     "INTERSTELLAR EXPLORER EDITION",
		Description:  "跨越星际的智能伙伴 · 探索无限可能<br>\n            引领您进入前所未有的数字宇宙",
		DownloadText: "START EXPLORING",
		DownloadURL:  "#",
		Platforms: []models.PlatformItem{
			{Name: "WINDOWS", URL: "#"},
			{Name: "MACOS", URL: "#"},
			{Name: "LINUX", URL: "#"},
			{Name: "IOS", URL: "#"},
			{Name: "ANDROID", URL: "#"},
		},
		Version:    "VERSION 3.2.1",
		LaunchYear: "LAUNCH: 2024",
		BadgeText:  "FREE ACCESS",
		Features: []models.FeatureItem{
			{Title: "星际导航", Desc: "先进的AI导航系统，精准定位您的需求，引领探索之旅"},
			{Title: "量子同步", Desc: "跨维度数据同步技术，您的数据在多宇宙中保持一致"},
			{Title: "星际防护", Desc: "来自未来的安全加密协议，守护您的数字资产安全"},
		},
		FooterText: "© 2024 YUHENG ONE // STELLAR EXPLORATION INITIATIVE",
	}
}

// renderHomepageHTML 根据数据生成首页 HTML（简化版，保留原样式与结构）
func renderHomepageHTML(d *models.HomepageData) string {
	if d == nil {
		d = &models.HomepageData{}
	}
	titleChars := splitTitle(d.Title)
	navHTML := ""
	for _, l := range d.NavLinks {
		navHTML += `<a href="` + escape(l.URL) + `" style="color: rgba(255,255,255,0.5); text-decoration: none; transition: color 0.3s;">` + escape(l.Label) + `</a>`
	}
	platformsHTML := ""
	for _, p := range d.Platforms {
		platformsHTML += `<div class="orbit-platform"><svg viewBox="0 0 24 24"><path d="M20 18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z"/></svg><span>` + escape(p.Name) + `</span></div>`
	}
	featuresHTML := ""
	for i, f := range d.Features {
		iconPath := []string{
			"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z",
			"M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM19 18H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h.71C7.37 7.69 9.48 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3s-1.34 3-3 3z",
			"M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z",
		}
		if i >= len(iconPath) {
			iconPath = append(iconPath, iconPath[0])
		}
		path := iconPath[i%3]
		featuresHTML += `<div class="feature-space"><div class="feature-icon"><svg viewBox="0 0 24 24"><path d="` + path + `"/></svg></div><h3>` + escape(f.Title) + `</h3><p>` + escape(f.Desc) + `</p></div>`
	}

	sb := &strings.Builder{}
	sb.WriteString("<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>")
	sb.WriteString(escape(d.Title))
	sb.WriteString(" - 星际探索版</title>\n")
	sb.WriteString(homepageCSS)
	sb.WriteString("</head>\n<body>\n<div class=\"space-bg\"></div>\n<div class=\"stars\" id=\"stars\"></div>\n<div class=\"planet planet-1\"></div>\n<div class=\"planet planet-2\"></div>\n<nav class=\"navbar\"><div class=\"logo-space\">")
	sb.WriteString(escape(d.LogoText))
	sb.WriteString("</div>\n<div style=\"display: flex; gap: 35px; font-family: 'Exo 2', sans-serif; font-size: 12px; letter-spacing: 2px;\">")
	sb.WriteString(navHTML)
	sb.WriteString("</div>\n</nav>\n<section class=\"hero\">\n<div class=\"title-container\"><h1 class=\"title-3d\">")
	for _, ch := range titleChars {
		sb.WriteString("<span>" + escape(ch) + "</span>")
	}
	sb.WriteString("</h1>\n</div>\n<p class=\"subtitle-space\">")
	sb.WriteString(escape(d.Subtitle))
	sb.WriteString("</p>\n<p class=\"description-space\">")
	sb.WriteString(strings.ReplaceAll(escape(d.Description), "\n", "<br>\n"))
	sb.WriteString("</p>\n<div class=\"download-warp\">\n<div class=\"warp-effect\"></div>\n<a href=\"")
	sb.WriteString(escape(d.DownloadURL))
	sb.WriteString("\" class=\"warp-btn\">\n<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\"/></svg>\n")
	sb.WriteString(escape(d.DownloadText))
	sb.WriteString("\n</a>\n</div>\n<div class=\"orbit-platforms\">")
	sb.WriteString(platformsHTML)
	sb.WriteString("</div>\n<div class=\"mission-info\">\n<span class=\"mission-badge\">")
	sb.WriteString(escape(d.Version))
	sb.WriteString("</span>\n<span>🚀 ")
	sb.WriteString(escape(d.LaunchYear))
	sb.WriteString("</span>\n<span>⚡ ")
	sb.WriteString(escape(d.BadgeText))
	sb.WriteString("</span>\n</div>\n<div class=\"features-space\">")
	sb.WriteString(featuresHTML)
	sb.WriteString("</div>\n</section>\n<footer>\n<p>")
	sb.WriteString(escape(d.FooterText))
	sb.WriteString("</p>\n</footer>\n<script>\nconst starsContainer = document.getElementById('stars');\nfor (let i = 0; i < 200; i++) {\nconst star = document.createElement('div');\nstar.className = 'star';\nstar.style.left = Math.random() * 100 + '%';\nstar.style.top = Math.random() * 100 + '%';\nstar.style.width = (Math.random() * 2 + 1) + 'px';\nstar.style.height = star.style.width;\nstar.style.setProperty('--duration', (Math.random() * 3 + 2) + 's');\nstar.style.setProperty('--min-opacity', Math.random() * 0.3 + 0.1);\nstarsContainer.appendChild(star);\n}\n</script>\n</body>\n</html>")
	return sb.String()
}

func splitTitle(s string) []string {
	var out []rune
	for _, r := range s {
		out = append(out, r)
	}
	if len(out) == 0 {
		return []string{"宇", "恒", "一", "号"}
	}
	result := make([]string, len(out))
	for i, r := range out {
		result[i] = string(r)
	}
	return result
}

func escape(s string) string {
	s = strings.ReplaceAll(s, "&", "&amp;")
	s = strings.ReplaceAll(s, "<", "&lt;")
	s = strings.ReplaceAll(s, ">", "&gt;")
	s = strings.ReplaceAll(s, "\"", "&quot;")
	return s
}

const homepageCSS = `<style>
@import url('https://fonts.googleapis.com/css2?family=Exo+2:wght@300;400;700;900&family=Noto+Sans+SC:wght@300;400;700&display=swap');
*{margin:0;padding:0;box-sizing:border-box;}
:root{--space-dark:#0a0a12;--space-blue:#1e3a5f;--nebula-purple:#4a1a6b;--star-white:#fff;--plasma-cyan:#00d4ff;--plasma-pink:#ff2d95;}
body{font-family:'Noto Sans SC',sans-serif;background:var(--space-dark);color:var(--star-white);min-height:100vh;overflow-x:hidden;}
.space-bg{position:fixed;top:0;left:0;width:100%;height:100%;z-index:0;background:radial-gradient(ellipse at 20% 80%,rgba(74,26,107,0.3) 0%,transparent 50%),radial-gradient(ellipse at 80% 20%,rgba(30,58,95,0.3) 0%,transparent 50%);}
.stars{position:fixed;top:0;left:0;width:100%;height:100%;z-index:1;pointer-events:none;}
.star{position:absolute;background:#fff;border-radius:50%;animation:twinkle 3s ease-in-out infinite;}
@keyframes twinkle{0%,100%{opacity:0.3;transform:scale(1);}50%{opacity:1;transform:scale(1.2);}}
.planet{position:fixed;border-radius:50%;z-index:2;pointer-events:none;}
.planet-1{width:300px;height:300px;top:10%;right:-100px;background:linear-gradient(135deg,var(--nebula-purple),#1a0a2e);opacity:0.6;}
.planet-2{width:150px;height:150px;bottom:20%;left:-50px;background:linear-gradient(135deg,var(--space-blue),#0a1520);opacity:0.5;}
.navbar{position:fixed;top:0;left:0;right:0;padding:25px 50px;display:flex;justify-content:space-between;align-items:center;z-index:100;background:linear-gradient(180deg,rgba(10,10,18,0.9) 0%,transparent 100%);}
.logo-space{font-family:'Exo 2',sans-serif;font-size:26px;font-weight:900;background:linear-gradient(90deg,var(--plasma-cyan),var(--star-white),var(--plasma-pink));-webkit-background-clip:text;-webkit-text-fill-color:transparent;letter-spacing:4px;}
.hero{min-height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:100px 20px;position:relative;z-index:10;}
.title-container{perspective:1000px;margin-bottom:30px;}
.title-3d{font-family:'Exo 2',sans-serif;font-size:clamp(60px,12vw,150px);font-weight:900;color:var(--star-white);text-shadow:0 0 20px rgba(0,212,255,0.3);}
.subtitle-space{font-family:'Exo 2',sans-serif;font-size:clamp(16px,3vw,24px);letter-spacing:12px;color:var(--plasma-cyan);margin-bottom:25px;}
.description-space{max-width:650px;text-align:center;color:rgba(255,255,255,0.6);line-height:2;font-size:16px;margin-bottom:50px;}
.download-warp{position:relative;display:inline-block;padding:0;background:transparent;border:none;cursor:pointer;}
.download-warp .warp-btn{display:flex;align-items:center;gap:15px;padding:22px 45px;font-size:16px;font-weight:700;color:var(--space-dark);background:linear-gradient(135deg,var(--plasma-cyan),var(--plasma-pink));border:none;font-family:'Exo 2',sans-serif;letter-spacing:2px;text-decoration:none;clip-path:polygon(20px 0,100% 0,100% calc(100% - 20px),calc(100% - 20px) 100%,0 100%,0 20px);transition:all 0.4s;}
.download-warp .warp-btn:hover{transform:scale(1.05);box-shadow:0 0 30px rgba(0,212,255,0.6);}
.warp-effect{position:absolute;top:50%;left:50%;width:0;height:0;background:radial-gradient(circle,rgba(255,255,255,0.8) 0%,transparent 70%);border-radius:50%;transform:translate(-50%,-50%);animation:warp-drive 1.5s ease-out infinite;}
@keyframes warp-drive{0%{width:0;height:0;opacity:1;}100%{width:300px;height:300px;opacity:0;}}
.orbit-platforms{display:flex;gap:25px;margin-top:70px;flex-wrap:wrap;justify-content:center;}
.orbit-platform{width:90px;height:90px;background:rgba(30,58,95,0.3);border:1px solid rgba(0,212,255,0.3);border-radius:50%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;cursor:pointer;transition:all 0.4s;}
.orbit-platform:hover{background:rgba(0,212,255,0.2);border-color:var(--plasma-cyan);transform:translateY(-10px);}
.orbit-platform svg{width:28px;height:28px;fill:var(--star-white);}
.orbit-platform span{font-size:10px;color:rgba(255,255,255,0.6);}
.mission-info{margin-top:60px;display:flex;gap:40px;flex-wrap:wrap;justify-content:center;font-size:13px;color:rgba(255,255,255,0.4);}
.mission-info .mission-badge{padding:4px 12px;background:rgba(0,212,255,0.1);border:1px solid rgba(0,212,255,0.3);border-radius:20px;color:var(--plasma-cyan);font-size:11px;}
.features-space{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:30px;max-width:1100px;margin:80px auto 0;padding:0 20px;}
.feature-space{background:linear-gradient(135deg,rgba(30,58,95,0.2),rgba(10,10,18,0.8));border:1px solid rgba(0,212,255,0.1);border-radius:20px;padding:35px;transition:all 0.5s;}
.feature-space:hover{transform:translateY(-15px);border-color:rgba(0,212,255,0.4);}
.feature-icon{width:55px;height:55px;background:linear-gradient(135deg,var(--plasma-cyan),var(--plasma-pink));border-radius:15px;display:flex;align-items:center;justify-content:center;margin-bottom:20px;}
.feature-icon svg{width:28px;height:28px;fill:var(--space-dark);}
.feature-space h3{font-family:'Exo 2',sans-serif;font-size:18px;color:var(--star-white);margin-bottom:12px;}
.feature-space p{color:rgba(255,255,255,0.5);font-size:14px;line-height:1.7;}
footer{padding:40px;text-align:center;border-top:1px solid rgba(255,255,255,0.05);margin-top:80px;}
footer p{color:rgba(255,255,255,0.3);font-size:12px;}
@media(max-width:768px){.planet{display:none;}}
</style>
`