package com.chinaweal.aiccs.aiccs.market.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chinaweal.aiccs.aiccs.abnormal.entity.EBaseinfo;
import com.chinaweal.aiccs.aiccs.abnormal.service.EBaseinfoService;
import com.chinaweal.aiccs.aiccs.market.ai.AreaSliceClaimAI;
import com.chinaweal.aiccs.aiccs.market.entity.AreaSlice;
import com.chinaweal.aiccs.aiccs.market.entity.BizOwnerAssign;
import com.chinaweal.aiccs.aiccs.market.entity.dto.AssignLogDto;
import com.chinaweal.aiccs.aiccs.market.entity.dto.EBaseInfoAssignDto;
import com.chinaweal.aiccs.aiccs.market.entity.dto.SliceAssignLogDto;
import com.chinaweal.aiccs.aiccs.market.mapper.BizOwnerAssignMapper;
import com.chinaweal.aiccs.aiccs.market.service.AreaSliceService;
import com.chinaweal.aiccs.aiccs.market.service.BizOwnerAssignService;
import com.chinaweal.aiccs.common.constant.PermissionConstant;
import com.chinaweal.aiccs.common.enums.SliceTypeEnums;
import com.chinaweal.aiccs.common.util.StringUtils;
import com.chinaweal.aiccs.org.entity.TUsers;
import com.chinaweal.aiccs.org.service.TUsersService;
import com.chinaweal.aicorg.model.AICUser;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.BaseServiceImpl;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.chinaweal.youfool.framework.springboot.util.AssertUtils;
import com.chinaweal.youfool.framework.sso.util.SSOUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * <p>
 * 业户管理业务记录表 服务实现类
 * </p>
 *
 * @author <a href="https://blog.lroyia.top">lroyia</a>
 * @since 2021-05-05
 */
@Service
@Slf4j
public class BizOwnerAssignServiceImpl extends BaseServiceImpl<BizOwnerAssignMapper, BizOwnerAssign> implements BizOwnerAssignService {

    @Autowired
    private AreaSliceService areaSliceService;
    @Autowired
    private TUsersService usersService;
    @Autowired
    private EBaseinfoService eBaseinfoService;
    @Autowired
    @Lazy
    private AreaSliceClaimAI areaSliceClaimAI;

    @Override
    public IPage<EBaseInfoAssignDto> ownerAssignPage(IPage<EBaseinfo> page, Map<String, Object> params) {
        return baseMapper.ownerAssignPage(page, params);
    }

    @Override
    public List<EBaseInfoAssignDto> ownerAssign(Map<String, Object> params) {
        return baseMapper.ownerAssign(params);
    }

    @Override
    public List<EBaseInfoAssignDto> waitAssignPage(String beginId, int limitSize) {
        return baseMapper.selectWaitAssignPage(beginId, limitSize);
    }

    @Override
    @Transactional
    public BizOwnerAssign areaClaim(String sliceId, String pripid, String operatorId) {
        // 发起认领
        LocalDateTime now = LocalDateTime.now();
        BizOwnerAssign bizOwner = new BizOwnerAssign()
                .setAssignDate(now)
                .setAssignOperator(operatorId)
                .setSliceId(sliceId)
                .setUpdater(operatorId)
                .setUpdateTime(now)
                .setPripid(pripid);
        save(bizOwner);
        AreaSlice areaSlice = areaSliceService.getById(sliceId);
        eBaseinfoService.updateEntAreaSliceInfo(pripid, areaSlice);
        // 认领后清理removeAssignId
        eBaseinfoService.updateById(new EBaseinfo().setPripid(pripid).setAssignId(""));
        return bizOwner;
    }

    @Override
    @Transactional
    public BizOwnerAssign areaClaim(String sliceId, String pripid, String operatorId, String assignType) {
        // 发起认领
        LocalDateTime now = LocalDateTime.now();
        BizOwnerAssign bizOwner = new BizOwnerAssign()
                .setAssignDate(now)
                .setAssignOperator(operatorId)
                .setSliceId(sliceId)
                .setUpdater(operatorId)
                .setUpdateTime(now)
                .setPripid(pripid)
                .setAssignType(assignType);

        save(bizOwner);
        AreaSlice areaSlice = areaSliceService.getById(sliceId);
        eBaseinfoService.updateEntAreaSliceInfo(pripid, areaSlice);
        // 认领后清理removeAssignId
        eBaseinfoService.updateById(new EBaseinfo().setPripid(pripid).setAssignId(""));
        return bizOwner;
    }

    @Override
    public List<BizOwnerAssign> listBySliceId(String sliceId) {
        QueryWrapper<BizOwnerAssign> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(BizOwnerAssign::getSliceId, sliceId).isNull(BizOwnerAssign::getRemType);
        return list(wrapper);
    }

    @Override
    public List<SliceAssignLogDto> listBySliceInfo(String sliceId, String pripid) {
        return baseMapper.listBySliceInfo(sliceId, pripid);
    }

    @Override
    public List<AssignLogDto> listAssignLog(String pripid) {
        AssertUtils.isNotBlank(pripid);

        List<AssignLogDto> result = new ArrayList<>();
        // 查询记录
        List<BizOwnerAssign> list = list(new LambdaQueryWrapper<BizOwnerAssign>()
                .eq(BizOwnerAssign::getPripid, pripid)
                .orderByAsc(BizOwnerAssign::getAssignDate, BizOwnerAssign::getAssignId)
                // 经常会出现时间相同的情况，因此先按时间排序，后按照id排序，id通过雪花算法生成，有递增的特性
        );
        if (CollectionUtils.isEmpty(list)) return result;

        // 查询片区和操作人
        Set<String> sliceIds = new HashSet<>();
        Set<String> operatorIds = new HashSet<>();
        for (BizOwnerAssign each : list) {
            sliceIds.add(each.getSliceId());
            if (StringUtils.isNotBlank(each.getRemOperator())) {
                operatorIds.add(each.getRemOperator());
            }
            if (StringUtils.isNotBlank(each.getAssignOperator())
                    && each.getAssignOperator().equals(AreaSliceClaimAI.OPERATOR)) {
                operatorIds.add(each.getAssignOperator());
            }
        }
        Map<String, AreaSlice> areaSliceMap = new HashMap<>();
        Map<String, TUsers> userMap = new HashMap<>();
        List<AreaSlice> areaSliceList = areaSliceService.listByIds(sliceIds);
        for (AreaSlice each : areaSliceList) {
            areaSliceMap.put(each.getSliceId(), each);
        }
        if (operatorIds.size() > 0) {
            List<TUsers> usersList = usersService.listByIds(operatorIds);
            for (TUsers each : usersList) {
                userMap.put(each.getUserid(), each);
            }
        }

        // 封装查询结果
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
        for (BizOwnerAssign each : list) {
            String sliceName = StringUtils.EMPTY;
            AreaSlice slice = areaSliceMap.get(each.getSliceId());
            if (slice != null) {
                sliceName = slice.getSliceName();
            }
            // 认领记录
            AssignLogDto assign = new AssignLogDto()
                    .setAssignType("认领")
                    .setSliceName(sliceName)
                    .setOperateTime(each.getAssignDate().format(dateTimeFormatter));
            if (AreaSliceClaimAI.OPERATOR.equals(each.getAssignOperator())) {
                assign.setOperator("自动认领");
            } else {
                TUsers users = userMap.get(each.getAssignOperator());
                if (users != null) {
                    assign.setOperator(users.getRealname());
                }
            }
            result.add(assign);

            // 移出记录
            if (StringUtils.isBlank(each.getRemOperator())) {
                continue;
            }
            TUsers users = userMap.get(each.getRemOperator());
            AssignLogDto removeRecord = new AssignLogDto()
                    .setAssignType("退还")
                    .setSliceName(sliceName)
                    .setOperateTime(each.getRemDate().format(dateTimeFormatter));
            if (users != null) {
                removeRecord.setOperator(users.getRealname());
            }
            result.add(removeRecord);
        }

//        result.sort(Comparator.comparing(AssignLogDto::getOperateTime).reversed());

        return result;
    }

    @Override
    public List<AreaSlice> getAssignableSlice(String pripid, AICUser curUser) {
        BizOwnerAssign assignLog = getLatestAssignLog(pripid);
        AreaSlice curSlice = null;
        if (assignLog != null) {
            curSlice = areaSliceService.getById(assignLog.getSliceId());
        }

        Set<String> sliceIdList = new HashSet<>();
        List<AreaSlice> resultList = new ArrayList<>();

        // 如果拥有片管员权限，则查询片管员所管理的范围
        List<AreaSlice> slicePersonAssign = getSlicePersonAssign(curSlice, curUser);
        for (AreaSlice each : slicePersonAssign) {
            sliceIdList.add(each.getSliceId());
            resultList.add(each);
        }

        // 如果拥有所片管员权限，则查询片管员所管理的范围
        List<AreaSlice> slicePlaceAssign = getSlicePlaceAssign(curSlice, curUser);
        for (AreaSlice each : slicePlaceAssign) {
            if (sliceIdList.contains(each.getSliceId())) {
                continue;
            }
            sliceIdList.add(each.getSliceId());
            resultList.add(each);
        }

        // 如果拥有区片管员权限，则查询片管员所管理的范围
        List<AreaSlice> sliceRegionAssign = getSliceRegionAssign(curSlice, curUser);
        for (AreaSlice each : sliceRegionAssign) {
            if (sliceIdList.contains(each.getSliceId())) {
                continue;
            }
            sliceIdList.add(each.getSliceId());
            resultList.add(each);
        }

        resultList.sort(Comparator.comparing(AreaSlice::getSliceType));

        return resultList;
    }

    @Override
    public BizOwnerAssign getLatestAssignLog(String pripid) {
        return baseMapper.selectLatestAssignLog(pripid);
    }

    @Override
    public List<EBaseinfo> selectNoAssignRecordInfo(String beginId, int limitSize, String supOrg) {
        return baseMapper.selectNoAssignRecordInfo(beginId, limitSize, supOrg);
    }

    @Override
    public RestResult<?> assignOwner(String sliceId, String pripid, String assignType) {
        // 数据校验
        AreaSlice areaSlice = areaSliceService.getById(sliceId);
        AssertUtils.isNotNull(areaSlice);
        SliceAssignLogDto assignLog = null;
        List<SliceAssignLogDto> claimLogList = this.listBySliceInfo(null, pripid);
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(claimLogList)) {
            for (SliceAssignLogDto each : claimLogList) {
                if (each.getRemDate() == null) {
                    if (assignLog == null || Integer.parseInt(assignLog.getSliceType()) < Integer.parseInt(each.getSliceType())) {
                        assignLog = each;
                    }
                }
            }
        }
        SliceTypeEnums typeEnums = null;
        if (assignLog != null) {
            typeEnums = SliceTypeEnums.getEnumsByCode(assignLog.getSliceType());
        }
        // 片区是否在范围校验
        if (typeEnums != null && Integer.parseInt(typeEnums.getCode()) >= Integer.parseInt(areaSlice.getSliceType())) {
            if ("2".equals(assignType)) {
                if (areaSlice.getOrgNumber().length() == 6) {//只要是区的就能认领市公共片区，系统中有错误数据，暂时用这个方法处理

                }else {
                    return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR);
                }
            }
        }

        AICUser loginUser = SSOUtil.getUser();
        String operator = loginUser.getPrimaryKey();
        EBaseinfo entity = eBaseinfoService.getById(pripid);
        BizOwnerAssign bizOwnerAssign = null;
        if (SliceTypeEnums.REGION_PUBLIC.getCode().equals(areaSlice.getSliceType())) {
            // 区公共片区认领
            bizOwnerAssign = this.areaClaim(areaSlice.getSliceId(), pripid, operator, assignType);
        } else if (SliceTypeEnums.STATION_PUBLIC.getCode().equals(areaSlice.getSliceType())) {
            // 所公共片区认领
            // 如果认领的父片区id不等于该已认领的区公共片区id，则为错误数据
            if (areaSlice.getPSliceId() == null || assignLog != null
                    && !areaSlice.getPSliceId().equals(assignLog.getSliceId())) {
                if ("2".equals(assignType)) {
                    if (loginUser.getRegionID().length() == 6) {//只要是区的就能认领市公共片区，系统中有错误数据，暂时用这个方法处理

                    }else {
                        return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR);
                    }
                }
            }
            // 区补领
            if (assignLog == null) {
                this.areaClaim(areaSlice.getPSliceId(), pripid, operator);
            }
            bizOwnerAssign = this.areaClaim(areaSlice.getSliceId(), pripid, operator, assignType);
        } else { // 指定片区认领

            if (assignLog == null) {
                AreaSlice pSlice = areaSliceService.getById(areaSlice.getPSliceId());
                // 区公共片区补领
                if (pSlice != null && StringUtils.isNotBlank(pSlice.getPSliceId())) {
                    this.areaClaim(pSlice.getPSliceId(), pripid, operator);
                }
                // 所公共片区补领
                this.areaClaim(areaSlice.getPSliceId(), pripid, operator);
            } else if (!assignLog.getSliceId().equals(areaSlice.getPSliceId())) {
                // 所补领
                this.areaClaim(areaSlice.getPSliceId(), pripid, operator);
            }
            // 操作认领
            //bizOwnerAssign = this.areaClaim(sliceId, pripid, operator, assignType);
            bizOwnerAssign = areaSliceClaimAI.claimToAreaSlice(entity.getAddress(), entity.getPripid(), sliceId, loginUser.getPrimaryKey());
        }

        // 认领后清理removeAssignId
        eBaseinfoService.updateById(new EBaseinfo().setPripid(pripid).setAssignId(""));

        return RestResult.ok(bizOwnerAssign.getAssignId());
    }

    @Override
    public void BatchAssignOwner(String sliceId, List list, String assignType) {
        for (Object pripid:list) {
            assignOwner(sliceId, (String) pripid, assignType);
        }
    }

    @Override
    public List<Map<String, String>> countAssign(String org, String psid, Map<String, Object> param) {
        return baseMapper.countAssign(org, psid, param);
    }

    /**
     * 获取区片管员认领片区范围
     *
     * @param curSlice 当前认领的片区
     * @param curUser  当前用户
     * @return 获取结果
     * @author lroyia
     * @since 2021年12月29日 15:33:48
     */
    private List<AreaSlice> getSliceRegionAssign(AreaSlice curSlice, AICUser curUser) {
        List<AreaSlice> result = new ArrayList<>();
        // 以至少认领过区公共片区，就不需要查区公共片区的范围了
        if(curSlice != null) {
            return result;
        }
        Set<String> permission = curUser.getAicPermissions().keySet();
        // 如果拥有区片管员权限，则查询片管员所管理的范围
        if (permission.contains(PermissionConstant.SLICE_REGION_ASSIGN)) {
//            if (curSlice != null) {
//                // 是否已经在所片管员的范围内
//                if (curSlice.getSliceType().equals("0")) {
//                    List<AreaSlice> list = areaSliceService.list(new LambdaQueryWrapper<AreaSlice>()
//                            .eq(AreaSlice::getPSliceId, curSlice.getSliceId())
//                            .gt(AreaSlice::getSliceType, curSlice.getSliceType()));
//                    result.addAll(list);
//                }
//            } else {
//                List<AreaSlice> list = areaSliceService.list(new LambdaQueryWrapper<AreaSlice>()
//                        .in(AreaSlice::getSliceType, "0", "1"));
//                result.addAll(list);
//            }
            String region = curUser.getRegionID().substring(0, 6);
            List<AreaSlice> list = areaSliceService.list(new LambdaQueryWrapper<AreaSlice>()
                    .eq(AreaSlice::getSliceType, SliceTypeEnums.REGION_PUBLIC.getCode())
                    // 组织架构号不等于440100
                    .likeRight(!"440100".equals(region), AreaSlice::getOrgNumber, region)
            );
            result.addAll(list);
        }
        return result;
    }

    /**
     * 获取所片管员认领片区范围
     *
     * @param curSlice 当前认领的片区
     * @param curUser  当前用户
     * @return 获取结果
     * @author lroyia
     * @since 2021年12月29日 15:33:48
     */
    private List<AreaSlice> getSlicePlaceAssign(AreaSlice curSlice, AICUser curUser) {
        List<AreaSlice> result = new ArrayList<>();
        Set<String> permission = curUser.getAicPermissions().keySet();
        // 如果拥有所片管员权限，则查询片管员所管理的范围
        if (permission.contains(PermissionConstant.SLICE_PLACE_ASSIGN)) {
            if (curSlice != null) {
                // 是否已经在所片管员的范围内
                if (!curSlice.getSliceType().equals(SliceTypeEnums.SPEC_SLICE.getCode())) {
                    String orgNumber = StringUtils.getRegionPrefixStr(curSlice.getOrgNumber());
                    String curUserOrgNumber = StringUtils.getRegionPrefixStr(curUser.getRegionID());
                    String likeRightOrg = null;
                    if (orgNumber.equals(curUserOrgNumber)) {
                        likeRightOrg = orgNumber;
                    } else if (orgNumber.startsWith(curUserOrgNumber)) {
                        likeRightOrg = orgNumber;
                    } else if (curUserOrgNumber.startsWith(orgNumber)) {
                        likeRightOrg = curUserOrgNumber;
                    }
                    if (likeRightOrg != null) {
                        List<AreaSlice> list = areaSliceService.list(new LambdaQueryWrapper<AreaSlice>()
                                .likeRight(AreaSlice::getOrgNumber, likeRightOrg).gt(AreaSlice::getSliceType,
                                        curSlice.getSliceType()));
                        result.addAll(list);
                    }
                }
            } else {
                List<AreaSlice> list = areaSliceService.list(new LambdaQueryWrapper<AreaSlice>()
                        .likeRight(AreaSlice::getOrgNumber, StringUtils.getRegionPrefixStr(curUser.getRegionID()))
                        .in(AreaSlice::getSliceType, SliceTypeEnums.SPEC_SLICE.getCode(), SliceTypeEnums.STATION_PUBLIC.getCode()));
                result.addAll(list);
            }
        }
        return result;
    }

    /**
     * 获取片管员认领片区范围
     *
     * @param curSlice 当前认领的片区
     * @param curUser  当前用户
     * @return 获取结果
     * @author lroyia
     * @since 2021年12月29日 15:33:48
     */
    private List<AreaSlice> getSlicePersonAssign(AreaSlice curSlice, AICUser curUser) {
        List<AreaSlice> result = new ArrayList<>();
        if (curSlice != null) {
            // 是否已经在片管员的范围内
            if (!curSlice.getSliceType().equals(SliceTypeEnums.SPEC_SLICE.getCode())) {
                String orgNumber = StringUtils.getRegionPrefixStr(curSlice.getOrgNumber());
                List<AreaSlice> list = areaSliceService.list(new LambdaQueryWrapper<AreaSlice>()
                        .likeRight(AreaSlice::getOrgNumber, orgNumber)
                        .eq(AreaSlice::getSupervisorId, curUser.getPrimaryKey())
                        .eq(AreaSlice::getSliceType, SliceTypeEnums.SPEC_SLICE.getCode()));
                result.addAll(list);
            }
        } else {
            List<AreaSlice> list = areaSliceService.list(new LambdaQueryWrapper<AreaSlice>()
                    .likeRight(AreaSlice::getOrgNumber, StringUtils.getRegionPrefixStr(curUser.getRegionID()))
                    .eq(AreaSlice::getSliceType, SliceTypeEnums.SPEC_SLICE.getCode()));
            result.addAll(list);
        }
        return result;
    }


}
