package service

import (
	"github.com/tiptok/gocomm/common"
	"github.com/tiptok/gocomm/pkg/log"
	"gitlab.fjmaimaimai.com/mmm-go/godevp/pkg/application/factory"
	"gitlab.fjmaimaimai.com/mmm-go/godevp/pkg/application/role/command"
	"gitlab.fjmaimaimai.com/mmm-go/godevp/pkg/application/role/query"
	"gitlab.fjmaimaimai.com/mmm-go/godevp/pkg/domain"
	"gitlab.fjmaimaimai.com/mmm-go/godevp/pkg/infrastructure/utils"
	"gitlab.fjmaimaimai.com/mmm-go/godevp/pkg/protocol"
	"time"
)

type RoleService struct {
}

func (svr *RoleService) CreateRole(header *protocol.RequestHeader, request *command.CreateRoleRequest) (rsp interface{}, err error) {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
	)
	rsp = &command.CreateRoleResponse{}
	if err = request.ValidateCommand(); err != nil {
		err = protocol.NewCustomMessage(2, err.Error())
	}
	if err = transactionContext.StartTransaction(); err != nil {
		log.Error(err)
		return nil, err
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	newRole := &domain.Role{
		RoleName:   request.RoleName,
		ParentId:   request.ParentId,
		CreateTime: time.Now(),
		UpdateTime: time.Now(),
	}

	var RoleRepository, _ = factory.CreateRoleRepository(transactionContext)
	if request.ParentId > 0 {
		if role, e := RoleRepository.FindOne(map[string]interface{}{"id": request.ParentId}); e != nil || role == nil {
			err = protocol.NewCustomMessage(1, "父角色不存在")
			return
		}
	}
	if m, err := RoleRepository.Save(newRole); err != nil {
		return nil, err
	} else {
		rsp = utils.LoadCustomField(m, "Id", "RoleName", "ParentId")
	}
	err = transactionContext.CommitTransaction()
	return
}

func (svr *RoleService) UpdateRole(header *protocol.RequestHeader, request *command.UpdateRoleRequest) (rsp interface{}, err error) {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
	)
	rsp = &command.UpdateRoleResponse{}
	if err = request.ValidateCommand(); err != nil {
		err = protocol.NewCustomMessage(2, err.Error())
		return
	}
	if err = transactionContext.StartTransaction(); err != nil {
		log.Error(err)
		return nil, err
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	var RoleRepository, _ = factory.CreateRoleRepository(transactionContext)
	var role *domain.Role
	if role, err = RoleRepository.FindOne(common.ObjectToMap(request)); err != nil {
		return
	}
	if role.Id == request.ParentId {
		err = protocol.NewCustomMessage(1, "父角色不能设为自己")
		return
	}
	if request.ParentId > 0 {
		if role, e := RoleRepository.FindOne(map[string]interface{}{"id": request.ParentId}); e != nil || role == nil {
			err = protocol.NewCustomMessage(1, "父角色不存在")
			return
		}
	}
	if err = role.Update(map[string]interface{}{"roleName": request.RoleName, "parentId": request.ParentId}); err != nil {
		return
	}
	if role, err = RoleRepository.Save(role); err != nil {
		return
	}
	err = transactionContext.CommitTransaction()
	return
}

func (svr *RoleService) GetRole(header *protocol.RequestHeader, request *query.GetRoleRequest) (rsp interface{}, err error) {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
	)
	transactionContext.SetTransactionClose()
	rsp = &query.GetRoleResponse{}
	if err = request.ValidateCommand(); err != nil {
		err = protocol.NewCustomMessage(2, err.Error())
		return
	}
	if err = transactionContext.StartTransaction(); err != nil {
		log.Error(err)
		return nil, err
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	var RoleRepository, _ = factory.CreateRoleRepository(transactionContext)
	var role *domain.Role
	if role, err = RoleRepository.FindOne(common.ObjectToMap(request)); err != nil {
		return
	}
	rsp = map[string]interface{}{"role": utils.LoadCustomField(role, "Id", "RoleName", "ParentId")}
	err = transactionContext.CommitTransaction()
	return
}

func (svr *RoleService) DeleteRole(header *protocol.RequestHeader, request *command.DeleteRoleRequest) (rsp interface{}, err error) {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
	)
	rsp = &command.DeleteRoleResponse{}
	if err = request.ValidateCommand(); err != nil {
		err = protocol.NewCustomMessage(2, err.Error())
		return
	}
	if err = transactionContext.StartTransaction(); err != nil {
		log.Error(err)
		return nil, err
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	var RoleRepository, _ = factory.CreateRoleRepository(transactionContext)
	var role *domain.Role
	if role, err = RoleRepository.FindOne(common.ObjectToMap(request)); err != nil {
		return
	}
	if count, _, e := RoleRepository.Find(map[string]interface{}{"parentId": role.Id}); e == nil && count > 0 {
		err = protocol.NewCustomMessage(2, "存在子角色,不可删除")
		return
	}
	if role, err = RoleRepository.Remove(role); err != nil {
		return
	}
	rsp = utils.LoadCustomField(role, "Id", "RoleName", "ParentId")
	err = transactionContext.CommitTransaction()
	return
}

func (svr *RoleService) ListRole(header *protocol.RequestHeader, request *query.ListRoleRequest) (rsp interface{}, err error) {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
	)
	rsp = &query.ListRoleResponse{}
	if err = request.ValidateCommand(); err != nil {
		err = protocol.NewCustomMessage(2, err.Error())
	}
	if err = transactionContext.StartTransaction(); err != nil {
		log.Error(err)
		return nil, err
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	var RoleRepository, _ = factory.CreateRoleRepository(transactionContext)
	var role []*domain.Role
	var total int64
	if total, role, err = RoleRepository.Find(map[string]interface{}{"orderById": "DESC"}); err != nil {
		return
	}
	rsp = map[string]interface{}{
		"total": total,
		"list":  utils.LoadCustomField(role, "Id", "RoleName", "ParentId"),
	}
	err = transactionContext.CommitTransaction()
	return
}

func NewRoleService(options map[string]interface{}) *RoleService {
	svr := &RoleService{}
	return svr
}