package main

import (
	"bytes"
	"fmt"
	"net/http"
	"strconv"
	"text/template"

	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"
)

func SetupRouter() *gin.Engine {
	r := gin.Default()

	r.Static("/static", "./static")
	r.GET("/ping", func(c *gin.Context) {
		c.String(200, "frpc-console 后端已启动 🎉")
	})
	r.GET("/", func(c *gin.Context) {
		c.File("./static/index.html")
	})

	api := r.Group("/api")
	{
		// 公开接口
		api.GET("/check/users", checkUsersHandler)
		api.POST("/register", registerHandler)
		api.POST("/login", loginHandler)

		// 需鉴权
		auth := api.Group("/")
		auth.Use(AuthMiddleware())
		{
			auth.GET("/config", getConfigHandler)
			auth.PUT("/config", updateConfigHandler)

			auth.GET("/proxies", getProxiesHandler)
			auth.GET("/proxy/:id", getProxyHandler)
			auth.POST("/proxy", createProxyHandler)
			auth.PUT("/proxy/:id", updateProxyHandler)
			auth.DELETE("/proxy/:id", deleteProxyHandler)

			auth.POST("/frpc/reload", reloadFrpcHandler)
			auth.POST("/frpc/start", startFrpcHandler)
			auth.POST("/frpc/stop", stopFrpcHandler)
			auth.GET("/frpc/status", getFrpcStatusHandler)

			auth.POST("/import/toml", importTomlHandler)
			auth.GET("/export/toml", ExportTomlHandler)

			auth.PUT("/user/password", changePasswordHandler)
		}
	}

	return r
}

// ========== 检查是否有用户 ==========
func checkUsersHandler(c *gin.Context) {
	count, err := CountUsers()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "查询用户失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": 0,
		"data": gin.H{
			"hasUsers": count > 0,
			"count":    count,
		},
	})
}

// ========== 注册（仅首次启动可用） ==========
func registerHandler(c *gin.Context) {
	var req struct {
		Username string `json:"username"`
		Password string `json:"password"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "请求参数错误"})
		return
	}

	count, err := CountUsers()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "查询用户失败"})
		return
	}
	if count > 0 {
		c.JSON(http.StatusForbidden, gin.H{"code": 1, "msg": "已存在管理员账户，请登录"})
		return
	}

	if len(req.Username) < 5 {
		c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "用户名至少 5 位"})
		return
	}

	if !ValidatePassword(req.Password) {
		c.JSON(http.StatusBadRequest, gin.H{
			"code": 1,
			"msg":  "密码至少 8 位，需包含大小写字母、数字和特殊字符",
		})
		return
	}

	hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "密码加密失败"})
		return
	}

	if err := CreateUser(req.Username, string(hash)); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "创建用户失败: " + err.Error()})
		return
	}

	token, err := GenerateJWT(req.Username)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "生成Token失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 0,
		"msg":  "注册成功",
		"data": gin.H{"token": token},
	})
}

// ========== 登录 ==========
func loginHandler(c *gin.Context) {
	var req struct {
		Username string `json:"username"`
		Password string `json:"password"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "请求参数错误"})
		return
	}

	user, err := GetUserByUsername(req.Username)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"code": 1, "msg": "用户名或密码错误"})
		return
	}

	if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.Password)); err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"code": 1, "msg": "用户名或密码错误"})
		return
	}

	token, err := GenerateJWT(user.Username)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "生成Token失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 0,
		"msg":  "登录成功",
		"data": gin.H{"token": token},
	})
}

// ========== 修改密码 ==========
func changePasswordHandler(c *gin.Context) {
	var req struct {
		OldPassword string `json:"oldPassword"`
		NewPassword string `json:"newPassword"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "请求参数错误"})
		return
	}

	username, exists := c.Get("username")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"code": 1, "msg": "未登录"})
		return
	}

	user, err := GetUserByUsername(username.(string))
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"code": 1, "msg": "用户不存在"})
		return
	}

	if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.OldPassword)); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "当前密码错误"})
		return
	}

	if !ValidatePassword(req.NewPassword) {
		c.JSON(http.StatusBadRequest, gin.H{
			"code": 1,
			"msg":  "密码至少 8 位，需包含大小写字母、数字和特殊字符",
		})
		return
	}

	hash, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "密码加密失败"})
		return
	}

	if err := UpdatePassword(username.(string), string(hash)); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "更新密码失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "密码修改成功"})
}

// ========== 全局配置 ==========
func getConfigHandler(c *gin.Context) {
	cfg, err := GetGlobalConfig()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "读取配置失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 0, "data": cfg})
}

func updateConfigHandler(c *gin.Context) {
	var cfg GlobalConfig
	if err := c.ShouldBindJSON(&cfg); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "请求参数错误"})
		return
	}
	cfg.TcpMux = true

	if err := UpdateGlobalConfig(&cfg); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "更新配置失败: " + err.Error()})
		return
	}

	if err := GenerateFrpcConfig(); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "生成配置文件失败: " + err.Error()})
		return
	}

	if err := ReloadFrpc(); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "热加载失败: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "配置更新成功"})
}

// ========== 隧道管理 ==========
func getProxiesHandler(c *gin.Context) {
	proxies, err := GetProxies()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "读取隧道列表失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 0, "data": proxies})
}

func getProxyHandler(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "无效的ID"})
		return
	}
	p, err := GetProxy(id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"code": 1, "msg": "隧道不存在"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 0, "data": p})
}

func createProxyHandler(c *gin.Context) {
	var p Proxy
	if err := c.ShouldBindJSON(&p); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "请求参数错误"})
		return
	}
	p.Enabled = true

	if err := CreateProxy(&p); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "创建隧道失败: " + err.Error()})
		return
	}

	if err := generateAndReload(); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "配置生效失败: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "隧道创建成功", "data": gin.H{"id": p.ID}})
}

func updateProxyHandler(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "无效的ID"})
		return
	}
	var p Proxy
	if err := c.ShouldBindJSON(&p); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "请求参数错误"})
		return
	}
	p.ID = id

	if err := UpdateProxy(&p); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "更新隧道失败: " + err.Error()})
		return
	}

	if err := generateAndReload(); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "配置生效失败: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "隧道更新成功"})
}

func deleteProxyHandler(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "无效的ID"})
		return
	}

	if err := DeleteProxy(id); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "删除隧道失败: " + err.Error()})
		return
	}

	if err := generateAndReload(); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "配置生效失败: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "隧道删除成功"})
}

// ========== frpc 控制 ==========
func reloadFrpcHandler(c *gin.Context) {
	if err := GenerateFrpcConfig(); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "生成配置失败: " + err.Error()})
		return
	}
	if err := ReloadFrpc(); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "热加载失败: " + err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "热加载成功"})
}

func startFrpcHandler(c *gin.Context) {
	if err := StartFrpc(); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "启动失败: " + err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "frpc 启动成功"})
}

func stopFrpcHandler(c *gin.Context) {
	if err := StopFrpc(); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "停止失败: " + err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "frpc 已停止"})
}

func getFrpcStatusHandler(c *gin.Context) {
	running, err := GetFrpcStatus()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "查询状态失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 0, "data": gin.H{"running": running}})
}

// ========== 导入 TOML ==========
func importTomlHandler(c *gin.Context) {
	file, err := c.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "请选择文件"})
		return
	}

	f, err := file.Open()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "读取文件失败"})
		return
	}
	defer f.Close()

	buf := new(bytes.Buffer)
	if _, err := buf.ReadFrom(f); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "读取文件失败"})
		return
	}

	parsed, err := ParseToml(buf.String())
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "解析 TOML 失败: " + err.Error()})
		return
	}

	cfg := parsed.ToGlobalConfig()
	cfg.TcpMux = true
	if err := UpdateGlobalConfig(cfg); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "更新配置失败: " + err.Error()})
		return
	}

	if _, err := DB.Exec("DELETE FROM proxies"); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "清空隧道失败"})
		return
	}

	proxies := parsed.ToProxies()
	for _, p := range proxies {
		if err := CreateProxy(&p); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "导入隧道失败: " + err.Error()})
			return
		}
	}

	if err := GenerateFrpcConfig(); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "生成配置失败: " + err.Error()})
		return
	}
	if err := ReloadFrpc(); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 0,
			"msg":  fmt.Sprintf("导入成功！共 %d 条隧道，但热加载失败: %s", len(proxies), err.Error()),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 0,
		"msg":  fmt.Sprintf("导入成功！共 %d 条隧道", len(proxies)),
	})
}

// ========== 导出 TOML ==========
func ExportTomlHandler(c *gin.Context) {
	cfg, err := GetGlobalConfig()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "读取配置失败: " + err.Error()})
		return
	}

	proxies, err := GetProxies()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "读取隧道失败: " + err.Error()})
		return
	}

	var activeProxies []Proxy
	for _, p := range proxies {
		if p.Enabled {
			activeProxies = append(activeProxies, p)
		}
	}

	data := struct {
		*GlobalConfig
		Proxies []Proxy
	}{
		GlobalConfig: cfg,
		Proxies:      activeProxies,
	}

	tmpl, err := template.New("frpc").Parse(FrpcTemplateContent)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "解析模板失败: " + err.Error()})
		return
	}

	var buf bytes.Buffer
	if err := tmpl.Execute(&buf, data); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "渲染模板失败: " + err.Error()})
		return
	}

	c.Header("Content-Type", "text/plain; charset=utf-8")
	c.Header("Content-Disposition", "attachment; filename=frpc.toml")
	c.String(http.StatusOK, buf.String())
}

// ========== 辅助 ==========
func generateAndReload() error {
	if err := GenerateFrpcConfig(); err != nil {
		return err
	}
	return ReloadFrpc()
}
