package handlers

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"

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

	"github.com/gin-gonic/gin"
	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

const yuhengCloudRegisterColl = "yuheng_cloud_register_records"

func cloudRegisterURL() string {
	u := strings.TrimSpace(os.Getenv("YH_CLOUD_REGISTER_URL"))
	if u != "" {
		return strings.TrimSuffix(u, "/")
	}
	return "http://www.cloud.yuxindazhineng.com:3001/register"
}

// YuhengCloudRegisterInput 与云端 POST /register 一致；email 仅用于调用云端，不写入 Mongo
type YuhengCloudRegisterInput struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
	Email    string `json:"email" binding:"required"`
}

type cloudRegisterPayload struct {
	Username string `json:"username"`
	Password string `json:"password"`
	Email    string `json:"email"`
}

func postCloudRegister(ctx context.Context, payload cloudRegisterPayload) (int, string, error) {
	body, err := json.Marshal(payload)
	if err != nil {
		return 0, "", err
	}
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, cloudRegisterURL(), bytes.NewReader(body))
	if err != nil {
		return 0, "", err
	}
	req.Header.Set("Content-Type", "application/json")
	client := &http.Client{Timeout: 45 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return 0, "", err
	}
	defer resp.Body.Close()
	b, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
	return resp.StatusCode, strings.TrimSpace(string(b)), nil
}

// CreateYuhengCloudRegister 调用云端注册接口，成功后在 Mongo 写入一条记录（仅 username、password）
func CreateYuhengCloudRegister(c *gin.Context) {
	var in YuhengCloudRegisterInput
	if err := c.ShouldBindJSON(&in); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请填写用户名、密码与邮箱（邮箱仅提交云端）"})
		return
	}
	in.Username = strings.TrimSpace(in.Username)
	in.Password = strings.TrimSpace(in.Password)
	in.Email = strings.TrimSpace(in.Email)
	if in.Username == "" || in.Password == "" || in.Email == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "用户名、密码、邮箱不能为空"})
		return
	}

	ctx, cancel := context.WithTimeout(c.Request.Context(), 50*time.Second)
	defer cancel()

	status, bodySnippet, err := postCloudRegister(ctx, cloudRegisterPayload{
		Username: in.Username,
		Password: in.Password,
		Email:    in.Email,
	})
	if err != nil {
		c.JSON(http.StatusBadGateway, gin.H{"error": "调用云端注册失败: " + err.Error()})
		return
	}
	if status < 200 || status >= 300 {
		msg := bodySnippet
		if len(msg) > 500 {
			msg = msg[:500] + "…"
		}
		if msg == "" {
			msg = http.StatusText(status)
		}
		c.JSON(http.StatusBadGateway, gin.H{"error": fmt.Sprintf("云端返回 %d: %s", status, msg)})
		return
	}

	db := config.GetDB(config.DBName)
	if db == nil {
		c.JSON(http.StatusServiceUnavailable, gin.H{"error": "数据库未连接，未写入本地记录"})
		return
	}
	insCtx, insCancel := context.WithTimeout(context.Background(), 8*time.Second)
	defer insCancel()
	doc := bson.M{
		"username":   in.Username,
		"password":   in.Password,
		"created_at": time.Now().UTC().Format(time.RFC3339),
	}
	res, err := db.Collection(yuhengCloudRegisterColl).InsertOne(insCtx, doc)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "云端已成功但本地记录失败: " + err.Error()})
		return
	}
	idHex := ""
	switch v := res.InsertedID.(type) {
	case bson.ObjectID:
		idHex = v.Hex()
	}
	c.JSON(http.StatusOK, gin.H{"id": idHex, "message": "已提交云端注册并写入本地记录"})
}

// ListYuhengCloudRegisterRecords 分页列出本地留痕（便于管理页展示）
func ListYuhengCloudRegisterRecords(c *gin.Context) {
	db := config.GetDB(config.DBName)
	if db == nil {
		c.JSON(http.StatusOK, gin.H{"list": []any{}, "total": 0})
		return
	}
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}
	skip := int64((page - 1) * pageSize)
	limit := int64(pageSize)

	ctx, cancel := context.WithTimeout(c.Request.Context(), 15*time.Second)
	defer cancel()
	coll := db.Collection(yuhengCloudRegisterColl)
	total, err := coll.CountDocuments(ctx, bson.M{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	opts := options.Find().SetSort(bson.D{{Key: "created_at", Value: -1}}).SetSkip(skip).SetLimit(limit)
	cur, err := coll.Find(ctx, bson.M{}, opts)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer cur.Close(ctx)
	var list []models.YuhengCloudRegisterRecord
	for cur.Next(ctx) {
		var row struct {
			ID        bson.ObjectID `bson:"_id"`
			Username  string        `bson:"username"`
			Password  string        `bson:"password"`
			CreatedAt string        `bson:"created_at"`
		}
		if err := cur.Decode(&row); err != nil {
			continue
		}
		list = append(list, models.YuhengCloudRegisterRecord{
			ID:        row.ID.Hex(),
			Username:  row.Username,
			Password:  row.Password,
			CreatedAt: row.CreatedAt,
		})
	}
	c.JSON(http.StatusOK, gin.H{"list": list, "total": total})
}
