package com.ruoyi.ibs.draw.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.ibs.draw.domain.dto.grid.*;
import com.ruoyi.ibs.draw.domain.entity.DrawGrid;
import com.ruoyi.ibs.draw.domain.entity.DrawGridCustUserUnbind;
import com.ruoyi.ibs.draw.domain.entity.DrawGridShapeRelate;
import com.ruoyi.ibs.draw.domain.entity.DrawGridUserRelate;
import com.ruoyi.ibs.draw.domain.vo.DrawGridListVO;
import com.ruoyi.ibs.draw.domain.vo.DrawGridVO;
import com.ruoyi.ibs.draw.mapper.*;
import com.ruoyi.ibs.draw.service.DrawGridCustService;
import com.ruoyi.ibs.draw.service.DrawGridService;
import com.ruoyi.ibs.draw.service.DrawShapeService;
import com.ruoyi.ibs.draw.utils.DrawUtils;
import com.ruoyi.ibs.grid.service.GridInfoRedisService;
import com.ruoyi.system.mapper.SysDeptMapper;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.operation.union.UnaryUnionOp;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author 吴凯程
 * @Date 2024/12/25
 **/
@Service
public class DrawGridServiceImpl implements DrawGridService {

    @Resource
    private DrawGridMapper drawGridMapper;

    @Resource
    private DrawShapeMapper drawShapeMapper;

    @Resource
    private DrawGridUserRelateMapper drawGridUserRelateMapper;

    @Resource
    private DrawGridShapeRelateMapper drawGridShapeRelateMapper;

    @Resource
    private DrawShapeService drawShapeService;

    @Resource
    private DrawGridCustService drawGridCustService;

    @Resource
    private SysDeptMapper sysDeptMapper;

    @Resource
    private DrawGridCustUserUnbindMapper drawGridCustUserUnbindMapper;

    @Resource
    private GridInfoRedisService gridInfoRedisService;


    /**
     * @param drawGridAddDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addDrawGrid(DrawGridAddDTO drawGridAddDTO) {
        checkNameValid(drawGridAddDTO.getGridName());
        if (drawShapeService.checkShapeRelate(drawGridAddDTO.getShapeIds())) {
            throw new ServiceException("存在绘制图形已被绑定");
        }
        DrawGrid drawGrid = new DrawGrid();
        BeanUtils.copyProperties(drawGridAddDTO, drawGrid);
        drawGrid.setDeptName(sysDeptMapper.selectDeptNameById(SecurityUtils.getDeptId()));
        drawGridMapper.insert(drawGrid);

        Long gridId = drawGrid.getGridId();

        drawGridAddDTO.getShapeIds().forEach(shapeId -> {
            DrawGridShapeRelate drawGridShapeRelate = new DrawGridShapeRelate();
            drawGridShapeRelate.setLayerId(drawGridAddDTO.getLayerId());
            drawGridShapeRelate.setShapeId(shapeId);
            drawGridShapeRelate.setGridId(gridId);
            drawGridShapeRelateMapper.insert(drawGridShapeRelate);
            drawShapeService.updateShapeRelate(shapeId);
        });

        drawGridAddDTO.getUserRelateDTOList().forEach(userRelateDTO -> {
            DrawGridUserRelate drawGridUserRelate = new DrawGridUserRelate();
            BeanUtils.copyProperties(userRelateDTO, drawGridUserRelate);
            drawGridUserRelate.setGridId(gridId);
            if (userRelateDTO.getRelateDeptType().equals("branch")){
                drawGridUserRelate.setRelateBranchId(userRelateDTO.getRelateDeptId());
                drawGridUserRelate.setRelateBranchName(userRelateDTO.getRelateDeptName());
            }else if (userRelateDTO.getRelateDeptType().equals("outlet")){
                drawGridUserRelate.setRelateOutletId(userRelateDTO.getRelateDeptId());
                drawGridUserRelate.setRelateOutletName(userRelateDTO.getRelateDeptName());
                SysDept sysDept = sysDeptMapper.selectDeptById(userRelateDTO.getRelateDeptId());
                SysDept parentDept = sysDeptMapper.selectDeptById(sysDept.getParentId());
                drawGridUserRelate.setRelateBranchId(parentDept.getDeptId());
                drawGridUserRelate.setRelateBranchName(parentDept.getDeptName());
            }
            drawGridUserRelateMapper.insert(drawGridUserRelate);
        });
        gridInfoRedisService.cleanGridInfo("4");
        return "特色绘制网格创建完成";
    }

    /**
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String editDrawGrid(DrawGridEditDTO drawGridEditDTO) {
        DrawGrid drawGrid = drawGridMapper.selectById(drawGridEditDTO.getGridId());
        if (Objects.isNull(drawGrid)) {
            throw new ServiceException("网格不存在");
        }
        if (Objects.nonNull(drawGridEditDTO.getGridName()) && !drawGrid.getGridName().equals(drawGridEditDTO.getGridName())) {
            checkNameValid(drawGridEditDTO.getGridName());
            drawGrid.setGridName(drawGridEditDTO.getGridName());
        }
        if (Objects.nonNull(drawGridEditDTO.getGridDutyType()) && !drawGrid.getGridDutyType().equals(drawGridEditDTO.getGridDutyType())) {
            drawGrid.setGridDutyType(drawGridEditDTO.getGridDutyType());
        }
        if (Objects.nonNull(drawGridEditDTO.getUserRelateDTOList()) && !drawGridEditDTO.getUserRelateDTOList().isEmpty()) {
            LambdaQueryWrapper<DrawGridUserRelate> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(DrawGridUserRelate::getGridId, drawGridEditDTO.getGridId());
            drawGridUserRelateMapper.delete(queryWrapper);
            drawGridEditDTO.getUserRelateDTOList().forEach(userRelateDTO -> {
                DrawGridUserRelate drawGridUserRelate = new DrawGridUserRelate();
                BeanUtils.copyProperties(userRelateDTO, drawGridUserRelate);
                drawGridUserRelate.setGridId(drawGridEditDTO.getGridId());
                if (userRelateDTO.getRelateDeptType().equals("branch")){
                    drawGridUserRelate.setRelateBranchId(userRelateDTO.getRelateDeptId());
                    drawGridUserRelate.setRelateBranchName(userRelateDTO.getRelateDeptName());
                }else if (userRelateDTO.getRelateDeptType().equals("outlet")){
                    drawGridUserRelate.setRelateOutletId(userRelateDTO.getRelateDeptId());
                    drawGridUserRelate.setRelateOutletName(userRelateDTO.getRelateDeptName());
                    SysDept sysDept = sysDeptMapper.selectDeptById(userRelateDTO.getRelateDeptId());
                    SysDept parentDept = sysDeptMapper.selectDeptById(sysDept.getParentId());
                    drawGridUserRelate.setRelateBranchId(parentDept.getDeptId());
                    drawGridUserRelate.setRelateBranchName(parentDept.getDeptName());
                }
                drawGridUserRelateMapper.insert(drawGridUserRelate);
            });
        }
        if (Objects.nonNull(drawGridEditDTO.getDeleteShapeIds()) && !drawGridEditDTO.getDeleteShapeIds().isEmpty()) {
            LambdaQueryWrapper<DrawGridShapeRelate> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(DrawGridShapeRelate::getGridId, drawGridEditDTO.getGridId())
                    .in(DrawGridShapeRelate::getShapeId, drawGridEditDTO.getDeleteShapeIds());
            List<DrawGridShapeRelate> drawGridShapeRelates = drawGridShapeRelateMapper.selectList(queryWrapper);
            for (DrawGridShapeRelate drawGridShapeRelate : drawGridShapeRelates) {
                drawShapeService.updateShapeRelate(drawGridShapeRelate.getShapeId());
                drawGridShapeRelateMapper.deleteById(drawGridShapeRelate);
            }
        }
        if (Objects.nonNull(drawGridEditDTO.getAddShapeIds()) && !drawGridEditDTO.getAddShapeIds().isEmpty()) {
            drawShapeService.checkShapeRelate(drawGridEditDTO.getAddShapeIds());
            drawGridEditDTO.getAddShapeIds().forEach(shapeId -> {
                DrawGridShapeRelate drawGridShapeRelate = new DrawGridShapeRelate();
                drawGridShapeRelate.setLayerId(drawGrid.getLayerId());
                drawGridShapeRelate.setShapeId(shapeId);
                drawGridShapeRelate.setGridId(drawGridEditDTO.getGridId());
                drawGridShapeRelateMapper.insert(drawGridShapeRelate);
                drawShapeService.updateShapeRelate(shapeId);
            });
        }
        drawGridMapper.updateById(drawGrid);
        return "特色网格更新成功";
    }

    /**
     * @param gridId
     * @return
     */
    @Override
    public DrawGridVO getDrawGrid(Long gridId) {
        DrawGrid drawGrid = drawGridMapper.selectById(gridId);
        if (Objects.isNull(drawGrid)) {
            throw new ServiceException("网格不存在");
        }
        DrawGridVO drawGridVO = new DrawGridVO();
        BeanUtils.copyProperties(drawGrid, drawGridVO);

        LambdaQueryWrapper<DrawGridShapeRelate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DrawGridShapeRelate::getGridId, gridId);
        List<Long> shapeIds = drawGridShapeRelateMapper.selectList(queryWrapper).stream().map(DrawGridShapeRelate::getShapeId).collect(Collectors.toList());
        drawGridVO.setShapeIds(shapeIds);

        LambdaQueryWrapper<DrawGridUserRelate> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(DrawGridUserRelate::getGridId, gridId);
        List<UserRelateDTO> users = drawGridUserRelateMapper.selectList(queryWrapper1).stream().map(drawGridUserRelate -> {
            UserRelateDTO userRelateDTO = new UserRelateDTO();
            BeanUtils.copyProperties(drawGridUserRelate, userRelateDTO);
            return userRelateDTO;
        }).collect(Collectors.toList());
        drawGridVO.setUserRelateDTOList(users);

        return drawGridVO;
    }

    @Override
    public String deleteDrawGrid(List<Long> gridIds) {
        for (Long gridId : gridIds) {
            DrawGrid drawGrid = drawGridMapper.selectById(gridId);
            if (Objects.isNull(drawGrid)) {
                throw new ServiceException("网格不存在");
            }
            if (!drawGrid.getDeptId().equals(SecurityUtils.getDeptId())) {
                throw new ServiceException("当前用户没有删除权限");
            }
            LambdaQueryWrapper<DrawGridShapeRelate> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(DrawGridShapeRelate::getGridId, gridId);
            List<DrawGridShapeRelate> drawGridShapeRelates = drawGridShapeRelateMapper.selectList(queryWrapper);
            for (DrawGridShapeRelate drawGridShapeRelate : drawGridShapeRelates) {
                drawShapeService.updateShapeRelate(drawGridShapeRelate.getShapeId());
            }
            drawGridShapeRelateMapper.delete(queryWrapper);

            LambdaQueryWrapper<DrawGridUserRelate> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(DrawGridUserRelate::getGridId, gridId);
            drawGridUserRelateMapper.delete(queryWrapper1);

            drawGridMapper.deleteById(gridId);
        }
        return "特色网格成功删除";
    }

    @Override
    public List<DrawGridListVO> getGridList(DrawGridListDTO drawGridListDTO) {
//        switch (SecurityUtils.userRole()) {
//            case "private":
//                drawGridListDTO.setOpsDept("0") ;
//                break;
//            case "public":
//                drawGridListDTO.setOpsDept("1") ;
//                break;
//            case "headOps":
//                drawGridListDTO.setOpsDept("2") ;
//                break;
//        }
        List<DrawGridListVO> gridList;
        drawGridListDTO.setUserName(SecurityUtils.getUsername());
        drawGridListDTO.setDeptId(SecurityUtils.getDeptId());
        if (SecurityUtils.userRole().equals("manager")) {
            gridList = drawGridMapper.getGridListByManager(drawGridListDTO);
        } else {
            gridList = drawGridMapper.getGridList(drawGridListDTO);
        }
        if (!gridList.isEmpty()) {
            gridList.forEach(drawGridListVO -> {
                CustCountDTO custCountByGrid = getCustCountByGrid(drawGridListVO.getGridId());
                drawGridListVO.setRetailCount(custCountByGrid.getRetailCount());
                drawGridListVO.setBusinessCount(custCountByGrid.getBusinessCount());
                drawGridListVO.setMerchantCount(custCountByGrid.getMerchantCount());
                if(drawGridListVO.getOpsDept().equals("0")){
                    drawGridListVO.setBusinessCount(null);
                }
                if(drawGridListVO.getOpsDept().equals("1")){
                    drawGridListVO.setMerchantCount(null);
                    drawGridListVO.setRetailCount(null);
                }

                if(SecurityUtils.getDeptId().equals(drawGridListVO.getDeptId())){
                    if(SecurityUtils.isHead()){
                        drawGridListVO.setIsEdit(drawGridListVO.getOpsDept().equals(SecurityUtils.getOpsDept()));
                    }else if (SecurityUtils.userRole().equals("branch")){
                        drawGridListVO.setIsEdit(Boolean.TRUE);
                    }else{
                        drawGridListVO.setIsEdit(Boolean.FALSE);
                    }
                }else {
                    drawGridListVO.setIsEdit(Boolean.FALSE);
                }

                LambdaQueryWrapper<DrawGridUserRelate> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(DrawGridUserRelate::getGridId, drawGridListVO.getGridId());
                List<DrawGridUserRelate> drawGridUserRelates = drawGridUserRelateMapper.selectList(queryWrapper);
                List<String> branch = new ArrayList<>();
                List<String> outlet = new ArrayList<>();
                List<String> users = new ArrayList<>();
                for (DrawGridUserRelate drawGridUserRelate : drawGridUserRelates) {
                    if (!drawGridUserRelate.getRelateDeptType().equals("outlet")) {
                        if (!branch.contains(drawGridUserRelate.getRelateDeptName())) {
                            branch.add(drawGridUserRelate.getRelateDeptName());
                        }
                    } else {
                        if (!outlet.contains(drawGridUserRelate.getRelateDeptName())) {
                            outlet.add(drawGridUserRelate.getRelateDeptName());
                            SysDept sysDept = sysDeptMapper.selectDeptById(drawGridUserRelate.getRelateDeptId());
                            if (!branch.contains(sysDept.getParentName())) {
                                branch.add(sysDept.getParentName());
                            }
                        }
                    }
                    if (!users.contains(drawGridUserRelate.getNickName())) {
                        users.add(drawGridUserRelate.getNickName() + "-" + drawGridUserRelate.getUserName());
                    }
                }
                if (!branch.isEmpty()) {
                    String collect = branch.stream().collect(Collectors.joining(","));
                    drawGridListVO.setBranchNames(collect);
                }
                if (!outlet.isEmpty()) {
                    String collect = outlet.stream().collect(Collectors.joining(","));
                    drawGridListVO.setOutletNames(collect);
                }
                if (!users.isEmpty()) {
                    String collect = users.stream().collect(Collectors.joining(","));
                    drawGridListVO.setUserNames(collect);
                }

                LambdaQueryWrapper<DrawGridShapeRelate> shapeWrapper = new LambdaQueryWrapper<>();
                shapeWrapper.eq(DrawGridShapeRelate::getGridId, drawGridListVO.getGridId());
                List<Long> shapeIds = drawGridShapeRelateMapper.selectList(shapeWrapper).stream().map(DrawGridShapeRelate::getShapeId).collect(Collectors.toList());
                if (shapeIds.isEmpty()) {
                    throw new ServiceException("特色网格加载错误");
                }
                List<Geometry> geoList = drawShapeMapper.selectBatchIds(shapeIds).stream()
                        .map(drawShape -> DrawUtils.parseWkt(drawShape.getShapeWkt()))
                        .collect(Collectors.toList());
                Geometry geometry = UnaryUnionOp.union(geoList);
                drawGridListVO.setWkt(DrawUtils.transferWKT(geometry));
            });
        }
        return gridList;
    }

    @Override
    public List<DrawGridListVO> getSimpleGridList(DrawGridListDTO drawGridListDTO) {
        if (SecurityUtils.userRole().equals("manager")) {
            return drawGridMapper.getGridListByManager(drawGridListDTO);
        } else {
            return drawGridMapper.getGridList(drawGridListDTO);
        }
    }

    private CustCountDTO getCustCountByGrid(Long gridId) {
        CustCountDTO custCountDTO = new CustCountDTO();
        LambdaQueryWrapper<DrawGridShapeRelate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DrawGridShapeRelate::getGridId, gridId);
        List<CustCountDTO> collect = drawGridShapeRelateMapper.selectList(queryWrapper).stream()
                .map(drawGridShapeRelate -> drawGridCustService.countCustByShape(drawGridShapeRelate.getShapeId()))
                .collect(Collectors.toList());
        custCountDTO.accumulate(collect);
        if (SecurityUtils.userRole().equals("manager")) {
            LambdaQueryWrapper<DrawGridCustUserUnbind> retailWrapper = new LambdaQueryWrapper<>();
            retailWrapper.eq(DrawGridCustUserUnbind::getGridId, gridId)
                    .eq(DrawGridCustUserUnbind::getCustType, "0");
            custCountDTO.setRetailCount(custCountDTO.getRetailCount() - drawGridCustUserUnbindMapper.selectCount(retailWrapper));

            LambdaQueryWrapper<DrawGridCustUserUnbind> merchantWrapper = new LambdaQueryWrapper<>();
            merchantWrapper.eq(DrawGridCustUserUnbind::getGridId, gridId)
                    .eq(DrawGridCustUserUnbind::getCustType, "1");
            custCountDTO.setMerchantCount(custCountDTO.getMerchantCount() - drawGridCustUserUnbindMapper.selectCount(merchantWrapper));

            LambdaQueryWrapper<DrawGridCustUserUnbind> businessWrapper = new LambdaQueryWrapper<>();
            businessWrapper.eq(DrawGridCustUserUnbind::getGridId, gridId)
                    .eq(DrawGridCustUserUnbind::getCustType, "2");
            custCountDTO.setBusinessCount(custCountDTO.getBusinessCount() - drawGridCustUserUnbindMapper.selectCount(businessWrapper));
        }
        return custCountDTO;
    }

    private void checkNameValid(String gridName) {
        LambdaQueryWrapper<DrawGrid> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DrawGrid::getDeptId, SecurityUtils.getDeptId()).eq(DrawGrid::getGridName, gridName);
        if (drawGridMapper.selectCount(queryWrapper) > 0) {
            throw new ServiceException("该网格名称已存在");
        }
    }

}
