package service

import (
	"fmt"
	"github.com/linmadan/egglib-go/core/application"
	"github.com/linmadan/egglib-go/utils/tool_funs"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/factory"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/org/command"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/org/query"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/utils"
	"time"
)

// 组织管理
type OrgService struct {
}

// 批量添加用户
func (orgService *OrgService) BatchAdd(batchAddCommand *command.BatchAddCommand) (interface{}, error) {
	if err := batchAddCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	batchAddOrgService, _ := factory.CreatePgBatchAddOrgService(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	if err = batchAddOrgService.BatchAddOrg(batchAddCommand.OperateInfo, batchAddCommand.OrgList); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}

	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return struct{}{}, nil
}

// 创建组织
func (orgService *OrgService) CreateOrg(createOrgCommand *command.CreateOrgCommand) (interface{}, error) {
	if err := createOrgCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	newOrg := &domain.Org{
		CompanyId: createOrgCommand.CompanyId,
		OrgCode:   createOrgCommand.OrgCode,
		OrgName:   createOrgCommand.OrgName,
		IsOrg:     createOrgCommand.IsOrg,
		ParentId:  createOrgCommand.ParentId,
		OrgStatus: domain.OrgStatusEnable,
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
		Ext:       &domain.Ext{},
	}
	var org *domain.Org
	if createOrgService, err := factory.CreatePgCreateOrgService(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	} else {
		if org, err = createOrgService.CreateOrg(nil, newOrg); err != nil {
			return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
		}
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return org, nil
}

// 设置组织启用状态
func (orgService *OrgService) EnableOrg(enableOrgCommand *command.EnableOrgCommand) (interface{}, error) {
	if err := enableOrgCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	orgRepository, org, err := factory.FastPgOrg(transactionContext, enableOrgCommand.OrgId)
	if err != nil {
		return nil, err
	}
	if err = org.SetOrgStatus(enableOrgCommand.OrgStatus); err != nil {
		return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
	}
	if org, err = orgRepository.Save(org); err != nil {
		return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return org, nil
}

// 返回组织
func (orgService *OrgService) GetOrg(getOrgQuery *query.GetOrgQuery) (interface{}, error) {
	if err := getOrgQuery.ValidateQuery(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	var orgRepository domain.OrgRepository
	if value, err := factory.CreateOrgRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	} else {
		orgRepository = value
	}
	org, err := orgRepository.FindOne(map[string]interface{}{"orgId": getOrgQuery.OrgId})
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	if org == nil {
		return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(getOrgQuery.OrgId)))
	} else {
		if err := transactionContext.CommitTransaction(); err != nil {
			return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
		}
		return org, nil
	}
}

// 获取组织的子部门(通用部门列表使用)
func (orgService *OrgService) GetOrgSubDepartment(getOrgSubDepartmentQuery *query.GetOrgSubDepartmentQuery) (interface{}, error) {
	if err := getOrgSubDepartmentQuery.ValidateQuery(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	orgRepository, org, err := factory.FastPgOrg(transactionContext, getOrgSubDepartmentQuery.OrgId)
	if err != nil {
		return nil, err
	}
	_, orgs, err := orgRepository.Find(map[string]interface{}{"companyId": org.CompanyId, "limit": 1000})
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	var treeNodes = make([]domain.TreeNode, len(orgs))
	for i := 0; i < len(orgs); i++ {
		treeNodes[i] = orgs[i]
	}
	tree := domain.NewTrees(treeNodes)
	nodes := tree.AllSubDepartment(org)
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return map[string]interface{}{
		"orgs": nodes,
	}, nil
}

// 返回组织列表
func (orgService *OrgService) ListOrg(listOrgQuery *query.ListOrgQuery) (interface{}, error) {
	if err := listOrgQuery.ValidateQuery(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	var orgRepository domain.OrgRepository
	if value, err := factory.CreateOrgRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	} else {
		orgRepository = value
	}
	if count, orgs, err := orgRepository.Find(utils.ObjectToMap(listOrgQuery)); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	} else {
		if err := transactionContext.CommitTransaction(); err != nil {
			return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
		}
		return map[string]interface{}{
			"count": count,
			"orgs":  orgs,
		}, nil
	}
}

// 移除组织
func (orgService *OrgService) RemoveOrg(removeOrgCommand *command.RemoveOrgCommand) (interface{}, error) {
	if err := removeOrgCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	var orgRepository domain.OrgRepository
	if value, err := factory.CreateOrgRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	} else {
		orgRepository = value
	}
	org, err := orgRepository.FindOne(map[string]interface{}{"orgId": removeOrgCommand.OrgId})
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	if org == nil {
		return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(removeOrgCommand.OrgId)))
	}

	// 存在下级部门

	if org, err := orgRepository.Remove(org); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	} else {
		if err := transactionContext.CommitTransaction(); err != nil {
			return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
		}
		return org, nil
	}
}

// 更新组织
func (orgService *OrgService) UpdateOrg(updateOrgCommand *command.UpdateOrgCommand) (interface{}, error) {
	if err := updateOrgCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	orgRepository, org, err := factory.FastPgOrg(transactionContext, updateOrgCommand.OrgId)
	if err != nil {
		return nil, err
	}

	//判断当前组织内是否唯一 组织编码、组织名称
	if org.OrgName != updateOrgCommand.OrgName {
		if findOne, err := orgRepository.FindOne(map[string]interface{}{"companyId": updateOrgCommand.OperateInfo.GetCompanyId(org.CompanyId), "parentId": updateOrgCommand.ParentId, "orgName": updateOrgCommand.OrgName, "notEqualOrgId": org.OrgId}); err == nil && findOne != nil {
			return nil, application.ThrowError(application.BUSINESS_ERROR, "部门名称重复")
		}
	}
	if org.OrgCode != updateOrgCommand.OrgCode {
		if findOne, err := orgRepository.FindOne(map[string]interface{}{"companyId": updateOrgCommand.OperateInfo.GetCompanyId(org.CompanyId), "parentId": updateOrgCommand.ParentId, "orgCode": updateOrgCommand.OrgCode, "notEqualOrgId": org.OrgId}); err == nil && findOne != nil {
			return nil, application.ThrowError(application.BUSINESS_ERROR, "部门编码重复")
		}
	}
	if err := org.Update(tool_funs.SimpleStructToMap(updateOrgCommand)); err != nil {
		return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
	}
	//上级组织
	if updateOrgCommand.ParentId != 0 {
		_, parentOrg, err := factory.FastPgOrg(transactionContext, updateOrgCommand.ParentId)
		if err != nil {
			return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
		}
		org.Ext.ParentDepName = parentOrg.OrgName
	}
	if org, err = orgRepository.Save(org); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return org, nil
}

func NewOrgService(options map[string]interface{}) *OrgService {
	newOrgService := &OrgService{}
	return newOrgService
}