package service

import (
	"fmt"
	"time"

	"github.com/linmadan/egglib-go/core/application"
	"github.com/linmadan/egglib-go/utils/tool_funs"
	"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/application/factory"
	roleService "gitlab.fjmaimaimai.com/allied-creation/performance/pkg/application/role"
	"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/application/summary_evaluation/adapter"
	"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/application/summary_evaluation/command"
	"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/domain"
	"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/infrastructure/dao"
)

type SummaryEvaluationService struct {
}

func NewSummaryEvaluationService() *SummaryEvaluationService {
	newService := &SummaryEvaluationService{}
	return newService
}

// GetExecutorCycleList
// 获取评估执行人可用的周期列表
func (srv *SummaryEvaluationService) GetExecutorCycleList(param *command.QueryCycleList) (map[string]interface{}, 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()
	}()
	evaluationDao := dao.NewSummaryEvaluationDao(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	limit := 300
	offset := 0
	if param.PageSize > 0 {
		limit = param.PageSize
	}
	if param.PageNumber > 0 {
		offset = (param.PageNumber - 1) * param.PageSize
	}

	cycleData, err := evaluationDao.GetExecutorCycleList(param.UserId, offset, limit, 0)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "获取周期列表"+err.Error())
	}

	cnt, err := evaluationDao.CountExecutorCycleList(param.UserId, 0)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	cycleList := []adapter.CycleListAdapter{}
	for _, v := range cycleData {
		m := adapter.CycleListAdapter{
			CycleId:   v.CycleId,
			CycleName: v.CycleName,
		}
		cycleList = append(cycleList, m)
	}
	return tool_funs.SimpleWrapGridMap(int64(cnt), cycleList), nil
}

// GetMenu
// 根据周期获取菜单显示
func (srv *SummaryEvaluationService) GetMenu(param *command.QueryMenu) (map[string]interface{}, 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()
	}()
	evaluationRepo := factory.CreateSummaryEvaluationRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})

	//查找我的绩效
	_, selfEvaluation, err := evaluationRepo.Find(map[string]interface{}{
		"types":      int(domain.EvaluationSelf),
		"executorId": param.UserId,
		"limit":      1,
	})
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	//查找360评估,统计未完成的
	cnt360, _, err := evaluationRepo.Find(map[string]interface{}{
		"types":      int(domain.Evaluation360),
		"executorId": param.UserId,
		"limit":      1,
		"status":     string(domain.EvaluationUncompleted),
	})
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	//查询上级评估,统计未完成
	cntSuper, _, err := evaluationRepo.Find(map[string]interface{}{
		"types":      int(domain.EvaluationSelf),
		"executorId": param.UserId,
		"limit":      1,
		"status":     string(domain.EvaluationUncompleted),
	})
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	//查询人资评估,统计未完成
	cntHrbp, _, err := evaluationRepo.Find(map[string]interface{}{
		"types":      int(domain.EvaluationHrbp),
		"executorId": param.UserId,
		"limit":      1,
		"status":     string(domain.EvaluationUncompleted),
	})
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}

	isHrbp, err := roleService.GetHRBP(transactionContext, param.CompanyId, param.UserId)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}

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

	menuList := []adapter.MenuListAdapter{}

	//模块-我的绩效
	menu1 := adapter.MenuListAdapter{
		CycleId:    0,
		NodeName:   "我的绩效",
		StatusName: "",
		Types:      "",
		Child:      []adapter.MenuListAdapter{},
	}
	menu1_1 := adapter.MenuListAdapter{
		CycleId:    param.CycleId,
		NodeName:   "填写综合自评",
		StatusName: "",
		Types:      "填写综合自评",
	}
	menu1_2 := adapter.MenuListAdapter{
		CycleId:    param.CycleId,
		NodeName:   "查看综合自评",
		StatusName: "",
		Types:      "查看综合自评",
	}
	if len(selfEvaluation) > 0 {
		if selfEvaluation[0].Status == domain.EvaluationCompleted {
			menu1_1.StatusName = "已完成"
		} else {
			menu1_1.StatusName = "未完成"
		}
		if selfEvaluation[0].CheckResult == domain.EvaluationCheckCompleted {
			menu1_2.StatusName = "已完成"
		} else {
			menu1_2.StatusName = "未完成"
		}
	}
	menu1.Child = append(menu1.Child, menu1_1, menu1_2)
	menuList = append(menuList, menu1)
	menu2 := adapter.MenuListAdapter{
		CycleId:    0,
		NodeName:   "给他人评估",
		StatusName: "",
		Types:      "",
		Child:      []adapter.MenuListAdapter{},
	}
	menu2_1 := adapter.MenuListAdapter{
		CycleId:    param.CycleId,
		NodeName:   "360综评",
		StatusName: "",
		Types:      "360综评",
	}
	if cnt360 > 0 {
		menu2_1.StatusName = "未完成"
	} else {
		menu2_1.StatusName = "已完成"
	}
	menu2.Child = append(menu2.Child, menu2_1)
	menuList = append(menuList, menu2)
	menu3 := adapter.MenuListAdapter{
		CycleId:    0,
		NodeName:   "人资评估",
		StatusName: "",
		Types:      "",
		Child:      []adapter.MenuListAdapter{},
	}
	menu3_1 := adapter.MenuListAdapter{
		CycleId:    param.CycleId,
		NodeName:   "上级综评",
		StatusName: "",
		Types:      "上级综评",
	}
	if cntHrbp > 0 {
		menu3_1.StatusName = "未完成"
	} else {
		menu3_1.StatusName = "已完成"
	}
	menu3.Child = append(menu3.Child, menu3_1)
	//hrbp 才有这个菜单
	if isHrbp > 0 {
		menuList = append(menuList, menu3)
	}
	menu4 := adapter.MenuListAdapter{
		CycleId:    0,
		NodeName:   "我的团队绩效",
		StatusName: "",
		Types:      "",
		Child:      []adapter.MenuListAdapter{},
	}
	menu4_1 := adapter.MenuListAdapter{
		CycleId:    param.CycleId,
		NodeName:   "上级综评",
		StatusName: "",
		Types:      "上级综评",
	}
	if cntSuper > 0 {
		menu4_1.StatusName = "未完成"
	} else {
		menu4_1.StatusName = "已完成"
	}
	menu4.Child = append(menu4.Child, menu4_1)
	menuList = append(menuList, menu4)
	result := map[string]interface{}{
		"menus": menuList,
	}
	return result, nil
}

// buildSummaryItemValue 将填写值填充进评估项
func (srv *SummaryEvaluationService) buildSummaryItemValue(itemList []*domain.EvaluationItemUsed, valueList []*domain.SummaryEvaluationValue) (itemValues []adapter.EvaluationItemAdapter) {
	itemValues = []adapter.EvaluationItemAdapter{}
	valueMap := map[int]*domain.SummaryEvaluationValue{}
	for _, v := range valueList {
		valueMap[v.EvaluationItemId] = v
	}
	for _, v := range itemList {
		item := adapter.EvaluationItemAdapter{
			EvaluationItemId: v.Id,
			SortBy:           v.SortBy,
			Category:         v.Category,
			Name:             v.Name,
			PromptTitle:      v.PromptTitle,
			PromptText:       v.PromptText,
			EntryItems:       v.EntryItems,
			RuleType:         v.RuleType,
			Rule:             v.Rule,
			Weight:           v.Weight,
			Required:         v.Required,
			Value:            "",
			Score:            "",
			Remark:           "",
		}
		value, ok := valueMap[v.Id]
		if ok {
			item.Score = value.Score
			item.Value = value.Value
			item.Remark = value.Remark
		}
		itemValues = append(itemValues, item)
	}
	return itemValues
}

// 获取综合自评详情
func (srv *SummaryEvaluationService) GetEvaluationSelf(param *command.QueryEvaluation) (*adapter.EvaluationInfoAdapter, 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()
	}()
	evaluationRepo := factory.CreateSummaryEvaluationRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	evaluationItemRepo := factory.CreateEvaluationItemUsedRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	itemValueRepo := factory.CreateSummaryEvaluationValueRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	_, evaluationList, err := evaluationRepo.Find(map[string]interface{}{
		"limit":      1,
		"cycleId":    param.CompanyId,
		"executorId": param.UserId,
		"types":      domain.EvaluationSelf,
	})
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	if len(evaluationList) == 0 {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	evaluationData := evaluationList[0]
	_, itemList, err := evaluationItemRepo.Find(map[string]interface{}{
		"evaluationProjectId": evaluationData.EvaluationProjectId,
		"nodeType":            int(domain.LinkNodeSelfAssessment),
	})
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}

	_, itemValues, err := itemValueRepo.Find(map[string]interface{}{
		"summaryEvaluationId": evaluationData.Id,
	})

	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	result := srv.getSummaryEvaluation(transactionContext, evaluationData)
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}

	itemValuesAdapter := srv.buildSummaryItemValue(itemList, itemValues)
	result.EvaluationItems = itemValuesAdapter
	return result, nil
}

func (srv *SummaryEvaluationService) getSummaryEvaluation(transactionContext application.TransactionContext, evaluationData *domain.SummaryEvaluation) *adapter.EvaluationInfoAdapter {
	result := adapter.EvaluationInfoAdapter{
		SummaryEvaluationId:   evaluationData.Id,
		CycleId:               int(evaluationData.CycleId),
		CycleName:             evaluationData.CycleName,
		EvaluationProjectId:   evaluationData.EvaluationProjectId,
		EvaluationProjectName: evaluationData.EvaluationProjectName,
		LinkNodeId:            evaluationData.NodeId,
		BeginTime:             evaluationData.BeginTime.Format("2006-01-02 15:04:05"),
		EndTime:               evaluationData.EndTime.Format("2006-01-02 15:04:05"),
		TargetUserId:          evaluationData.TargetUser.UserId,
		TargetUserName:        evaluationData.TargetUser.UserName,
		CompanyLogo:           "",
		CompanyName:           "",
		SupperUser:            "",
		DutyTime:              "",
		Status:                string(evaluationData.Status),
		EvaluationItems:       []adapter.EvaluationItemAdapter{},
	}
	//获取用户信息
	companyRepo := factory.CreateCompanyRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	userRepo := factory.CreateUserRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})

	companyData, err := companyRepo.FindOne(map[string]interface{}{
		"id": evaluationData.CompanyId,
	})

	if err != nil {
		return &result
	}

	userData, err := userRepo.FindOne(map[string]interface{}{
		"id": evaluationData.TargetUser.UserId,
	})
	if err != nil {
		return &result
	}
	result.DutyTime = userData.EntryTime
	result.CompanyLogo = companyData.Logo
	result.CompanyName = companyData.Name

	if userData.ParentId <= 0 {
		return &result
	}
	pUserData, err := userRepo.FindOne(map[string]interface{}{
		"id": userData.ParentId,
	})
	if err != nil {
		return &result
	}
	result.SupperUser = pUserData.Name
	return &result
}

// 编辑综合自评详情
func (srv *SummaryEvaluationService) EditEvaluationSelf(param *command.EditEvaluationValue) (map[string][]adapter.EvaluationItemAdapter, 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()
	}()
	evaluationRepo := factory.CreateSummaryEvaluationRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	itemUsedRepo := factory.CreateEvaluationItemUsedRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})

	itemValueRepo := factory.CreateSummaryEvaluationValueRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	evaluationData, err := evaluationRepo.FindOne(map[string]interface{}{
		"id": param.SummaryEvaluationId,
	})
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	if evaluationData.Types != domain.EvaluationSelf {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "没有操作权限")
	}

	if evaluationData.Executor.UserId != param.ExecutorId {

		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "没有操作权限")
	}

	if evaluationData.CompanyId != param.CompanyId {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "没有操作权限")
	}

	_, itemList, err := itemUsedRepo.Find(map[string]interface{}{
		"evaluationProjectId": evaluationData.EvaluationProjectId,
		"nodeType":            domain.LinkNodeSelfAssessment,
	})
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}

	_, itemValueList, err := itemValueRepo.Find(map[string]interface{}{
		"summaryEvaluationId": evaluationData.Id,
	})

	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}

	evaluationValueMap := map[int]*domain.SummaryEvaluationValue{}
	for _, v := range itemList {
		newValue := &domain.SummaryEvaluationValue{}
		newValue.SetBlankValue(evaluationData, v)
		evaluationValueMap[v.Id] = newValue
	}
	for _, v := range itemValueList {
		if mValue, ok := evaluationValueMap[v.EvaluationItemId]; ok {
			mValue.Id = v.Id
		}
	}
	nowTime := time.Now()
	for _, v := range param.EvaluationItems {
		updatedData, ok := evaluationValueMap[v.EvaluationItemId]
		if !ok {
			continue
		}
		updatedData.UpdatedAt = nowTime
		updatedData.Value = v.Value
		updatedData.Remark = v.Remark
		//计算得分
		err = updatedData.SummaryEvaluationScore()
		if err != nil {
			return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
		}
	}

	evaluationValueList := []*domain.SummaryEvaluationValue{}
	for _, v := range evaluationValueMap {
		//保存填写值
		err = itemValueRepo.Save(v)
		if err != nil {
			return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
		}
		evaluationValueList = append(evaluationValueList, v)
	}
	//计算总得分
	err = evaluationData.EvaluationTotalScore(evaluationValueList)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	evaluationData.UpdatedAt = nowTime
	evaluationData.Status = domain.EvaluationCompleted
	//保存填写值
	err = evaluationRepo.Save(evaluationData)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	itemValueAdapter := srv.buildSummaryItemValue(itemList, evaluationValueList)
	return map[string][]adapter.EvaluationItemAdapter{
		"EvaluationItems": itemValueAdapter,
	}, nil
}

// GetTargetUserCycleList
// 获取周期列表,被评估的周期列表
func (srv *SummaryEvaluationService) GetTargetUserCycleList(param *command.QueryCycleList) (map[string]interface{}, 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()
	}()
	evaluationDao := dao.NewSummaryEvaluationDao(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	limit := 300
	offset := 0
	if param.PageSize > 0 {
		limit = param.PageSize
	}
	if param.PageNumber > 0 {
		offset = (param.PageNumber - 1) * param.PageSize
	}

	cycleData, err := evaluationDao.GetTargetUserCycleList(param.UserId, offset, limit, param.Types)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "获取周期列表"+err.Error())
	}

	cnt, err := evaluationDao.CountTargetUserCycleList(param.UserId, param.Types)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	cycleList := []adapter.CycleListAdapter{}
	for _, v := range cycleData {
		m := adapter.CycleListAdapter{
			CycleId:   v.CycleId,
			CycleName: v.CycleName,
		}
		cycleList = append(cycleList, m)
	}
	return tool_funs.SimpleWrapGridMap(int64(cnt), cycleList), nil
}

// 自评小结详情
func (srv *SummaryEvaluationService) CountEvaluationSelfLevel(param *command.QueryEvaluation) (*adapter.EvaluationInfoAdapter, error) {
	evaluationInfo, err := srv.GetEvaluationSelf(param)
	if err != nil {
		return nil, err
	}
	levelCodeMap := map[int][]adapter.LevalCodeCount{}
	for _, v := range evaluationInfo.EvaluationItems {
		codes := v.Rule.GetLevelCodes()
		levelCode := []adapter.LevalCodeCount{}
		for _, v2 := range codes {
			levelCode = append(levelCode, adapter.LevalCodeCount{
				Code:   v2,
				Number: 0,
			})
		}
		levelCodeMap[v.EvaluationItemId] = levelCode
	}
	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()
	}()

	//统计周期内,评估项等级的数量
	assessDao := dao.NewStaffAssessDao(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	levelCodeCountList, err := assessDao.CountAssessContentLevelCode(param.UserId, domain.AssessSelf, param.CycleId)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}

	levelCodeCountMap := map[string]int{}
	for _, v := range levelCodeCountList {
		key := fmt.Sprintf("%s-%s-%s", v.Category, v.Name, v.LevelValue)
		levelCodeCountMap[key] = v.Cnt
	}

	for i := range evaluationInfo.EvaluationItems {
		itemId := evaluationInfo.EvaluationItems[i].EvaluationItemId
		levelCodes, ok := levelCodeMap[itemId]
		if !ok {
			continue
		}
		evaluationInfo.EvaluationItems[i].LevelCount = levelCodes
		for i2 := range levelCodes {
			key := fmt.Sprintf("%s-%s-%s",
				evaluationInfo.EvaluationItems[i].Category,
				evaluationInfo.EvaluationItems[i].Name,
				levelCodes[i2].Code,
			)

			if mVal, ok := levelCodeCountMap[key]; ok {
				levelCodes[i2].Number = mVal
			}
		}
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	return evaluationInfo, nil
}