package models

import (
	"WorldEpcho/src/datasource"
	"errors"
	"fmt"
	"github.com/go-xorm/xorm"
	"log"
)

/*type User struct {
	Id                 int64  `json:"id"`
	Username           string `json:"username"`
	Phone              string `json:"phone"` //手机号字段表中唯一约束
	Password           string `json:"password"`
	Status             int    `json:"status"` // 0 正常状态, 1应用展览模式
	Createtime         int64  `json:"createtime"`
	Level              int    `json:"level"`       // 权限等级
	InviteCode         string `json:"invite_code"` // 邀请码
	WxOpenid           string `json:"wx_openid"`   // 微信用户的openid
	InitialInspiration int64  `xorm:"initial_inspiration" json:"initial_inspiration"`
}*/

type User struct {
	Id                 int64    `json:"id"`
	Username           string   `json:"username"`
	Phone              string   `json:"phone"` //手机号字段表中唯一约束
	Password           string   `json:"password"`
	Status             int      `json:"status"` // 0 正常状态, 1应用展览模式
	Createtime         int64    `json:"createtime"`
	Level              int      `json:"level"`       // 权限等级
	InviteCode         string   `json:"invite_code"` // 邀请码
	WxOpenid           string   `json:"wx_openid"`   // 微信用户的openid
	InitialInspiration int64    `xorm:"initial_inspiration" json:"initial_inspiration"`
	Tags               []string `xorm:" 'tags' json" json:"tags" `
	RegisteredSource   string   `xorm:"registered_source" json:"registered_source"`
	AuthId             string   `xorm:"authid" json:"AuthId"`
}

var (
	NoFoundUserErr = errors.New("该用户不存在!")
)

//--------------数据库操作-----------------

//根据用户名和密码,查询id
func QueryUserWithParam(username, password string) (int64, int, int, error) {
	var user = User{Username: username, Password: password}
	has, err := datasource.Engine.Get(&user)
	if err != nil {
		log.Println(err.Error())
		return 0, -2, -2, errors.New(err.Error())
	}
	if has {
		return user.Id, user.Level, user.Status, nil
	}
	return 0, -2, -2, errors.New("未查到该用户!")
}

// QueryUserWithParam queries the user by username and password and returns user id, level, status, tags and error.
func QueryUserWithParam2(username, password string) (int64, int, int, []string, string, error) {
	var user = User{Username: username, Password: password}
	has, err := datasource.Engine.Get(&user)
	if err != nil {
		log.Println(err.Error())
		return 0, -2, -2, nil, "", errors.New("database error: " + err.Error())
	}
	if has {
		return user.Id, user.Level, user.Status, user.Tags, user.RegisteredSource, nil
	}
	return 0, -2, -2, nil, "", errors.New("user not found")
}

// UpdateUserStatusAndPhone 根据用户ID更新用户状态和手机号
func UpdateUserStatusAndPhone(session *xorm.Session, userId int64, newStatus int, newPhone string) error {
	user := User{Status: newStatus, Phone: newPhone}
	_, err := session.ID(userId).Cols("status", "phone").Update(&user)
	return err
}

// AddUser 插入一个新用户到数据库
func AddUser(session *xorm.Session, user *User) (int64, int64, error) {
	affected_rows, err := session.Insert(user)
	return affected_rows, user.Id, err
}

//添加或更新
func CreateAndUpdateUser(session *xorm.Session, user *User) (int64, int64, error) {
	var existingUser User
	// 首先根据用户名查询用户是否存在(用户名是学号)
	exists, err := session.Where("username = ?", user.Username).Get(&existingUser)
	if err != nil {
		return 0, 0, err
	}

	var affected_rows int64
	if !exists {
		// 如果用户不存在,则插入新用户
		affected_rows, err = session.Insert(user)
		if err != nil {
			return 0, 0, err
		}
	} else {
		// 如果用户已存在,则更新该用户
		// 注意:这里我们使用existingUser的ID来确保更新正确的记录
		affected_rows, err = session.Id(existingUser.Id).Update(user)
		if err != nil {
			return 0, 0, err
		}
	}

	return affected_rows, user.Id, err

}

// QueryUserWithUsernameAndPhone 根据用户名和手机号查询用户Id
func QueryUserWithUsernameAndPhone(userName, userPhone string) (int64, error) {
	var user = User{Username: userName, Phone: userPhone}

	has, err := datasource.Engine.Get(&user)
	if err != nil {
		return 0, err
	}
	if !has {
		return 0, nil // 可以返回特定的错误,表示用户不存在
	}
	return user.Id, nil

}

// QueryUserWithUsernameAndPhone 根据用户名和手机号查询用户Id
func QueryUserWithUsernameAndPhone_Tx(session *xorm.Session, userName, userPhone string) (int64, error) {
	var user = User{Username: userName, Phone: userPhone}

	has, err := session.Get(&user)
	if err != nil {
		return 0, err
	}
	if !has {
		return 0, nil // 可以返回特定的错误,表示用户不存在
	}
	return user.Id, nil

}

//更新用户信息
func ModifyUserInfo(id int64, user *User) error {
	// 查询用户是否存在
	existingUser := new(User)
	has, err := datasource.Engine.ID(id).Get(existingUser)
	if err != nil {
		return err
	}
	if !has {
		return NoFoundUserErr
	}

	// 更新用户信息
	_, err = datasource.Engine.ID(id).Cols("username", "phone").Update(user)
	if err != nil {
		return err
	}

	return nil
}

// 根据用户ID获取用户对象
func GetUserByID(id int64) (*User, error) {
	user := new(User)
	has, err := datasource.Engine.ID(id).Get(user)
	if err != nil {
		return nil, err
	}
	if !has {
		return nil, fmt.Errorf("User not found")
	}
	return user, nil
}

func GetUserByID_Tx(session *xorm.Session, id int64) (*User, bool, error) {
	user := new(User)
	has, err := session.ID(id).Get(user)
	if err != nil {
		return nil, false, err
	}
	if !has {
		return nil, false, nil
	}
	return user, true, nil
}

// 根据用户id删除用户
func DeleteUserById(id int64) error {
	_, err := datasource.Engine.ID(id).Delete(&User{})
	return err
}

// GetUserExistByID 返回是否找到用户和用户对象
func GetUserExistByID(id int64) (bool, *User, error) {
	// 开启事务
	session := datasource.Engine.NewSession()
	defer session.Close()

	err := session.Begin()
	if err != nil {
		return false, nil, fmt.Errorf("启动事务失败: %v", err)
	}
	user := new(User)
	has, err := session.ID(id).Get(user)
	if err != nil {
		return false, nil, err
	}
	if !has {
		return false, nil, nil
	}
	// 提交事务
	err = session.Commit()
	if err != nil {
		return false, nil, fmt.Errorf("提交事务失败: %v", err)
	}
	return true, user, nil
}

func GetUserExistByID_Tx(session *xorm.Session, id int64) (bool, *User, error) {
	user := new(User)
	has, err := session.ID(id).Get(user)
	if err != nil {
		return false, nil, err
	}
	if !has {
		return false, nil, nil
	}
	return true, user, nil
}

// UpdatePasswordByPhone 更新指定手机号的用户密码
func UpdatePasswordByPhone(session *xorm.Session, phone string, password string) error {
	user := User{}
	found, err := session.Where("phone = ?", phone).Get(&user)
	if err != nil {
		return err
	}
	//用户不存在
	if !found {
		return fmt.Errorf("用户不存在")
	}
	user.Password = password
	_, err = datasource.Engine.ID(user.Id).Cols("password").Update(&user)
	if err != nil {
		return err
	}
	return nil
}

// GetUserByPhone 根据手机号查询用户对象

func GetUserByPhone_Tx(session *xorm.Session, phone string) (*User, bool, error) {
	user := &User{}
	found, err := session.Where("phone = ?", phone).Get(user)
	if err != nil {
		return nil, false, fmt.Errorf("根据手机号查询用户时失败!")
	}
	// 如果用户存在,返回用户对象以及true
	if found {
		return user, true, nil
	}
	// 用户不存在时,返回false
	return nil, false, nil
}

//根据用户名查询用户信息
func GetUserByName_Tx(session *xorm.Session, Username string) (*User, bool, error) {
	user := &User{}
	found, err := session.Where("username = ?", Username).Get(user)
	if err != nil {
		return nil, false, fmt.Errorf("根据手机号查询用户时失败!")
	}
	// 如果用户存在,返回用户对象以及true
	if found {
		return user, true, nil
	}
	// 用户不存在时,返回false
	return nil, false, nil
}

func GetUserByPhone(session *xorm.Session, phone string) (*User, bool, error) {
	user := &User{}
	found, err := session.Where("phone = ?", phone).Get(user)
	if err != nil {
		return nil, false, fmt.Errorf("根据手机号查询用户时失败!")
	}
	// 如果用户存在,返回用户对象以及true
	if found {
		return user, true, nil
	}
	// 用户不存在时,返回false
	return nil, false, nil
}

// 根据微信用户的openid查询对象
func GetWxUserByOpenId(session *xorm.Session, openId string) (*User, bool, error) {
	user := &User{}
	found, err := session.Where("wx_openid = ?", openId).Get(user)
	if err != nil {
		return nil, false, fmt.Errorf("根据手机号查询用户时失败!")
	}
	// 如果用户存在,返回用户对象以及true
	if found {
		return user, true, nil
	}
	// 用户不存在时,返回false
	return nil, false, nil
}

//获取用户权限
func GetUserLevel(id int64) (int, error) {
	user, err := GetUserByID(id)
	if err != nil {
		log.Println("获取用户对象,获取权限时失败!")
		return -1, fmt.Errorf("根据手机号查询用户时失败! ")
	}

	return user.Level, nil
}

// FindOrCreateUser 根据手机号查询用户,若不存在则添加
func FindOrCreateOrUpdateUser(session *xorm.Session, user *User) (int64, error) {
	var existingUser User
	var exist bool
	var err error
	// 检查是否已存在相同的手机号
	if user.Phone != "" {
		exist, err = session.Where("phone = ? ", user.Phone).Get(&existingUser)
	}
	if err != nil {
		return 0, err
	}

	// 如果用户不存在,创建新用户
	if !exist {
		_, err := session.Insert(user)
		if err != nil {
			return 0, err
		}
	} else {
		// 如果用户已存在,则更新用户信息
		_, err := session.ID(existingUser.Id).Update(user)
		if err != nil {
			return 0, err
		}
	}

	return user.Id, nil
}

// IsUserInExhibitionMode 根据用户 ID 查询用户的状态,并返回状态是否为展览模式 (Status == 1)
func IsUserInExhibitionMode(userId int64) (bool, *User, error) {
	var user User
	has, err := datasource.Engine.Where("id = ?", userId).Get(&user)
	if err != nil {
		return false, nil, fmt.Errorf("查询用户状态值出错: %v", err)
	}
	if !has {
		return false, nil, nil // 没有找到用户,返回 false 和 nil
	}
	if user.Status > 0 {
		return true, &user, nil // 用户状态为 1,返回 true 和用户对象
	}
	return false, nil, nil // 用户状态不为 1,返回 false 和 nil
}

//根据用户对象修改用户信息
func UpdateUser(user *User) (userid int64, err error) {

	_, err = datasource.Engine.Id(user.Id).Update(user)
	if err != nil {
		return 0, fmt.Errorf("更新用户失败: %s", err)
	}

	return user.Id, nil
}

//根据用户对象修改用户信息2,
func UpdateUser_Tx(session *xorm.Session, user *User) (userid int64, err error) {
	_, err = session.Id(user.Id).Update(user)
	if err != nil {
		return 0, fmt.Errorf("更新用户失败: %s", err)
	}
	return user.Id, nil
}

// FindUserWithStudentID 查询学号等于指定学号的用户
func FindUserWithStudentID(studentId string) (*User, *UserInfo, error) {
	var user User
	var userInfo UserInfo
	found, err := datasource.Engine.Table("user").Alias("u").
		Select("u.*, ui.*").
		Join("INNER", []string{"user_info", "ui"}, "u.username = ui.student_id").
		Where("ui.student_id = ?", studentId).
		Get(&user)
	if err != nil {
		return nil, nil, err
	}
	if !found {
		return nil, nil, nil // 没有错误,但也没有找到记录
	}
	// 因为使用了Get方法和自定义Select,需要手动分配获取的UserInfo字段到UserInfo结构体
	datasource.Engine.Table("user_info").Where("student_id = ?", studentId).Get(&userInfo)
	return &user, &userInfo, nil
}

// FindUserAndUserInfoByPhone 根据手机号查询用户及其详细信息
func FindUserAndUserInfoByPhone(phone string) (*User, *UserInfo, error) {
	var user User
	var userInfo UserInfo

	// 首先根据电话查询用户
	has, err := datasource.Engine.Where("phone = ?", phone).Get(&user)
	if err != nil {
		return nil, nil, err // 查询过程中发生错误
	}
	if !has {
		return nil, nil, nil // 没有找到对应的用户
	}

	// 有用户,则根据用户ID查询用户详细信息
	_, err = datasource.Engine.Where("user_id = ?", user.Id).Get(&userInfo)
	if err != nil {
		return nil, nil, err // 查询用户详情过程中发生错误
	}

	return &user, &userInfo, nil
}

// GetUserAndUserInfo 通过用户ID查询用户注册信息和用户详情信息
func GetUserAndUserInfo(userID int64) (*User, *UserInfo, error) {
	// 思路是先查询 User 表,然后用相同的用户ID查询 UserInfo 表

	// 查询用户注册信息
	user := &User{}
	if _, err := datasource.Engine.ID(userID).Get(user); err != nil {
		return nil, nil, fmt.Errorf("error querying user by id: %v", err)
	}

	// 查询用户详情信息
	userInfo := &UserInfo{}
	if _, err := datasource.Engine.Where("user_id = ?", userID).Get(userInfo); err != nil {
		return nil, nil, fmt.Errorf("error querying user info by user id: %v", err)
	}

	return user, userInfo, nil
}