package service

import (
	"sort"
	"strconv"
	"time"

	"github.com/linmadan/egglib-go/core/application"
	"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/application/factory"
	"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/application/notify"
	"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/application/staff_assess/command"
	"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/domain"
	"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/infrastructure/dao"
	"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/log"
)

// 定时调用 ,按时下发员工的需要填写的评估
// 根据项目评估的配置,创建员工的评估任务
func (srv StaffAssessServeice) CreateStaffAssessTask(transactionContext application.TransactionContext, param *command.CreateStaffAssessTask) (map[string]interface{}, error) {
	log.Logger.Debug("CreateStaffAssessTask 获取参数", map[string]interface{}{
		"param": param,
	})
	assessTaskRepo := factory.CreateStaffAssessTaskRepository(map[string]interface{}{"transactionContext": transactionContext})

	taskBeginTime, err := time.ParseInLocation("2006-01-02 15:04:05", param.BeginTime, time.Local)
	if err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, "任务开始时间填写错误,"+param.BeginTime)
	}
	taskEndTime, err := time.ParseInLocation("2006-01-02 15:04:05", param.EndTime, time.Local)
	if err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, "任务结束时间填写错误,"+param.EndTime)
	}
	nowTime := time.Now()

	assessTaskData := &domain.StaffAssessTask{
		Id:                    0,
		CompanyId:             param.CompanyId,
		EvaluationProjectId:   param.EvaluationProjectId,
		EvaluationProjectName: param.EvaluationProjectName,
		CycleId:               param.CycleId,
		CycleName:             param.CycleName,
		BeginTime:             taskBeginTime,
		EndTime:               taskEndTime,
		StepList:              []domain.AssessTaskStep{},
		ExecutorId:            []int{},
		CreatedAt:             nowTime,
		UpdatedAt:             nowTime,
		DeletedAt:             nil,
		BeginDay:              taskBeginTime.Local().Format("2006-01-02"),
	}
	executorIds := []int{}              //提取评估的参与人id
	executorIdMap := map[int]struct{}{} //过滤重复的用户
	//从入参中提取参与人
	for _, v := range param.ExecutorId {
		if _, ok := executorIdMap[v]; ok {
			continue
		}
		executorIdMap[v] = struct{}{}
		executorIds = append(executorIds, v)
	}
	assessTaskData.ExecutorId = executorIds
	for _, v := range param.StepList {
		stepBeginTime, err := time.ParseInLocation("2006-01-02 15:04:05", param.BeginTime, time.Local)
		if err != nil {
			return nil, application.ThrowError(application.ARG_ERROR, "评估环节开始时间填写错误,"+param.BeginTime)
		}
		stepEndTime, err := time.ParseInLocation("2006-01-02 15:04:05", param.EndTime, time.Local)
		if err != nil {
			return nil, application.ThrowError(application.ARG_ERROR, "评估环节结束时间填写错误,"+param.EndTime)
		}
		step := domain.AssessTaskStep{
			SortBy:       v.SortBy,
			LinkNodeId:   v.LinkNodeId,
			LinkNodeName: v.LinkNodeName,
			LinkNodeType: v.LinkNodeType,
			BeginTime:    stepBeginTime,
			EndTime:      stepEndTime,
		}
		assessTaskData.StepList = append(assessTaskData.StepList, step)
	}
	//添加员工的节点任务
	assessList, err := srv.buildStaffAssess(transactionContext, assessTaskData)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "生成个人评估项"+err.Error())
	}

	//合并项目评估的新旧数据
	_, assassessTaskList, err := assessTaskRepo.Find(map[string]interface{}{
		"evaluationProjectId": param.EvaluationProjectId,
		"beginDay":            taskBeginTime.Local().Format("2006-01-02"),
	})
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "查询同日期同项目已存在的评估任务"+err.Error())
	}

	if len(assassessTaskList) > 0 {
		//旧数据中提取参与人
		for _, v := range assassessTaskList[0].ExecutorId {
			if _, ok := executorIdMap[v]; ok {
				continue
			}
			executorIdMap[v] = struct{}{}
			executorIds = append(executorIds, v)
		}
		assassessTaskList[0].UpdatedAt = time.Now()
		assassessTaskList[0].ExecutorId = executorIds
		//更新步骤
		assassessTaskList[0].StepList = append(assassessTaskList[0].StepList, assessTaskData.StepList...)
		for _, val := range assessTaskData.StepList {
			hasFound := false
			for _, val2 := range assassessTaskList[0].StepList {
				if val.LinkNodeType == val2.LinkNodeType {
					hasFound = true
					break
				}
			}
			if !hasFound {
				assassessTaskList[0].StepList = append(assassessTaskList[0].StepList, val)
			}
		}
		assessTaskData = assassessTaskList[0]
		//排序流程环节
	}
	stepList := domain.SortTaskStep(assessTaskData.StepList)
	sort.Sort(stepList)
	//保存 下发的每日评估
	_, err = assessTaskRepo.Save(assessTaskData)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "保存评估任务"+err.Error())
	}
	//保存 员工的需要填写的每日评估
	assessRepo := factory.CreateStaffAssessRepository(map[string]interface{}{"transactionContext": transactionContext})
	//保存 员工的需要填写的每日任务型 指标项
	taskRecordRepo := factory.CreateTaskRecordRepository(map[string]interface{}{"transactionContext": transactionContext})
	// 保存 员工的需要填写的每日任务型 指标项
	taskDao := dao.NewTaskDao(map[string]interface{}{"transactionContext": transactionContext})
	for i := range assessList {
		assessList[i].StaffAssessTaskId = assessTaskData.Id
		_, err = assessRepo.Save(&assessList[i])
		if err != nil {
			return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "保存个人评估项"+err.Error())
		}
		if assessList[i].Types == domain.AssessSelf {
			//添加待发送的短信通知
			notify.AddNotifyStaffAssess(&assessList[i])
		}

		if assessList[i].Types == domain.AssessSelf {
			//添加 指标任务
			taskRecordList, err := srv.buildTaskRecord(&assessList[i])
			if err != nil {
				return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "构建个人任务型指标项"+err.Error())
			}
			for _, val2 := range taskRecordList {
				_, err := taskRecordRepo.Insert(val2)
				if err != nil {
					return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "保存个人任务型指标项"+err.Error())
				}
				err = taskDao.IncreaseAnomaly([]int{val2.TaskId}, 1)
				if err != nil {
					return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "保存个人任务型指标项"+err.Error())
				}
			}
		}
	}
	return map[string]interface{}{
		"assessTaskId": assessTaskData.Id,
	}, nil
}

// 添加节点任务
func (srv StaffAssessServeice) buildStaffAssess(transactionContext application.TransactionContext, param *domain.StaffAssessTask) ([]domain.StaffAssess, error) {
	selfUserId := []int{}           //评估的参与人
	userIdMap := map[int]struct{}{} //过滤重复的用户
	for _, v := range param.ExecutorId {
		if _, ok := userIdMap[v]; ok {
			continue
		}
		selfUserId = append(selfUserId, v)
	}
	// 获取用户的信息
	if len(selfUserId) == 0 {
		log.Logger.Error("createStaffAssess", map[string]interface{}{
			"param": param,
		})
		return nil, application.ThrowError(application.ARG_ERROR, "未填写评估任务的执行人")
	}
	userRepo := factory.CreateUserRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	//获取员工信息
	_, userList, err := userRepo.Find(map[string]interface{}{
		"ids":    selfUserId,
		"status": 1,
	})
	if err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, "获取员工信息"+err.Error())
	}
	departmentRepo := factory.CreateDepartmentRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	//获取用户的部门
	userDepartmentMap := map[int64][]*domain.Department{}
	for _, v := range userList {
		if len(v.DepartmentId) == 0 {
			continue
		}
		_, departmemtList, err := departmentRepo.Find(map[string]interface{}{
			"ids": v.DepartmentId,
		})
		if err != nil {
			return nil, application.ThrowError(application.ARG_ERROR, "获取员工的部门信息"+err.Error())
		}
		userDepartmentMap[v.Id] = departmemtList
	}
	assessList := []domain.StaffAssess{}
	//数据样板
	stepSelfTemp := domain.StaffAssess{
		Id:                    0,
		CompanyId:             param.CompanyId,
		EvaluationProjectId:   param.EvaluationProjectId,
		EvaluationProjectName: param.EvaluationProjectName,
		CycleId:               param.CycleId,
		CycleName:             param.CycleName,
		StaffAssessTaskId:     param.Id,
		// TargetUser:            domain.StaffDesc{},
		// TargetDepartment:      nil,
		// Executor:              domain.StaffDesc{},
		Types: "",
		// LinkNodeId: v.LinkNodeId,
		Status: domain.StaffAssessUncompleted,
		// BeginTime:  time.Time{},
		// EndTime:    time.Time{},
		CreatedAt: param.CreatedAt,
		UpdatedAt: param.UpdatedAt,
		DeletedAt: nil,
	}
	for _, v := range param.StepList {
		if v.LinkNodeType == domain.LinkNodeSelfAssessment {
			//员工自评
			stepSelfTemp.BeginTime = v.BeginTime
			stepSelfTemp.EndTime = v.EndTime
			stepSelfTemp.LinkNodeId = v.LinkNodeId
			stepSelfTemp.LinkNodeName = v.LinkNodeName
			stepSelfTemp.Types = domain.AssessSelf
			assessListTemp, err := srv.buildStaffAssessSelf(stepSelfTemp, userList, userDepartmentMap)
			if err != nil {
				return nil, err
			}
			assessList = append(assessList, assessListTemp...)
		}
		if v.LinkNodeType == domain.LinkNodeSuperiorAssessment {
			// 创建上级评估
			stepSelfTemp.BeginTime = v.BeginTime
			stepSelfTemp.EndTime = v.EndTime
			stepSelfTemp.LinkNodeId = v.LinkNodeId
			stepSelfTemp.LinkNodeName = v.LinkNodeName
			stepSelfTemp.Types = domain.AssessSuper
			assessListTemp2, err := srv.buildStaffAssessSupper(stepSelfTemp, userList, userDepartmentMap)
			if err != nil {
				return nil, err
			}
			assessList = append(assessList, assessListTemp2...)
		}
	}
	return assessList, nil
}

// 构建员工自评
func (srv StaffAssessServeice) buildStaffAssessSelf(
	assessTemp domain.StaffAssess,
	userList []*domain.User,
	userDepartmentMap map[int64][]*domain.Department) ([]domain.StaffAssess, 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()
	}()

	assessRepo := factory.CreateStaffAssessRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	beginDay := assessTemp.BeginTime.Local().Format("2006-01-02")
	_, assessListOld, err := assessRepo.Find(map[string]interface{}{"cycleId": assessTemp.CycleId, "beginDay": beginDay, "types": domain.AssessSelf})
	if err != nil {
		return nil, err
	}
	userMapReal := map[int]*domain.User{}
	for _, val := range userList {
		userMapReal[int(val.Id)] = val
	}
	for _, val := range assessListOld {
		delete(userMapReal, val.TargetUser.UserId)
	}
	assessListNew := []domain.StaffAssess{}
	for _, usr := range userMapReal {
		assessTemp.TargetUser = domain.StaffDesc{
			UserId:   int(usr.Id),
			Account:  usr.Account,
			UserName: usr.Name,
		}
		assessTemp.Executor = domain.StaffDesc{
			UserId:   int(usr.Id),
			Account:  usr.Account,
			UserName: usr.Name,
		}
		if depList, ok := userDepartmentMap[usr.Id]; ok {
			for _, dep := range depList {
				assessTemp.TargetDepartment = append(assessTemp.TargetDepartment, domain.StaffDepartment{
					DepartmentId:   int(dep.Id),
					DepartmentName: dep.Name,
				})
			}
		}
		assessListNew = append(assessListNew, assessTemp)
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	return assessListNew, nil
}

// 构建员工的上级评估
func (srv StaffAssessServeice) buildStaffAssessSupper(
	assessTemp domain.StaffAssess,
	userList []*domain.User,
	userDepartmentMap map[int64][]*domain.Department,
) ([]domain.StaffAssess, 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()
	}()
	assessRepo := factory.CreateStaffAssessRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	beginDay := assessTemp.BeginTime.Local().Format("2006-01-02")
	_, assessListOld, err := assessRepo.Find(map[string]interface{}{"cycleId": assessTemp.CycleId, "beginDay": beginDay, "types": domain.AssessSuper})
	if err != nil {
		return nil, err
	}
	userMapReal := map[int]*domain.User{}
	for _, val := range userList {
		userMapReal[int(val.Id)] = val
	}
	for _, val := range assessListOld {
		delete(userMapReal, val.TargetUser.UserId)
	}

	var assessListNew []domain.StaffAssess
	for _, v := range userMapReal {
		//获取上级
		chargeUserList, err := srv.getStaffSuper(transactionContext, *v)
		if err != nil {
			return nil, err
		}
		if len(chargeUserList) == 0 {
			continue
		}
		for _, v2 := range chargeUserList {
			assessTemp.TargetUser = domain.StaffDesc{
				UserId:   int(v.Id),
				Account:  v.Account,
				UserName: v.Name,
			}
			assessTemp.Executor = domain.StaffDesc{
				UserId:   int(v2.Id),
				Account:  v2.Account,
				UserName: v2.Name,
			}
			targetDepartment := []domain.StaffDepartment{}
			if departmentList, ok := userDepartmentMap[v.Id]; ok {
				for _, department := range departmentList {
					targetDepartment = append(targetDepartment, domain.StaffDepartment{
						DepartmentId:   int(department.Id),
						DepartmentName: department.Name,
					})
				}
			}
			assessTemp.TargetDepartment = targetDepartment
			assessListNew = append(assessListNew, assessTemp)
		}
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	return assessListNew, nil
}

// 按照评估模板中指标类型,创建里程碑任务
// staffAssess 每日自评评估
func (srv StaffAssessServeice) buildTaskRecord(staffAssess *domain.StaffAssess) ([]*domain.TaskRecord, 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()
	}()
	projectRepo := factory.CreateEvaluationProjectRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	itemUsedRepo := factory.CreateEvaluationItemUsedRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	taskRepo := factory.CreateTaskRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	taskStageRepo := factory.CreateTaskStageRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	})

	projectData, err := projectRepo.FindOne(map[string]interface{}{"id": staffAssess.EvaluationProjectId})
	if err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, "获取项目EvaluationProject信息"+err.Error())
	}

	// projectData.PrincipalId
	userIdstr := strconv.Itoa(staffAssess.Executor.UserId)
	if projectData.PrincipalId != userIdstr {
		return nil, nil
	}
	// 获取指标为任务类型的评估项
	_, evaluationItemList, err := itemUsedRepo.Find(map[string]interface{}{
		"indicatorType":       domain.IndicatorTypeTask,
		"evaluationProjectId": projectData.Id,
	})

	if err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, "获取评估项EvaluationItemUsed信息"+err.Error())
	}
	if len(evaluationItemList) == 0 {
		return nil, nil
	}
	taskRecordList := []*domain.TaskRecord{}
	for _, val := range evaluationItemList {
		_, taskList, err := taskRepo.Find(map[string]interface{}{
			"name":     val.Name,
			"leaderId": projectData.PrincipalId,
		})
		if err != nil {
			return nil, application.ThrowError(application.ARG_ERROR, "获取评估项指标任务task信息"+err.Error())
		}
		if len(taskList) == 0 {
			continue
		}
		//获取里程碑数据
		_, taskStageList, err := taskStageRepo.Find(map[string]interface{}{
			"taskId": taskList[0].Id,
		})
		if err != nil {
			return nil, application.ThrowError(application.ARG_ERROR, "获取评估项指标任务里程碑TaskStage信息"+err.Error())
		}
		newTaskRecord := domain.TaskRecord{
			Id:             0,
			CompanyId:      staffAssess.CompanyId,
			StaffAssessId:  staffAssess.Id,
			TaskId:         taskList[0].Id,
			TaskCategory:   val.Category,
			TaskName:       taskList[0].Name,
			TaskAlias:      taskList[0].Alias,
			TaskLeader:     taskList[0].Leader,
			AssistLevel:    0,
			AssistContent:  "",
			TaskStages:     []domain.TaskStage{},
			TaskStageCheck: domain.TaskStage{},
		}
		sort.Slice(taskStageList, func(i, j int) bool {
			return taskStageList[i].SortBy < taskStageList[j].SortBy
		})
		for i2, val2 := range taskStageList {
			newTaskRecord.TaskStages = append(newTaskRecord.TaskStages, *taskStageList[i2])
			if newTaskRecord.TaskStageCheck.Id == 0 {
				//按顺序第一个未完成的里程碑
				if val2.RealCompletedAt <= 0 {
					newTaskRecord.TaskStageCheck = *taskStageList[i2]
				}
			}
		}
		taskRecordList = append(taskRecordList, &newTaskRecord)
	}

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