package handler

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

	"cyberstrike-ai/internal/config"
	"cyberstrike-ai/internal/robot/ilink"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"go.uber.org/zap"
)

const wechatLoginTTL = 5 * time.Minute

// WechatConfigSaver 绑定成功后写入配置并重启机器人连接
type WechatConfigSaver interface {
	ApplyWechatRobotBinding(cfg config.RobotWechatConfig) error
}

type wechatLoginSession struct {
	QRCode           string
	QRCodeImgURL     string
	PendingVerify    string
	CurrentBaseURL   string
	StartedAt        time.Time
}

// WechatRobotHandler 微信 iLink 机器人（扫码绑定 + 配置）
type WechatRobotHandler struct {
	config       *config.Config
	configSaver  WechatConfigSaver
	logger       *zap.Logger
	mu           sync.Mutex
	logins       map[string]*wechatLoginSession
}

// NewWechatRobotHandler 创建微信机器人处理器
func NewWechatRobotHandler(cfg *config.Config, saver WechatConfigSaver, logger *zap.Logger) *WechatRobotHandler {
	return &WechatRobotHandler{
		config:      cfg,
		configSaver: saver,
		logger:      logger,
		logins:      make(map[string]*wechatLoginSession),
	}
}

func (h *WechatRobotHandler) purgeExpiredLogins() {
	now := time.Now()
	for k, v := range h.logins {
		if now.Sub(v.StartedAt) > wechatLoginTTL {
			delete(h.logins, k)
		}
	}
}

func (h *WechatRobotHandler) ilinkClient(baseURL string) *ilink.Client {
	ver := h.config.Version
	if ver == "" {
		ver = "1.0.0"
	}
	ver = strings.TrimPrefix(strings.TrimSpace(ver), "v")
	ver = strings.TrimPrefix(ver, "V")
	wc := h.config.Robots.Wechat
	return ilink.NewClient(baseURL, wc.BotToken, wc.BotAgent, ilink.BuildClientVersion(ver))
}

// HandleWechatQRCode POST /api/robot/wechat/qrcode — 生成绑定二维码
func (h *WechatRobotHandler) HandleWechatQRCode(c *gin.Context) {
	h.mu.Lock()
	h.purgeExpiredLogins()
	h.mu.Unlock()

	var req struct {
		BotType string `json:"bot_type"`
	}
	_ = c.ShouldBindJSON(&req)

	botType := req.BotType
	if botType == "" {
		botType = h.config.Robots.Wechat.BotType
	}
	if botType == "" {
		botType = ilink.DefaultBotType
	}
	baseURL := h.config.Robots.Wechat.BaseURL
	if baseURL == "" {
		baseURL = ilink.DefaultBaseURL
	}

	var localTokens []string
	if t := h.config.Robots.Wechat.BotToken; t != "" {
		localTokens = []string{t}
	}

	client := h.ilinkClient(baseURL)
	ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
	defer cancel()

	qr, err := client.GetBotQRCode(ctx, botType, localTokens)
	if err != nil {
		h.logger.Warn("获取微信二维码失败", zap.Error(err))
		c.JSON(http.StatusBadGateway, gin.H{"error": "获取二维码失败: " + err.Error()})
		return
	}
	if qr.QRCode == "" || qr.QRCodeImgContent == "" {
		c.JSON(http.StatusBadGateway, gin.H{"error": "微信服务器未返回有效二维码"})
		return
	}

	sessionKey := uuid.New().String()
	h.mu.Lock()
	h.logins[sessionKey] = &wechatLoginSession{
		QRCode:         qr.QRCode,
		QRCodeImgURL:   qr.QRCodeImgContent,
		CurrentBaseURL: baseURL,
		StartedAt:      time.Now(),
	}
	h.mu.Unlock()

	resp := gin.H{
		"session_key":     sessionKey,
		"qrcode":          qr.QRCode,
		"qrcode_open_url": qr.QRCodeImgContent,
		"message":         "请使用微信扫描二维码并确认绑定",
	}
	if dataURL, err := ilink.QRCodeDataURL(qr.QRCodeImgContent, 256); err != nil {
		h.logger.Warn("生成二维码图片失败", zap.Error(err))
	} else {
		resp["qrcode_image_data_url"] = dataURL
	}

	c.JSON(http.StatusOK, resp)
}

// HandleWechatQRCodeStatus GET /api/robot/wechat/qrcode/status — 轮询扫码状态
func (h *WechatRobotHandler) HandleWechatQRCodeStatus(c *gin.Context) {
	sessionKey := c.Query("session_key")
	verifyCode := c.Query("verify_code")
	if sessionKey == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "缺少 session_key"})
		return
	}

	h.mu.Lock()
	sess, ok := h.logins[sessionKey]
	h.mu.Unlock()
	if !ok {
		c.JSON(http.StatusNotFound, gin.H{"error": "登录会话不存在或已过期，请重新生成二维码"})
		return
	}
	if time.Since(sess.StartedAt) > wechatLoginTTL {
		h.mu.Lock()
		delete(h.logins, sessionKey)
		h.mu.Unlock()
		c.JSON(http.StatusGone, gin.H{"error": "二维码已过期，请重新生成"})
		return
	}

	baseURL := sess.CurrentBaseURL
	if baseURL == "" {
		baseURL = ilink.DefaultBaseURL
	}
	vc := verifyCode
	if vc == "" {
		vc = sess.PendingVerify
	}

	client := h.ilinkClient(baseURL)
	ctx, cancel := context.WithTimeout(c.Request.Context(), 40*time.Second)
	defer cancel()

	st, err := client.GetQRCodeStatus(ctx, sess.QRCode, vc)
	if err != nil {
		h.logger.Warn("轮询微信二维码状态失败", zap.Error(err))
		c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
		return
	}

	switch st.Status {
	case "wait", "scaned":
		c.JSON(http.StatusOK, gin.H{"status": st.Status})
		return
	case "need_verifycode":
		c.JSON(http.StatusOK, gin.H{
			"status":  st.Status,
			"message": "请在手机微信查看配对数字，并在下方输入",
		})
		return
	case "scaned_but_redirect":
		if st.RedirectHost != "" {
			h.mu.Lock()
			if s, ok := h.logins[sessionKey]; ok {
				s.CurrentBaseURL = "https://" + st.RedirectHost
			}
			h.mu.Unlock()
		}
		c.JSON(http.StatusOK, gin.H{"status": st.Status})
		return
	case "binded_redirect":
		h.mu.Lock()
		delete(h.logins, sessionKey)
		h.mu.Unlock()
		c.JSON(http.StatusOK, gin.H{
			"status":            st.Status,
			"already_connected": true,
			"message":           "该微信已绑定过，无需重复绑定",
		})
		return
	case "confirmed":
		if st.BotToken == "" || st.ILinkBotID == "" {
			c.JSON(http.StatusBadGateway, gin.H{"error": "绑定确认成功但缺少 bot_token"})
			return
		}
		saveBase := st.BaseURL
		if saveBase == "" {
			saveBase = baseURL
		}
		wc := h.config.Robots.Wechat
		wc.Enabled = true
		wc.BotToken = st.BotToken
		wc.ILinkBotID = st.ILinkBotID
		wc.ILinkUserID = st.ILinkUserID
		wc.BaseURL = saveBase
		if wc.BotType == "" {
			wc.BotType = ilink.DefaultBotType
		}
		if wc.BotAgent == "" {
			wc.BotAgent = ilink.DefaultBotAgent
		}
		if h.configSaver != nil {
			if err := h.configSaver.ApplyWechatRobotBinding(wc); err != nil {
				h.logger.Warn("保存微信机器人配置失败", zap.Error(err))
				c.JSON(http.StatusInternalServerError, gin.H{"error": "保存配置失败: " + err.Error()})
				return
			}
		} else {
			h.config.Robots.Wechat = wc
		}
		h.mu.Lock()
		delete(h.logins, sessionKey)
		h.mu.Unlock()
		c.JSON(http.StatusOK, gin.H{
			"status":        "confirmed",
			"message":       "绑定成功，微信机器人已启用",
			"ilink_bot_id":  st.ILinkBotID,
			"ilink_user_id": st.ILinkUserID,
		})
		return
	default:
		c.JSON(http.StatusOK, gin.H{"status": st.Status})
	}
}

// HandleWechatVerifyCode POST /api/robot/wechat/qrcode/verify — 提交手机配对数字
func (h *WechatRobotHandler) HandleWechatVerifyCode(c *gin.Context) {
	var req struct {
		SessionKey string `json:"session_key"`
		VerifyCode string `json:"verify_code"`
	}
	if err := c.ShouldBindJSON(&req); err != nil || req.SessionKey == "" || req.VerifyCode == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "需要 session_key 与 verify_code"})
		return
	}
	h.mu.Lock()
	sess, ok := h.logins[req.SessionKey]
	if ok {
		sess.PendingVerify = req.VerifyCode
	}
	h.mu.Unlock()
	if !ok {
		c.JSON(http.StatusNotFound, gin.H{"error": "登录会话不存在或已过期"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "已提交配对码，请继续等待绑定"})
}

// HandleWechatStatus GET /api/robot/wechat/status — 当前绑定状态（供前端展示）
func (h *WechatRobotHandler) HandleWechatStatus(c *gin.Context) {
	wc := h.config.Robots.Wechat
	bound := wc.BotToken != "" && wc.ILinkBotID != ""
	c.JSON(http.StatusOK, gin.H{
		"enabled":       wc.Enabled,
		"bound":         bound,
		"ilink_bot_id":  wc.ILinkBotID,
		"ilink_user_id": wc.ILinkUserID,
		"base_url":      wc.BaseURL,
	})
}
