package models

import (
	"database/sql"
	"errors"
	"fmt"
	"time"
	"xugu_license/internal/api"
	"xugu_license/internal/global"
	tokens "xugu_license/internal/utils/token"

	"golang.org/x/crypto/bcrypt"
)

type UserInfo struct {
	Id        int
	UniqueID  string
	Username  string
	Account   string
	Password  string
	Telephone string
	Email     string
	Role      string
	GroupId   sql.NullInt32
}

func (u *UserInfo) PrepareGive() {
	u.Password = ""
}

// 根据用户id查询用户信息
func GetUserInfoByID(uid uint) (*UserInfo, error) {
	var u UserInfo
	fmt.Println("uid: ", uid)
	// 根据user_id从数据库查询数据
	rows, err := global.XuguDB.Query("select ID,UNIQUEID,USERNAME,Account,PASSWORD,TELEPHONE,EMAIL,ROLE,GroupId  from lic_USER where id = ? and  deltime is null  ", uid)
	if err != nil {
		global.Logger.Errorln(" rows user not found ", err.Error())
		return nil, errors.New(" rows user not found")
	}

	for rows.Next() {
		err = rows.Scan(&u.Id, &u.UniqueID, &u.Username, &u.Account, &u.Password, &u.Telephone, &u.Email, &u.Role, &u.GroupId)
		if err != nil {

			global.Logger.Errorln("rows.Next user not found err ", err.Error())

			return nil, errors.New("rows.Next user not found")
		}
	}
	defer rows.Close()
	fmt.Println("u: ", u)
	u.PrepareGive()
	return &u, nil
}

// 查询邮箱或用户名或电话是否已经存在
func CheckEmailOrTelphoneOrAccount(UserName string, Account string, email string, telephone string) (*UserInfo, error) {
	var user UserInfo
	// 根据user_id从数据库查询数据
	fmt.Println("Account: ", Account, email, telephone)
	rows, err := global.XuguDB.Query("select ID,UNIQUEID,USERNAME,Account,PASSWORD,TELEPHONE,EMAIL,ROLE  from lic_USER where (username = ? or Account = ? or telephone = ? or email = ?)  and  deltime is null  ", UserName, Account, telephone, email)
	if err != nil {
		global.Logger.Errorln(" rows user not found", err.Error())
		return nil, errors.New(fmt.Sprintln(" rows user not found: ", err.Error()))
	}

	for rows.Next() {
		err = rows.Scan(&user.Id, &user.UniqueID, &user.Username, &user.Account, &user.Password, &user.Telephone, &user.Email, &user.Role)
		if err != nil {
			//fmt.Println("rows.Scan err: ", err)
			global.Logger.Errorln("rows.Next  not found err  ", err.Error())
			return nil, errors.New(fmt.Sprintln(" rows.Next  user not found: ", err.Error()))
		}
	}

	return &user, nil
}

func LoginCheck(reqAccount, reqPassword string) (string, error) {
	//数据库查询
	fmt.Println("req.reqAccount: ", reqAccount)
	var user UserInfo
	// 对用户名和密码进行验证
	rows, err := global.XuguDB.Query("select id,UNIQUEID,username,Account,password,telephone,email,role  from lic_USER where Account = ? and  deltime is null  ", reqAccount)
	if err != nil {
		return "", err
	}
	hasRows := false
	for rows.Next() {
		hasRows = true
		err = rows.Scan(&user.Id, &user.UniqueID, &user.Username, &user.Account, &user.Password, &user.Telephone, &user.Email, &user.Role)
		if err != nil {
			global.Logger.Errorln("rows.Next  not found err ", err.Error())
			return "", err

		}
	}

	if !hasRows {
		fmt.Println("没有数据。")

		return "", errors.New("no user 没有数据。")
	}
	// 检查遍历是否有错误
	if err = rows.Err(); err != nil {

		global.Logger.Errorln("遍历结果集时出错", err.Error())
		return "", errors.New(fmt.Sprintln(" rows.Next   not found: ", err.Error()))
	} else {
		fmt.Println("查询完毕,无更多数据。")
	}

	defer rows.Close()
	fmt.Printf("user: %#v \n", user)
	err = VerifyPassword(reqPassword, user.Password)
	if err != nil && err == bcrypt.ErrMismatchedHashAndPassword {
		global.Logger.Errorln("bcrypt.ErrMismatchedHashAndPassword时出错", err.Error())
		return "", err
	}

	token, err := tokens.GenerateToken(uint(user.Id), user.UniqueID, user.Username, user.Account, user.Email)
	if err != nil {
		global.Logger.Errorln("tokens.GenerateToken时出错", err.Error())
		return "", err
	}
	return token, nil

}

func VerifyPassword(password, hashedPassword string) error {
	fmt.Println("hashedPassword: ", hashedPassword)
	fmt.Println("password: ", password)
	return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
}

// 获取所有用户
func GetAllUser() (*[]UserInfo, error) {

	//
	rows, err := global.XuguDB.Query("select ID,UniqueID,USERNAME,Account,TELEPHONE,EMAIL,ROLE,GroupId from lic_USER where deltime is null ")
	if err != nil {
		return nil, errors.New(" rows user not found")
	}
	var uS []UserInfo
	for rows.Next() {
		var u UserInfo
		err = rows.Scan(&u.Id, &u.UniqueID, &u.Username, &u.Account, &u.Telephone, &u.Email, &u.Role, &u.GroupId)
		if err != nil {
			global.Logger.Error("GetAllUser ", err.Error())
			return nil, errors.New(fmt.Sprintln("GetAllUser失败: ", err.Error()))
		}
		uS = append(uS, u)
	}
	defer rows.Close()

	return &uS, nil
}

func UpdateUserInfo(u api.UserInfoRequest) error {
	tx, err := global.XuguDB.Begin()
	if err != nil {
		return fmt.Errorf("begin transaction: %v", err)
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			err = tx.Commit()
		}
	}()
	if u.Password != "" {
		//插入 LicenseInfo 表
		_, err = tx.Exec(`
UPDATE lic_USER SET Username = ?,TELEPHONE = ?,EMAIL = ?,PASSWORD =? ,ROLE =? WHERE id = ?;
	`, u.Username, u.Telephone, u.Email, u.Password, u.Role, u.Id)
	} else {

		_, err = tx.Exec(`
UPDATE lic_USER SET Username = ?,TELEPHONE = ?,EMAIL = ? ,ROLE =? WHERE id = ?;
				`, u.Username, u.Telephone, u.Email, u.Role, u.Id)
	}

	if err != nil {

		global.Logger.Error("UpdateUserInfo ", err.Error())

		return err
	}

	return nil
}

func DeleteUserInfo(UniqueID string) error {
	tx, err := global.XuguDB.Begin()
	if err != nil {
		return fmt.Errorf("begin transaction: %v", err)
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			err = tx.Commit()
		}
	}()
	fmt.Println("UniqueID: ", UniqueID)
	//插入 LicenseInfo 表
	//DELETE FROM lic_USER WHERE UNIQUEID = ?;
	_, err = tx.Exec("UPDATE lic_USER SET  deltime = ? WHERE UNIQUEID = ?;", time.Now(), UniqueID)

	if err != nil {

		global.Logger.Error("DeleteUserInfo ", err.Error())
		return err
	}

	return nil
}