package tui

import (
	"context"
	"errors"
	"fmt"
	"github.com/google/uuid"
	"time"
	"wireguard-ui/component"
	"wireguard-ui/global/client"
	"wireguard-ui/global/constant"
	"wireguard-ui/http/vo"
	"wireguard-ui/service"
	"wireguard-ui/utils"
)

type App struct {
	TokenSecret string            // token密钥
	User        *vo.User          // 登陆用户
	Client      *ClientComponent  // 客户端组件
	Server      *ServerComponent  // 服务端组件
	Setting     *SettingComponent // 设置组件
}

func NewApp() *App {
	app := &App{}
	if _, err := app.Login(); err != nil {
		fmt.Println("登陆失败: ", err)
		return nil
	}
	err := app.AuthLogin()
	if err != nil {
		fmt.Println("登陆失败: ", err)
		return nil
	}
	fmt.Println("\n=============== 登陆成功 ==============================================================================")
	app.Client = NewClientComponent(app.User)
	app.Server = NewServerComponent(app.User)
	app.Setting = NewSettingComponent(app.User)
	fmt.Println("=============== 欢迎使用wireguard-tui =================================================================")
	fmt.Println("=============== 当前用户: ", app.User.Nickname, " ================================================================")
	fmt.Println("=============== 当前时间: ", time.Now().Format("2006-01-02 15:04:05"), " =======================================================")
	fmt.Println("=============== 注意事项如下: =========================================================================")
	fmt.Println("=============== 1. 请确保服务端已经安装wireguard ======================================================")
	fmt.Println("=============== 2. 请确保服务端和客户端配置文件路径正确 ===============================================")
	fmt.Println("=============== 3. 请确保服务端和客户端配置文件权限正确 ===============================================")
	fmt.Println("=============== 4. 请确保服务端和客户端配置文件内容正确 ===============================================")
	fmt.Println("=============== 5. 请勿泄露配置文件内容 ===============================================================")
	fmt.Println("=============== 6. 每次修改客户端、服务端配置或者全局配置过后，请使用重启功能重启服务端，以保证生效 ===")
	fmt.Println("=============== 7. 当使用重启无效时，请手动执行对应命令 ===============================================")
	fmt.Println("=============== 8. 请勿随意删除客户端，删除后无法恢复 =================================================")
	fmt.Println("=============== 9. 手动命令 ===========================================================================")
	fmt.Println("=============== 10. 启动wireguard服务端: wg-quick up wg0 ==============================================")
	fmt.Println("=============== 11. 停止wireguard服务端: wg-quick down wg0 ============================================")

	return app
}

func (a *App) Run() {
	if a == nil {
		return
	}
	for {

		PrintMenu()
		chooseMenu := readInput("请选择菜单: ")
		switch chooseMenu {
		case "1":
			a.Client.ConnectList()
		case "2":
			a.Client.Menus()
		case "3":
			a.Server.Menus()
		case "4":
			a.Setting.Menus()
		case "q":
			return
		}
	}
}

// AuthLogin
// @description: 登陆认证
// @receiver a
// @return string
func (a *App) AuthLogin() error {
	// 先判断token是否存在
	tokenStr, err := client.Redis.Get(context.Background(), fmt.Sprintf("%s:%s", constant.TUIUserToken, a.User.Id)).Result()
	if err != nil {
		// 不存在，去登陆
		tokenStr, err = a.Login()
		if err != nil {
			return err
		}
	}

	// 存在，不必要再次登陆,解析token
	claims, err := component.JWT().ParseToken("Bearer "+tokenStr, a.TokenSecret, "tui")
	if err != nil {
		return err
	}

	user, err := service.User().GetUserById(claims.ID)
	if err != nil {
		return err
	}

	if user.Status != constant.Enabled {
		return errors.New("用户状态异常，请联系管理员处理")
	}

	a.User = &vo.User{
		Id:       user.Id,
		Account:  user.Account,
		Nickname: user.Nickname,
		Avatar:   user.Avatar,
		Contact:  user.Contact,
		IsAdmin:  user.IsAdmin,
		Status:   user.Status,
	}

	return nil
}

// Login
// @description: 登陆
// @receiver a
// @return string
func (a *App) Login() (tokenStr string, err error) {
	fmt.Println("============== 登陆 ==============")

	username := readInput("请输入用户名: ")
	password := readInput("请输入密码: ")
	// 验证码正确，查询用户信息
	user, err := service.User().GetUserByAccount(username)
	if err != nil {
		return "", fmt.Errorf("用户不存在: %v", err)
	}

	// 对比密码
	if !utils.Password().ComparePassword(user.Password, password) {
		return "", errors.New("密码错误")
	}

	secret := component.JWT().GenerateSecret(password, uuid.NewString(), time.Now().Local().String())
	// 生成token
	token, _, err := component.JWT().GenerateToken(user.Id, secret, "tui")
	if err != nil {
		return "", fmt.Errorf("登陆失败: %v", err)
	}

	a.User = &vo.User{
		Id:       user.Id,
		Account:  user.Account,
		Nickname: user.Nickname,
		Avatar:   user.Avatar,
		Contact:  user.Contact,
		IsAdmin:  user.IsAdmin,
		Status:   user.Status,
	}

	a.TokenSecret = secret

	return "Bearer " + token, nil
}
