package service

import (
	"cold-delivery/app/admin/model"
	"cold-delivery/app/admin/service/dto"
	"cold-delivery/common/actions"
	cDto "cold-delivery/common/dto"
	"cold-delivery/common/global"
	"errors"
	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
	"gogs.baozhida.cn/zoie/OAuth-core/pkg/utils"
	"gogs.baozhida.cn/zoie/OAuth-core/service"
	"gorm.io/gorm"
)

type SysUser struct {
	service.Service
}

// GetPage 获取SysUser列表
func (e *SysUser) GetPage(c *dto.SysUserGetPageReq, p *actions.DataPermission, list *[]model.SysUser, count *int64) error {
	var err error
	var data model.SysUser
	var userList []model.SysUser
	if p.DeptId == 0 {
		err = e.Orm.
			Scopes(
				cDto.MakeCondition(c.GetNeedSearch()),
				cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
			).Where("create_by = ?", p.UserId).
			Where("user_type = ?", model.UserTypeSys).
			Preload("Dept").
			Find(&userList).Limit(-1).Offset(-1).
			Count(count).Error
	} else {
		err = e.Orm.
			Scopes(
				cDto.MakeCondition(c.GetNeedSearch()),
				cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
				actions.UserPermission(data.TableName(), p),
			).
			Where("user_type = ?", model.UserTypeSys).
			Preload("Dept").
			Find(&userList).Limit(-1).Offset(-1).
			Count(count).Error
	}

	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}
	*list = userList
	return nil
}

func GetSysUserCompanyIdScopes(companyId int) func(db *gorm.DB) *gorm.DB {

	return func(db *gorm.DB) *gorm.DB {
		if companyId == 0 {
			return db
		}
		return db.Where("dept_id = ?", companyId)
	}
}
func (e *SysUser) GetPageByDeptId(c *dto.SysUserGetPageByDeptIdReq, p *actions.DataPermission, list *[]model.SysUser, count *int64) error {
	var err error
	var userList []model.SysUser

	var operatingUser model.SysUser
	err = e.Orm.Model(&operatingUser).
		Scopes(actions.UserPermission(operatingUser.TableName(), p)).
		Find(&operatingUser, p.UserId).Error
	if err != nil {
		e.Log.Errorf("获取操作用户信息失败: %s", err)
		return errors.New("获取操作用户信息失败")
	}
	if !operatingUser.HasPost() && operatingUser.Id != 1 {
		return nil
	}

	err = e.Orm.
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
			GetSysUserCompanyIdScopes(c.CompanyId),
		).
		Where("user_type = ?", model.UserTypeSys).
		Preload("Dept").
		Preload("CreateUser").
		Find(&userList).Limit(-1).Offset(-1).
		Count(count).Error

	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}
	*list = userList
	return nil
}

// Get 获取SysUser对象
func (e *SysUser) Get(d *dto.SysUserGetReq, p *actions.DataPermission, userModel *model.SysUser) error {
	var data model.SysUser
	err := e.Orm.Model(&data).
		Scopes(actions.UserPermission(data.TableName(), p)).
		Preload("Dept").
		First(userModel, d.GetId()).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.GetNotFoundOrNoPermissionErr
		}
		return global.GetFailedErr
	}

	return nil
}
func IdScopesUser(id int) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if id == 0 {
			return db
		}
		return db.Where("id = ? ", id)
	}
}
func (e *SysUser) GetUser(id int, userModel *model.SysUser) error {
	var data model.SysUser
	var err error
	err = e.Orm.Model(&data).
		Scopes(IdScopesUser(id)).
		First(userModel).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.GetNotFoundOrNoPermissionErr
		}
		return global.GetFailedErr
	}
	return nil
}

// Insert 创建SysUser对象
func (e *SysUser) Insert(c *dto.SysUserInsertReq, p *actions.DataPermission) error {
	var err error
	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	var dept model.SysDept
	var deptCount int64
	err = e.Orm.Model(&dept).Where("id = ?", c.DeptId).Count(&deptCount).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.CreateFailedErr
	}
	if deptCount == 0 {
		err = errors.New("公司不存在！")
		e.Log.Errorf("db error: %s", err)
		return err
	}

	var operatingUser model.SysUser
	err = e.Orm.Model(&operatingUser).
		Scopes(actions.UserPermission(operatingUser.TableName(), p)).
		Find(&operatingUser, p.UserId).Error
	if err != nil {
		e.Log.Errorf("获取操作用户信息失败: %s", err)
		return errors.New("获取操作用户信息失败")
	}

	//if (!operatingUser.HasPost() && operatingUser.Id != 1) || (operatingUser.Id != 1) {
	//	err = errors.New("无权添加用户，请联系管理员！")
	//	return err
	//}
	if !operatingUser.HasPost() && operatingUser.Id != 1 {
		err = errors.New("无权添加用户，请联系管理员！")
		return err
	}

	var data model.SysUser
	var i int64
	err = e.Orm.Model(&data).Where("username = ?", c.Username).Count(&i).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.CreateFailedErr
	}
	if i > 0 {
		err = errors.New("用户名已存在！")
		e.Log.Errorf("db error: %s", err)
		return err
	}

	var uuid string
	for {
		uuid = utils.GetUUID()
		var j int64
		err = e.Orm.Model(&data).Where("uuid = ?", uuid).Count(&j).Error
		if err != nil {
			continue
		}
		if j == 0 {
			break
		}
	}
	c.Generate(&data)
	data.Uuid = uuid
	err = tx.Create(&data).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.CreateFailedErr
	}
	c.Id = data.Id

	return nil
}

// Update 修改SysUser对象
func (e *SysUser) Update(c *dto.SysUserUpdateReq, p *actions.DataPermission) error {
	var err error
	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	var userModel model.SysUser
	err = e.Orm.
		Scopes(actions.UserPermission(userModel.TableName(), p)).
		First(&userModel, c.GetId()).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.UpdateNotFoundOrNoPermissionErr
		}
		return global.UpdateFailedErr
	}

	c.Generate(&userModel)
	err = tx.Model(&userModel).Where("id = ?", &userModel.Id).
		Omit("password", "salt", "type").Updates(&userModel).Error
	if err != nil {
		if errors.Is(err, model.ErrForbidUpdateSysRole) {
			return model.ErrForbidUpdateSysRole
		}
		e.Log.Errorf("db error: %s", err)
		return global.UpdateFailedErr
	}
	return nil
}

// UpdateStatus 更新用户状态
func (e *SysUser) UpdateStatus(c *dto.UpdateSysUserStatusReq, p *actions.DataPermission) error {
	var userModel model.SysUser
	err := e.Orm.
		Scopes(actions.UserPermission(userModel.TableName(), p)).
		First(&userModel, c.GetId()).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.UpdateNotFoundOrNoPermissionErr
		}
		return global.UpdateFailedErr
	}
	err = e.Orm.Table(userModel.TableName()).Where("id = ? ", c.Id).Updates(c).Error
	if err != nil {
		if errors.Is(err, model.ErrForbidUpdateSysRole) {
			return model.ErrForbidUpdateSysRole
		}
		e.Log.Errorf("db error: %s", err)
		return global.UpdateFailedErr
	}
	return nil
}

// ResetPwd 重置用户密码
func (e *SysUser) ResetPwd(c *dto.ResetSysUserPwdReq, p *actions.DataPermission) error {
	var userModel model.SysUser
	err := e.Orm.
		Scopes(actions.UserPermission(userModel.TableName(), p)).
		First(&userModel, c.GetId()).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.UpdateNotFoundOrNoPermissionErr
		}
		return global.UpdateFailedErr
	}
	c.Generate(&userModel)
	err = e.Orm.Omit("username", "nick_name", "phone", "role_id", "avatar", "sex").Save(&userModel).Error
	if err != nil {
		if errors.Is(err, model.ErrForbidUpdateSysRole) {
			return model.ErrForbidUpdateSysRole
		}
		e.Log.Errorf("db error: %s", err)
		return global.UpdateFailedErr
	}
	return nil
}

// Remove 删除SysUser
func (e *SysUser) Remove(c *dto.SysUserDeleteReq, p *actions.DataPermission) error {
	var err error
	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	var operatingUser model.SysUser
	err = e.Orm.Model(&operatingUser).
		Scopes(actions.UserPermission(operatingUser.TableName(), p)).
		Find(&operatingUser, p.UserId).Error
	if err != nil {
		e.Log.Errorf("获取操作用户信息失败: %s", err)
		return errors.New("获取操作用户信息失败")
	}

	var data model.SysUser
	err = e.Orm.Model(&data).
		Scopes(actions.UserPermission(data.TableName(), p)).
		Find(&data, c.GetId()).Error
	if err != nil {
		e.Log.Errorf("获取操作用户信息失败: %s", err)
		return errors.New("获取操作用户信息失败")
	}
	if p.UserId != 1 {
		if data.CreateBy == 1 && data.HasPost() {
			return errors.New("禁止删除管理员")
		}
	}
	// 管理员1 门店管理员2 配送员3
	if !operatingUser.HasPost() && operatingUser.Id != 1 && data.HasPost() {
		return errors.New("禁止删除管理员")
	}

	if err = tx.Delete(&data, c.GetId()).Error; err != nil {
		if errors.Is(err, model.ErrForbidDeleteSysRole) {
			return model.ErrForbidDeleteSysRole
		}
		e.Log.Errorf("db error: %s", err)
		return err
	}
	return nil
}

// UpdatePwd 修改SysUser对象密码
func (e *SysUser) UpdatePwd(id int, oldPassword, newPassword string) error {
	var err error

	if newPassword == "" {
		return nil
	}
	c := &model.SysUser{}

	err = e.Orm.Model(c).
		Select("id", "password", "salt").
		First(c, id).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.UpdateNotFoundOrNoPermissionErr
		}
		return errors.New("密码修改失败")
	}
	var ok bool
	ok, err = pkg.CompareHashAndPassword(c.Password, oldPassword)
	if err != nil {
		e.Log.Errorf("CompareHashAndPassword error, %s", err.Error())
		return errors.New("密码修改失败")
	}
	if !ok {
		err = errors.New("incorrect Password")
		e.Log.Warnf("user[%d] %s", id, err.Error())
		return err
	}
	c.Password = newPassword
	db := e.Orm.Model(c).Where("id = ?", id).
		Select("Password", "Salt").
		Updates(c)
	if err = db.Error; err != nil {
		if errors.Is(err, model.ErrForbidUpdateSysRole) {
			return model.ErrForbidUpdateSysRole
		}
		e.Log.Errorf("db error: %s", err)
		return errors.New("密码修改失败")
	}
	return nil
}

func (e *SysUser) GetProfile(c *dto.SysUserById, user *model.SysUser) error {
	err := e.Orm.Preload("Dept").First(user, c.GetId()).Error
	if err != nil {
		return err
	}

	return nil
}

// GetUserProfile 获取当前用户权限
func GetUserProfile(e *gorm.DB, userid int) (err error, user model.SysUser) {
	err = e.Preload("Dept").First(&user, userid).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("User not found"), user
		}
		return err, user
	}

	return nil, user
}
