/**
 *
 */
package com.sifang.modules.taskdispatch.service;


import com.jfinal.plugin.activerecord.Record;
import com.sifang.modules.sunshine.SystemSetting.dao.CrmPlatformEmpDao;
import com.sifang.modules.sunshine.SystemSetting.utils.BusinessException;
import com.sifang.modules.sys.common.UserUtils;
import com.sifang.modules.sys.common.entity.User;
import com.sifang.modules.sys.common.service.BaseService;
import com.sifang.modules.sys.util.CrmUtils;
import com.sifang.modules.sys.util.LayuiPage;
import com.sifang.modules.taskdispatch.dao.CrmReviewGroupDao;
import com.sifang.modules.taskdispatch.dao.CrmReviewGroupMemberDao;
import com.sifang.modules.taskdispatch.entity.CrmReviewGroup;
import com.sifang.modules.taskdispatch.entity.CrmReviewGroupMember;
import com.sifang.modules.taskdispatch.vo.EditGroupReq;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 保险信息Service
 *
 * @author gaols
 */
@Component
public class CrmReviewGroupService extends BaseService {

    @Autowired
    private CrmReviewGroupDao crmReviewGroupDao;
    @Autowired
    private CrmReviewGroupMemberDao groupMemberDao;
    @Autowired
    CrmReviewGroupMemberService reviewGroupMemberService;
    @Autowired
    CrmPlatformEmpDao platformEmpDao;

    public CrmReviewGroup get(String id) {
        return crmReviewGroupDao.get(id);
    }

    public void listData(LayuiPage<Record> page, Map<String, String> params) {
        crmReviewGroupDao.listData(page, params);
        List<Record> groups = page.getData();
        Map<String, String> queryMemberParams = new HashMap<>();
        queryMemberParams.put("partnerId", params.get("partnerId"));
        List<Record> allMembers = groupMemberDao.listData(null, queryMemberParams);
        Map<String, List<Record>> groupedMembers = allMembers.stream().collect(Collectors.groupingBy(e -> e.getStr("group_id")));
        for (Record group : groups) {
            List<Record> thisGroupMembers = groupedMembers.get(group.getStr("id"));
            if (!CollectionUtils.isEmpty(thisGroupMembers)) {
                String memberJoined = thisGroupMembers.stream().map(e -> e.getStr("name")).collect(Collectors.joining("、"));
                group.set("members", memberJoined);
            }
        }
        crmReviewGroupDao.listDataCount(page, params);
    }

    @Transactional(readOnly = true)
    public List<CrmReviewGroup> allGroups() {
        return crmReviewGroupDao.findAll();
    }

    public void editGroup(EditGroupReq editGroupReq) {
        String groupId = editGroupReq.getGroupId();
        crmReviewGroupDao.getById(groupId);

        Map<String, Integer> orderMap = new HashMap<>();
        List<String> nowEmpIds = editGroupReq.getEmployeeIds();
        int i = 0;
        for (String nowEmpId : nowEmpIds) {
            orderMap.put(nowEmpId, i++);
        }

        boolean tsp1 = false;
        boolean tsp2 = false;
        int hour1 = 0, hour2 = 0, min1 = 0, min2 = 0;
        if (StringUtils.isNotBlank(editGroupReq.getHour1())) {
            tsp1 = true;
            hour1 = Integer.parseInt(editGroupReq.getHour1());
            hour2 = Integer.parseInt(editGroupReq.getHour2());
            min1 = Integer.parseInt(editGroupReq.getMinute1());
            min2 = Integer.parseInt(editGroupReq.getMinute2());
            checkTimeSpan(hour1, min1, hour2, min2, "上午时间段不正确！");
        }
        int hour3 = 0, hour4 = 0, min3 = 0, min4 = 0;
        if (StringUtils.isNotBlank(editGroupReq.getHour3())) {
            tsp2 = true;
            hour3 = Integer.parseInt(editGroupReq.getHour3());
            hour4 = Integer.parseInt(editGroupReq.getHour4());
            min3 = Integer.parseInt(editGroupReq.getMinute3());
            min4 = Integer.parseInt(editGroupReq.getMinute4());
            checkTimeSpan(hour3, min3, hour4, min4, "下午时间段不正确！");
        }
        if (!tsp1 && !tsp2) {
            throw new BusinessException("请至少选择一个时间段！");
        }
        if (tsp1 && tsp2) {
            if (hour3 * 60 + min3 < hour2 * 60 + min2) {
                throw new BusinessException("时间段不能有重叠！");
            }
        }

        List<Record> members = groupMemberDao.findByEmployeeIds(nowEmpIds, editGroupReq.getPartnerId());
        Set<String> otherGroupEmpIds = new HashSet<>();
        for (Record member : members) {
            if (!Objects.equals(member.getStr("group_id"), groupId)) {
                otherGroupEmpIds.add(member.getStr("employee_id"));
            }
        }
        if (!otherGroupEmpIds.isEmpty()) {
            List<Record> employees = platformEmpDao.findByIds(otherGroupEmpIds);
            String conflicts = employees.stream().map(e -> e.getStr("name")).collect(Collectors.joining("、"));
            throw new BusinessException(conflicts + " 已经在其他组中，请确认！");
        }

        Set<String> empIdSet = new HashSet<>(nowEmpIds);
        if (!empIdSet.contains(editGroupReq.getLeaderEmployeeId())) {
            nowEmpIds.add(editGroupReq.getLeaderEmployeeId()); // 组长如果不在组员中，将组长加到组员中
        }

        List<Record> prevGroupMembers = reviewGroupMemberService.groupMembers(groupId);
        List<Set<String>> diffs = diffGroupMembers(prevGroupMembers, nowEmpIds);
        Set<String> addEmps = diffs.get(0);
        Set<String> modEmps = diffs.get(1);
        Set<String> delEmps = diffs.get(2);

        User user = UserUtils.getUser();
        List<CrmReviewGroupMember> groupMembers = new ArrayList<>();
        List<Record> addedEmployees = platformEmpDao.findByIds(addEmps);
        Map<String, Record> empId2EmpMap = addedEmployees.stream().collect(Collectors.toMap(e -> e.getStr("id"), e -> e, (a, b) -> a));
        for (String employeeId : addEmps) {
            Record record = groupMemberDao.findFirstByEmployeeId(employeeId);
            Date signinTime = (record != null ? record.getDate("signin_time") : null);
            Date signoutTime = (record != null ? record.getDate("signout_time") : null);
            CrmReviewGroupMember m = new CrmReviewGroupMember();
            m.setGroupId(groupId);
            m.setEmployeeId(employeeId);
            m.setUserId(empId2EmpMap.get(employeeId).getStr("user_id"));
            m.setLeadership("0");
            m.setPartnerId(editGroupReq.getPartnerId());
            m.setStatus("0");
            m.setCreateBy(user.getId());
            m.setCreator(CrmUtils.getUserXM(user));
            m.setSort(orderMap.getOrDefault(employeeId, 0));
            m.setCreateTime(new Date());
            m.setSigninTime(signinTime);
            m.setSignoutTime(signoutTime);
            groupMembers.add(m);
        }
        String leaderEmpId = editGroupReq.getLeaderEmployeeId();
        groupMemberDao.insert(groupMembers);
        List<Record> modMembers = prevGroupMembers.stream().filter(e -> modEmps.contains(e.getStr("empoyee_id"))).collect(Collectors.toList());
        groupMemberDao.updateSort(modMembers, orderMap, groupId);
        groupMemberDao.deleteByEmployeeIds(delEmps, groupId);
        groupMemberDao.setLeader(leaderEmpId, groupId);

        String worktimeStart1 = null, worktimeEnd1 = null, worktimeStart2 = null, worktimeEnd2 = null;
        if (tsp1) {
            worktimeStart1 = editGroupReq.getHour1() + ":" + editGroupReq.getMinute1();
            worktimeEnd1 = editGroupReq.getHour2() + ":" + editGroupReq.getMinute2();
        }
        if (tsp2) {
            worktimeStart2 = editGroupReq.getHour3() + ":" + editGroupReq.getMinute3();
            worktimeEnd2 = editGroupReq.getHour4() + ":" + editGroupReq.getMinute4();
        }
        crmReviewGroupDao.updateWorkTime(leaderEmpId, worktimeStart1, worktimeEnd1, worktimeStart2, worktimeEnd2, groupId);
    }

    private List<Set<String>> diffGroupMembers(List<Record> prevGroupMembers, List<String> nowEmployeeIds) {
        List<Set<String>> ret = new ArrayList<>();
        Set<String> adds = new HashSet<>();
        Set<String> mods = new HashSet<>();
        Set<String> dels = new HashSet<>();
        ret.add(adds);
        ret.add(mods);
        ret.add(dels);
        Set<String> prevIds = prevGroupMembers.stream().map(e -> e.getStr("employee_id")).collect(Collectors.toSet());

        for (String employeeId : nowEmployeeIds) {
            if (!prevIds.contains(employeeId)) {
                adds.add(employeeId);
            } else {
                mods.add(employeeId);
            }
        }
        for (String prevId : prevIds) {
            if (!nowEmployeeIds.contains(prevId)) {
                dels.add(prevId);
            }
        }
        return ret;
    }

    private void checkTimeSpan(int hour1, int minute1, int hour2, int minute2, String msg) {
        int x = hour1 * 60 + minute1;
        int y = hour2 * 60 + minute2;
        if (y <= x) {
            throw new BusinessException(msg);
        }
    }

}
