package service

import (
	"fmt"

	"gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/factory"
	"gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/users/command"
	"gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/users/query"
	"gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/domain"
	"gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/infrastructure/serviceGateway"
	"gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/lib"
)

type UsersService struct {
}

func NewUsersService(option map[string]interface{}) *UsersService {
	newUsersService := new(UsersService)
	return newUsersService
}

func (service UsersService) UserLoginBySecretKey(cmd command.LoginBySecretKeyCommand) (interface{}, error) {
	var err error
	if err = cmd.ValidateCommand(); err != nil {
		return nil, err
	}
	//向统一用户中心确认密钥信息并获取用户数据
	ucenterService := serviceGateway.NewMmmUserCenterServiceGateway()
	loginResp, err := ucenterService.RequestUCenterLoginBySecret(cmd.Code)
	if err != nil {
		e := fmt.Sprintf("通过密钥(code=%s)从统一用户中心获取数据失败:%s", cmd.Code, err.Error())
		return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
	}

	if err := loginResp.IsOK(); err != nil {
		e := fmt.Sprintf("登录失败:%s", err)
		return nil, lib.ThrowError(lib.BUSINESS_ERROR, e)
	}
	adminBusinessService := serviceGateway.NewMmmBusinessAdminServiceGateway()
	getUserAuthResp, err := adminBusinessService.GetUserAuth(loginResp.Data.Muid)
	if err != nil {
		e := fmt.Sprintf("用户鉴权失败:%s", err)
		return nil, lib.ThrowError(lib.BUSINESS_ERROR, e)
	}
	if err := getUserAuthResp.IsOK(); err != nil {
		return nil, lib.ThrowError(lib.BUSINESS_ERROR, "该公司没有操作权限")
	}
	if !getUserAuthResp.Data.UserAuth {
		return nil, lib.ThrowError(lib.BUSINESS_ERROR, "该公司没有操作权限")
	}
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
	)
	if err = transactionContext.StartTransaction(); err != nil {
		return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	var (
		companyRespository domain.CompanyRepository
		userRespository    domain.UsersRepository
		companyData        domain.Company
		usersData          domain.Users
	)
	if companyRespository, err = factory.CreateCompanyRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	if userRespository, err = factory.CreateUsersRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	//检索本系统的公司数据判断公司权限
	companyData, err = companyRespository.FindOne(domain.CompanyFindOneOptions{
		AdminCompanyId: loginResp.Data.CompanyId,
	})
	if err != nil {
		e := fmt.Sprintf("获取公司(admin_company_id=%d)数据失败:%s", loginResp.Data.CompanyId, err.Error())
		return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
	}
	//检索本系统的用户数据
	usersData, err = userRespository.FindOne(domain.UsersFindOneQuery{
		Id:        loginResp.Data.Muid,
		CompanyId: companyData.Id,
	})
	if err != nil {
		e := fmt.Sprintf("获取用户(id=%d;CompanyId=%d)数据失败:%s",
			loginResp.Data.Muid, companyData.Id, err.Error())
		return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
	}
	//确认用户权限
	if !usersData.IsUsable() {
		return nil, lib.ThrowError(lib.BUSINESS_ERROR, "用户被禁用")
	}
	err = transactionContext.CommitTransaction()
	newJwt := lib.NewMyToken(usersData.Id, companyData.Id)
	newToken, err := newJwt.CreateJWTToken()
	//生成token
	returnData := map[string]interface{}{
		"access": map[string]interface{}{
			"accessToken": newToken,
			"expiresIn":   lib.JWtExpiresSecond,
		},
	}
	return returnData, nil
}

//GetAdminpPofile  登录后获取用户的权限配置数据
func (service UsersService) GetUserPofile(userId int64) (interface{}, error) {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
		err                   error
	)
	if err = transactionContext.StartTransaction(); err != nil {
		return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	var (
		userRespository      domain.UsersRepository
		usersData            domain.Users
		permissionRepository domain.AdminPermissionRepository
		permissionList       []domain.AdminPermission
	)
	if userRespository, err = factory.CreateUsersRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	if permissionRepository, err = factory.CreateAdminPermissionRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	usersData, err = userRespository.FindOne(domain.UsersFindOneQuery{
		Id: userId,
	})
	if err != nil {
		e := fmt.Sprintf("获取用户(Id=%d)数据失败:%s",
			userId, err.Error())
		return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
	}
	var permissionQuery domain.PermissionFindOption
	permissionList, err = permissionRepository.Find(permissionQuery)
	if err != nil {
		return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	err = transactionContext.CommitTransaction()
	returnData := service.buildUserPofile(usersData, permissionList)
	return returnData, nil
}

//buildUserPofile 组装前端需要的数据 ,用户登录后获取的配置
func (service UsersService) buildUserPofile(userData domain.Users, permissionList []domain.AdminPermission) map[string]interface{} {
	menus := make([]map[string]interface{}, 0, len(permissionList))
	for _, v := range permissionList {
		m := map[string]interface{}{
			"code":     v.Code,
			"icon":     v.Icon,
			"parentId": v.ParentId,
			"sort":     v.Sort,
			"name":     v.Name,
			"id":       v.Id,
			"status":   0, //状态 1-启用 0-禁用,前端需要
		}
		if userData.IsSuperAdmin() {
			m["status"] = 1
			menus = append(menus, m)
			continue
		}
		for _, p := range userData.Permission {
			if p.Id == v.Id {
				m["status"] = 1
				break
			}
			if p.Id == v.ParentId {
				m["status"] = 1
				break
			}
		}
		menus = append(menus, m)
	}
	user := map[string]string{
		"id":        fmt.Sprint(userData.Id),
		"name":      userData.Name,
		"adminType": "2", //	前端需要的管理员类型 1-超级管理员 2-子管理员
	}
	if userData.IsSuperAdmin() {
		user["adminType"] = "1"
	}
	respData := map[string]interface{}{
		"user":  user,
		"menus": menus,
	}
	return respData
}

//ValidateAdminpPermission 校验用户的操作权限
func (service UsersService) ValidateAdminpPermission(queryOption query.ValidatePermissionQuery) (bool, error) {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
		err                   error
	)
	if err = transactionContext.StartTransaction(); err != nil {
		return false, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	var (
		userRespository domain.UsersRepository
		usersData       domain.Users
	)

	if userRespository, err = factory.CreateUsersRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return false, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	usersData, err = userRespository.FindOne(domain.UsersFindOneQuery{
		Id: queryOption.UserId,
	})
	if err != nil {
		return false, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	if !usersData.IsUsable() {
		return false, nil
	}
	err = transactionContext.CommitTransaction()
	ok := usersData.HasPermissionByCode(queryOption.PermissionCode)
	return ok, nil
}

//获取用户列表
func (service UsersService) GetUserList(queryOption query.UserListQuery) (int, []map[string]interface{}, error) {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
		err                   error
	)
	if err = transactionContext.StartTransaction(); err != nil {
		return 0, nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	var (
		userRespository      domain.UsersRepository
		usersData            []domain.Users
		cnt                  int
		permissionRepository domain.AdminPermissionRepository
		permissionList       []domain.AdminPermission
	)
	if userRespository, err = factory.CreateUsersRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return 0, nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	if permissionRepository, err = factory.CreateAdminPermissionRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return 0, nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	cnt, usersData, err = userRespository.Find(domain.UsersFindQuery{
		UserNameMatch: queryOption.UserNameMatch,
		Offset:        queryOption.Offset,
		Limit:         queryOption.Limit,
		CompanyId:     queryOption.CompanyId,
	})
	var permissionQuery = domain.PermissionFindOption{}
	permissionList, err = permissionRepository.Find(permissionQuery)
	if err != nil {
		return 0, nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	err = transactionContext.CommitTransaction()
	result := service.buildGetUserList(usersData, permissionList)
	return cnt, result, nil
}

//buildGetUserList 组装构建前端需要的用户列表数据
func (service UsersService) buildGetUserList(usersData []domain.Users, permissionData []domain.AdminPermission) []map[string]interface{} {
	result := make([]map[string]interface{}, 0, len(usersData))
	permissionMap := map[int64]domain.AdminPermission{}
	for i := range permissionData {
		if permissionData[i].ParentId > 0 {
			continue
		}
		permissionMap[permissionData[i].Id] = permissionData[i]
	}
	for i := range usersData {
		permissionTypes := []string{}
		if usersData[i].IsSuperAdmin() {
			for _, pd := range permissionData {
				if pd.ParentId > 0 {
					continue
				}
				permissionTypes = append(permissionTypes, pd.Name)
			}
		} else {
			for _, vv := range usersData[i].Permission {
				if pm, ok := permissionMap[vv.Id]; ok {
					permissionTypes = append(permissionTypes, pm.Name)
				}
			}
		}
		m := map[string]interface{}{
			"id":          usersData[i].Id,
			"account":     usersData[i].Phone,
			"name":        usersData[i].Name,
			"permission":  permissionTypes,
			"isAdmin":     0,
			"partnership": len(usersData[i].AccessPartners),
		}
		if usersData[i].IsSuperAdmin() {
			m["isAdmin"] = 1
		}
		result = append(result, m)
	}
	return result
}

func (service UsersService) GetUserData(userId int64, companyId int64) (map[string]interface{}, error) {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
		err                   error
	)
	if err = transactionContext.StartTransaction(); err != nil {
		return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	var (
		userRespository   domain.UsersRepository
		perterRespository domain.PartnerInfoRepository
		usersData         domain.Users
		pertnerList       []domain.PartnerInfo
	)
	if userRespository, err = factory.CreateUsersRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	if perterRespository, err = factory.CreatePartnerInfoRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	usersData, err = userRespository.FindOne(domain.UsersFindOneQuery{
		Id: userId, CompanyId: companyId,
	})
	if err != nil {
		e := fmt.Sprintf("获取用户(id=%d;company_id=%d)数据失败;%s", userId, companyId, err)
		return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
	}
	var partnerIds []int64
	for _, v := range usersData.AccessPartners {
		partnerIds = append(partnerIds, v.Id)
	}
	if len(partnerIds) > 0 {
		pertnerList, err = perterRespository.Find(domain.PartnerFindQuery{
			Ids: partnerIds,
		})
		if err != nil {
			e := fmt.Sprintf("获取合伙人数据失败:%s", err)
			return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
		}
	}
	transactionContext.CommitTransaction()
	return service.buildGetUserData(&usersData, pertnerList)
}

//buildGetUserData 构建前端需要的数据
func (service UsersService) buildGetUserData(userData *domain.Users, partnerList []domain.PartnerInfo) (map[string]interface{}, error) {
	result := map[string]interface{}{
		"id":             userData.Id,
		"permissionType": []int64{},
		"name":           userData.Name,
		"account":        userData.Phone,
		"isAdmin":        0,
		"status":         0,
		"checkedPartner": []map[string]interface{}{},
	}
	if userData.IsSuperAdmin() {
		result["isAdmin"] = 1
	}
	if userData.IsUsable() {
		result["status"] = 1
	}
	permissionIds := make([]int64, 0, len(userData.Permission))
	for _, v := range userData.Permission {
		permissionIds = append(permissionIds, v.Id)
	}

	if userData.IsSuperAdmin() {
		transactionContext, _ := factory.CreateTransactionContext(nil)
		var permissionRepository domain.AdminPermissionRepository
		var err error
		if permissionRepository, err = factory.CreateAdminPermissionRepository(map[string]interface{}{
			"transactionContext": transactionContext,
		}); err != nil {
			return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
		}
		permissionList, err := permissionRepository.Find(domain.PermissionFindOption{})
		if err != nil {
			e := fmt.Sprintf("获取权限列表数据失败:%s", err)
			return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
		}
		permissionIds = make([]int64, 0)
		for _, v := range permissionList {
			permissionIds = append(permissionIds, v.Id)
		}
	}
	result["permissionType"] = permissionIds
	checkedPartner := make([]map[string]interface{}, 0, len(partnerList))
	for i := range partnerList {
		m := map[string]interface{}{
			"id":   partnerList[i].Partner.Id,
			"name": partnerList[i].Partner.PartnerName,
		}
		checkedPartner = append(checkedPartner, m)
	}
	result["checkedPartner"] = checkedPartner
	return result, nil
}

//EditUserPermission 编辑用户的权限
func (service UsersService) EditUserPermission(cmd command.EditUserPermissionCommand) error {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
		err                   error
	)
	if err = transactionContext.StartTransaction(); err != nil {
		return lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	var (
		userRespository      domain.UsersRepository
		usersData            domain.Users
		permissionRepository domain.AdminPermissionRepository
		permissionList       []domain.AdminPermission
		partnerRespository   domain.PartnerInfoRepository
		partnerList          []domain.PartnerInfo
	)
	if userRespository, err = factory.CreateUsersRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	usersData, err = userRespository.FindOne(domain.UsersFindOneQuery{
		Id: cmd.Id,
	})
	if err != nil {
		e := fmt.Sprintf("获取用户(id=%d)数据失败,%s", cmd.Id, err)
		return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
	}
	if !usersData.InCompany(cmd.CompanyId) {
		return lib.ThrowError(lib.BUSINESS_ERROR, "提交的数据异常")
	}

	if permissionRepository, err = factory.CreateAdminPermissionRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	if len(cmd.PermissionType) > 0 {
		permissionList, err = permissionRepository.Find(domain.PermissionFindOption{
			Ids: cmd.PermissionType,
		})
		if err != nil {
			e := fmt.Sprintf("获取权限列表数据失败:%s", err)
			return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
		}
	}
	if partnerRespository, err = factory.CreatePartnerInfoRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
	}
	if len(cmd.CheckedPartner) > 0 {
		partnerList, err = partnerRespository.Find(domain.PartnerFindQuery{
			Ids:       cmd.CheckedPartner,
			CompanyId: cmd.CompanyId,
		})
		if err != nil {
			e := fmt.Sprintf("获取合伙人列表数据失败:%s", err)
			return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
		}
	}
	var (
		partners        = make([]domain.Partner, 0, len(partnerList))
		permissionsBase = make([]domain.AdminPermissionBase, 0)
	)
	for i := range partnerList {
		p := partnerList[i].Partner
		partners = append(partners, p)
	}
	for i := range permissionList {
		if permissionList[i].Code == domain.PERMINSSION_ADMIN_USER && !usersData.IsSuperAdmin() {
			return lib.ThrowError(lib.BUSINESS_ERROR, "操作异常")
		}
		p := domain.AdminPermissionBase{
			Id:   permissionList[i].Id,
			Code: permissionList[i].Code,
		}
		permissionsBase = append(permissionsBase, p)
	}
	updateMap := map[string]interface{}{
		"AccessPartners": partners,
	}
	if !usersData.IsSuperAdmin() {
		updateMap["Permission"] = permissionsBase
	}
	_ = usersData.Update(updateMap)
	err = userRespository.Edit(&usersData)
	if err != nil {
		e := fmt.Sprintf("更新用户(id=%d)数据失败:%s", usersData.Id, err)
		return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
	}
	err = transactionContext.CommitTransaction()
	return nil
}