package handler

import (
	"context"
	"errors"
	"gitee.ltd/lxh/xybot"
	"github.com/gofiber/fiber/v2/log"
	"strconv"
	"strings"
	"time"

	"github.com/gofiber/fiber/v2"
	"gorm.io/gorm"

	"gitee.ltd/lxh/wechat-robot/internal/config"
	"gitee.ltd/lxh/wechat-robot/internal/docker"
	"gitee.ltd/lxh/wechat-robot/internal/model"
)

// ListRobots 列出所有机器人
func ListRobots(c *fiber.Ctx) error {
	db := model.GetDB()
	var robots []model.Robot

	if err := db.Find(&robots).Error; err != nil {
		return fiber.NewError(fiber.StatusInternalServerError, "获取机器人列表失败")
	}

	total := len(robots)
	online := 0
	offline := 0
	for _, robot := range robots {
		if robot.Status == model.RobotStatusOnline {
			online++
		} else {
			offline++
		}
	}

	return c.Render("robot/index", fiber.Map{
		"Title":  "机器人列表",
		"Robots": robots,
		"Status": map[string]int{
			"Total":   total,
			"Online":  online,
			"Offline": offline,
		},
	})
}

// NewRobotForm 显示创建机器人表单
func NewRobotForm(c *fiber.Ctx) error {
	return c.Render("robot/new", fiber.Map{
		"Title": "新建机器人",
	})
}

// CreateRobot 创建新机器人
func CreateRobot(c *fiber.Ctx) error {
	robotName := c.FormValue("name")
	if robotName == "" {
		return fiber.NewError(fiber.StatusBadRequest, "机器人名称不能为空")
	}

	// 获取可选的端口映射配置
	port := 0
	portStr := c.FormValue("port")
	if portStr != "" {
		var err error
		port, err = strconv.Atoi(portStr)
		if err != nil || port <= 0 || port > 65535 {
			return fiber.NewError(fiber.StatusBadRequest, "端口必须是1-65535之间的有效数字")
		}
	}

	// 加载配置
	cfg, err := config.Load()
	if err != nil {
		return fiber.NewError(fiber.StatusInternalServerError, "加载配置失败")
	}

	// 创建Docker容器
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	containerID, containerHost, err := docker.CreateRobotContainer(ctx, &cfg.Docker, robotName, port)
	if err != nil {
		return fiber.NewError(fiber.StatusInternalServerError, "创建容器失败: "+err.Error())
	}

	// 创建机器人数据库记录
	robot := model.Robot{
		ContainerID:   containerID,
		ContainerHost: containerHost, // 使用新的字段名
		Nickname:      robotName,
		Status:        model.RobotStatusOffline,
	}
	// 处理一下设备 Id 和设备名称，防止后面出现空值
	robot.CheckDevice()

	db := model.GetDB()
	if err = db.Create(&robot).Error; err != nil {
		// 如果数据库创建失败，尝试删除容器
		_ = docker.RemoveContainer(ctx, containerID, true)
		return fiber.NewError(fiber.StatusInternalServerError, "保存机器人信息失败: "+err.Error())
	}

	// 添加到监控器
	// 注意：这里假设有一个全局可访问的监控器实例，实际中可能需要通过依赖注入或其他方式获取
	monitor := docker.NewContainerMonitor(db, time.Minute)
	monitor.AddRobot(containerID)

	return c.Redirect("/admin/robots/" + strconv.Itoa(int(robot.ID)))
}

// ShowRobot 显示机器人详情
func ShowRobot(c *fiber.Ctx) error {
	id, err := strconv.Atoi(c.Params("id"))
	if err != nil {
		return fiber.NewError(fiber.StatusBadRequest, "无效的ID")
	}

	var robot model.Robot
	db := model.GetDB()

	if err := db.First(&robot, id).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return fiber.NewError(fiber.StatusNotFound, "机器人不存在")
		}
		return fiber.NewError(fiber.StatusInternalServerError, "查询数据库失败")
	}

	return c.Render("robot/show", fiber.Map{
		"Title": robot.Nickname,
		"Robot": robot,
	})
}

// DeleteRobot 删除机器人
func DeleteRobot(c *fiber.Ctx) error {
	id, err := strconv.Atoi(c.Params("id"))
	if err != nil {
		// 针对API请求返回JSON
		if strings.HasPrefix(c.Get("Accept"), "application/json") || c.Method() == "DELETE" {
			return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
				"success": false,
				"message": "无效的ID",
			})
		}
		return fiber.NewError(fiber.StatusBadRequest, "无效的ID")
	}

	var robot model.Robot
	db := model.GetDB()

	if err = db.First(&robot, id).Error; err != nil {
		// 针对API请求返回JSON
		if strings.HasPrefix(c.Get("Accept"), "application/json") || c.Method() == "DELETE" {
			return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
				"success": false,
				"message": "机器人不存在",
			})
		}
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return fiber.NewError(fiber.StatusNotFound, "机器人不存在")
		}
		return fiber.NewError(fiber.StatusInternalServerError, "查询数据库失败")
	}

	// 首先尝试登出微信
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	robotCli, err := xybot.NewClient(robot.WechatID, robot.ContainerHost, false)
	if err != nil {
		log.Errorf("创建微信客户端失败: %v", err)
	}

	if robot.Status == model.RobotStatusOnline {
		if err = robotCli.Login.Logout(); err != nil {
			log.Errorf("登出机器人失败: %v", err)
			// 继续删除流程，不因登出失败而中断
		}
	}

	// 删除容器
	if err = docker.RemoveContainer(ctx, robot.ContainerID, true); err != nil {
		log.Errorf("删除容器失败: %v", err)
		// 继续删除流程，不因容器删除失败而中断
	}

	// 从监控器移除
	monitor := docker.NewContainerMonitor(db, time.Minute)
	monitor.RemoveRobot(robot.ContainerID)

	// 删除数据库记录
	if err = db.Delete(&robot).Error; err != nil {
		// 针对API请求返回JSON
		if strings.HasPrefix(c.Get("Accept"), "application/json") || c.Method() == "DELETE" {
			return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
				"success": false,
				"message": "删除机器人失败: " + err.Error(),
			})
		}
		return fiber.NewError(fiber.StatusInternalServerError, "删除机器人失败: "+err.Error())
	}

	// 针对API请求返回JSON
	if strings.HasPrefix(c.Get("Accept"), "application/json") || c.Method() == "DELETE" {
		return c.JSON(fiber.Map{
			"success": true,
			"message": "机器人已成功删除",
		})
	}

	// 普通请求重定向
	return c.Redirect("/admin/robots")
}

// RobotLogin 显示微信登录二维码或唤醒登录
func RobotLogin(c *fiber.Ctx) error {
	id, err := strconv.Atoi(c.Params("id"))
	if err != nil {
		return fiber.NewError(fiber.StatusBadRequest, "无效的ID")
	}

	var robot model.Robot
	db := model.GetDB()
	if err = db.First(&robot, id).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return fiber.NewError(fiber.StatusNotFound, "机器人不存在")
		}
		return fiber.NewError(fiber.StatusInternalServerError, "查询数据库失败")
	}

	// 检查机器人是否已在线，如果在线则无需登录
	if robot.Status == model.RobotStatusOnline {
		// 渲染"已在线"页面
		return c.Render("robot/login", fiber.Map{
			"Title":    "微信登录",
			"Robot":    robot,
			"IsOnline": true,
		})
	}

	// 检查是否指定使用二维码登录
	forceQrcode := c.Query("qrcode") == "1"

	// 创建微信客户端
	robotCli, err := xybot.NewClient(robot.WechatID, robot.ContainerHost, false)
	if err != nil {
		return c.Render("robot/login", fiber.Map{
			"Title":   "微信登录",
			"Robot":   robot,
			"Message": "创建微信客户端失败: " + err.Error(),
			"IsError": true,
		})
	}

	// 如果存在WechatID且没有强制要求使用二维码，则使用唤醒登录
	if robot.WechatID != "" && !forceQrcode {
		awakenResp, err := robotCli.Login.AwakenLogin()
		if err != nil {
			return c.Render("robot/login", fiber.Map{
				"Title":    "微信登录",
				"Robot":    robot,
				"Message":  "唤醒登录失败: " + err.Error(),
				"IsError":  true,
				"IsAwaken": true,
			})
		}

		// 渲染唤醒登录页面
		return c.Render("robot/login", fiber.Map{
			"Title":    "微信登录",
			"Robot":    robot,
			"UUID":     awakenResp.QrCodeResponse.Uuid,
			"Expired":  awakenResp.QrCodeResponse.ExpiredTime,
			"IsAwaken": true,
		})
	}

	// 使用新的GetQRCode接口获取二维码，并传递容器访问地址
	qrcodeResp, err := robotCli.Login.GetQRCode(robot.DeviceId, robot.DeviceName)
	if err != nil {
		return c.Render("robot/login", fiber.Map{
			"Title":   "微信登录",
			"Robot":   robot,
			"Message": "获取登录二维码失败: " + err.Error(),
			"IsError": true,
		})
	}

	// 渲染登录页面，包含二维码和UUID（用于后续状态检查）
	return c.Render("robot/login", fiber.Map{
		"Title":    "微信登录",
		"Robot":    robot,
		"QRCode":   qrcodeResp.QRCodeURL,
		"UUID":     qrcodeResp.Uuid,
		"Expired":  qrcodeResp.ExpiredTime,
		"IsAwaken": false,
	})
}

// RobotLogout 机器人退出微信登录
func RobotLogout(c *fiber.Ctx) error {
	id, err := strconv.Atoi(c.Params("id"))
	if err != nil {
		return fiber.NewError(fiber.StatusBadRequest, "无效的ID")
	}

	var robot model.Robot
	db := model.GetDB()

	if err = db.First(&robot, id).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return fiber.NewError(fiber.StatusNotFound, "机器人不存在")
		}
		return fiber.NewError(fiber.StatusInternalServerError, "查询数据库失败")
	}

	// 创建微信客户端
	robotCli, err := xybot.NewClient(robot.WechatID, robot.ContainerHost, false)
	if err != nil {
		return fiber.NewError(fiber.StatusInternalServerError, "创建微信客户端失败: "+err.Error())
	}
	// 使用新的Logout API接口，传递容器访问地址
	if robot.WechatID != "" {
		if err = robotCli.Login.Logout(); err != nil {
			return fiber.NewError(fiber.StatusInternalServerError, "登出微信失败: "+err.Error())
		}
	}

	// 更新机器人状态
	robot.Status = model.RobotStatusOffline
	if err = db.Save(&robot).Error; err != nil {
		return fiber.NewError(fiber.StatusInternalServerError, "更新状态失败")
	}

	return c.Redirect("/admin/robots/" + c.Params("id"))
}
