package com.junmp.jyzb.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.junmp.jyzb.api.bean.dto.CabinetDto;
import com.junmp.jyzb.api.bean.dto.CabinetBoxDto;
import com.junmp.jyzb.api.bean.query.CabinetBoxReq;
import com.junmp.jyzb.api.bean.query.CabinetReq;
import com.junmp.jyzb.api.bean.req.UpdateCabinetBoxReq;
import com.junmp.jyzb.api.bean.req.UpdateCabinetReq;
import com.junmp.jyzb.entity.*;
import com.junmp.jyzb.api.exception.enums.CabinetExceptionEnum;
import com.junmp.jyzb.api.exception.enums.PolicemanExceptionEnum;
import com.junmp.jyzb.mapper.*;
import com.junmp.jyzb.service.*;
import com.junmp.jyzb.utils.*;
import com.junmp.v2.common.exception.base.ServiceException;
import com.junmp.v2.common.util.BeanPlusUtil;
import com.junmp.v2.db.api.factory.PageFactory;
import com.junmp.v2.db.api.factory.PageResultFactory;
import com.junmp.v2.db.api.page.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

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


@Service
public class CabinetServiceImpl extends ServiceImpl<CabinetMapper, Cabinet> implements CabinetService {


    @Resource
    private CabinetMapper cabinetMapper;
    @Resource
    private PubOrgService pubOrgService;
    @Resource
    private CabinetBoxService cabinetBoxService;
    @Resource
    private PolicemanService policemanService;

    @Resource
    private CabinetBoxPoliceService cabinetBoxPoliceService;

    @Resource
    private CabinetBoxPoliceMapper cabinetBoxPoliceMapper;
    @Autowired
    private RabbitMQSendMsg MQ;

    private List<Long> getAllOrgId(CabinetReq req, String includeLowerLevel) {
        List<Long> allOrg = new ArrayList<>();
        if (includeLowerLevel.equals("false")) {
            allOrg.add(req.getOrgId());
        } else if (includeLowerLevel.equals("true")) {
            //查询某组织机构的本级及下级
            allOrg = pubOrgService.getLowerOrg(req.getOrgId());
        }
        return allOrg;
    }

    private List<Cabinet> getAllCabinetByOrg( List<Long> allOrgId) {
        List<Cabinet> allCabinet = new ArrayList<>();
        allCabinet = cabinetMapper.getAllCabinetByOrgList(allOrgId);
        return allCabinet;
    }


    /**
     * 添加单警柜
     *
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String addCabinetInfo(UpdateCabinetReq req) {
        Cabinet cabinet = new Cabinet();
        // 查询传入的组织机构id是否存在
        pubOrgService.PubOrgExist(req.getOrgId());
        // 查询是否有重复的单警柜编号
        List<Cabinet> list = this.list(new LambdaQueryWrapper<Cabinet>()
                .eq(ObjectUtil.isNotEmpty(req.getSerialNum()), Cabinet::getCabinetNum, req.getSerialNum()));
        if (list.size() > 0) {
            // 抛出单警柜重复异常
            throw new ServiceException(CabinetExceptionEnum.CABINETID_IS_EXISTS);
        }
        BeanPlusUtil.copyProperties(req, cabinet);
        cabinet.setCabinetNum(req.getSerialNum());
        cabinet.setNum(req.getCabinetBoxList().size());
        cabinet.setOnlineState(1);//新增后设置离线
        cabinet.setUpdateTime(new Date());
        cabinet.setCreateTime(new Date());
        // 添加或更新单警柜
        save(cabinet);

        // 处理箱门信息
        if (CollectionUtil.isNotEmpty(req.getCabinetBoxList())) {
            List<CabinetBox> boxList = req.getCabinetBoxList().stream()
                    .map(boxReq -> {
                        CabinetBox box = new CabinetBox();
                        box.setCabinetId(cabinet.getId());
                        box.setPower(boxReq.getPower());
                        box.setEquipmentConfig(boxReq.getEquipmentConfig());
                        box.setContainType(boxReq.getContainType());
                        box.setState(0);
                        box.setNum(boxReq.getNum());
                        return box;
                    })
                    .collect(Collectors.toList());
            cabinetBoxService.saveOrUpdateBatch(boxList);
        }

        return cabinet.getId();
    }


    /**
     * 删除单警柜(批量删除)
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteCabinetInfo(UpdateCabinetReq req) {
        //获取传递的id列表
        if (ObjectUtil.isNull(req.getCabinetList()) || req.getCabinetList().size()==0){
            throw new ServiceException(CabinetExceptionEnum.PARAMETER_ERROR);
        }
        List<String> cabinetIdList = req.getCabinetList();
        for (String s:cabinetIdList ) {
            if (s.equals("")){
                throw new ServiceException(CabinetExceptionEnum.PARAMETER_ERROR);
            }
        }
        List<Cabinet> cabinetList=new ArrayList<>();
        //遍历单警柜id列表
        for (String id:cabinetIdList) {
            //通过单警柜id查询出他的箱门数
            Cabinet cabinet = CabinetExist(id);
            //查询出单警柜之后添加到列表中
            cabinetList.add(cabinet);
            //通过单警柜id循环遍历出并删除所有箱门信息
            List<CabinetBox> list = cabinetBoxService.list(new LambdaQueryWrapper<CabinetBox>()
                    .eq(ObjectUtil.isNotEmpty(id), CabinetBox::getCabinetId, id));
            //创建cabinetBox列表方便批量删除操作
            List<CabinetBox> cabinetBoxList=new ArrayList<>();
            for (CabinetBox cabinetBox: list) {
                CabinetBox cabinetBox1 = new CabinetBox();
                BeanPlusUtil.copyProperties(cabinetBox,cabinetBox1);
                cabinetBoxList.add(cabinetBox1);
//
            }
            //批量修改绑定箱门的警员信息，将其解绑
//            cabinetBoxPoliceService.remove(new LambdaQueryWrapper<CabinetBoxPolice>().eq(CabinetBoxPolice::getCabinetId,cabinetIdList));
            //批量删除箱门数
            cabinetBoxService.removeBatchByIds(cabinetBoxList);
            //批量删除单警柜id
            removeBatchByIds(cabinetList);
        }
        return true;
    }

    /**
     * 获取单警柜列表
     *通过机构id进行查询
     * @param req 单警柜信息
     * @param req
     * @return
     */
    @Override
    public List<CabinetDto> getAllCabinetList(CabinetReq req) {
        List<CabinetDto> cabinetList = new ArrayList<>();
        List<Cabinet> list = cabinetMapper.getAllCabinetsWithSingleCabinet(String.valueOf(req.getOrgId()),null);

        if (list.size() == 0) {
            return new ArrayList<>();
        }

        // 使用 Stream API 对数据进行分组和排序
        Map<String, List<Cabinet>> groupedCabinets = list.stream()
                .collect(Collectors.groupingBy(Cabinet::getId));

        groupedCabinets.forEach((id, cabinets) -> {
            // 对每个分组内的数据按照 num 字段升序排序
            List<Cabinet> sortedCabinets = cabinets.stream()
                    .sorted(Comparator.comparingInt(Cabinet::getNumber))
                    .collect(Collectors.toList());

            // 创建 CabinetDto 对象并设置属性
            CabinetDto cabinetDto = new CabinetDto();
            BeanPlusUtil.copyProperties(sortedCabinets.get(0), cabinetDto);
            cabinetDto.setOrgId(sortedCabinets.get(0).getOrgIdInt());
            cabinetDto.setOrgName(sortedCabinets.get(0).getOrgName());
            List<CabinetBoxDto> cabinetBoxList = new ArrayList<>();
            for (Cabinet cabinet : sortedCabinets) {
                // 在 cabinetBoxList 中查找是否已存在相同 id 的 CabinetBoxDto
                Optional<CabinetBoxDto> existingCabinetBox = cabinetBoxList.stream()
                        .filter(box -> box.getId().equals(cabinet.getBoxId()))
                        .findFirst();

                if (existingCabinetBox.isPresent()) {
                    // 如果已存在，则在现有对象的 policeName 和 policeId 字段分别继续拼接
                    CabinetBoxDto cabinetBoxDto = existingCabinetBox.get();
                    String existingPoliceName = cabinetBoxDto.getPoliceName();
                    String existingPoliceId = cabinetBoxDto.getPoliceId();
                    String currentPoliceName = cabinet.getPoliceName();
                    String currentPoliceId = cabinet.getPoliceId();

                    // 拼接 policeName，使用逗号分隔
                    String updatedPoliceName = existingPoliceName + "," + currentPoliceName;
                    cabinetBoxDto.setPoliceName(updatedPoliceName);

                    // 拼接 policeId，使用逗号分隔
                    String updatedPoliceId = existingPoliceId + "," + currentPoliceId;
                    cabinetBoxDto.setPoliceId(updatedPoliceId);

                    // 更新其他属性...
                } else {
                    // 如果不存在，则创建新的对象并添加到 cabinetBoxList 中
                    CabinetBoxDto cabinetBoxDto = new CabinetBoxDto();
                    BeanPlusUtil.copyProperties(cabinet, cabinetBoxDto);
                    cabinetBoxDto.setNum(cabinet.getNumber());
                    cabinetBoxDto.setPoliceId(cabinet.getPoliceId());
                    cabinetBoxDto.setId(cabinet.getBoxId());

                    // 直接拼接 policeName 和 policeId，使用逗号分隔
                    cabinetBoxDto.setPoliceName(cabinet.getPoliceName());
                    cabinetBoxDto.setPoliceId(cabinet.getPoliceId());

                    // 设置其他属性...

                    cabinetBoxList.add(cabinetBoxDto);
                }
            }


            cabinetDto.setCabinetBoxList(cabinetBoxList);
            cabinetList.add(cabinetDto);
        });

        return cabinetList;
    }

    //根据组织机构id查询出单警柜的详细信息(page)
    @Override
    public PageResult<CabinetDto> ShowCabinetPage(CabinetReq req) {
        // 判断组织机构是否存在
        PubOrg pubOrg = pubOrgService.PubOrgExist(req.getOrgId());

        LambdaQueryWrapper<Cabinet> eq = new LambdaQueryWrapper<Cabinet>()
                .eq(Cabinet::getOrgIdInt, req.getOrgId())
                .like(ObjectUtil.isNotNull(req.getName()), Cabinet::getName, req.getName())
                .like(ObjectUtil.isNotNull(req.getServerNum()), Cabinet::getCabinetNum, req.getServerNum());

        // 使用 PageHelper 开始分页
        Page<Cabinet> page = PageFactory.getDefaultPage(req.getPageNo(), req.getPageSize());

        // 执行分页查询
        IPage<Cabinet> cabinetPage = page(page, eq);

        // 获取查询结果列表
        List<Cabinet> records = cabinetPage.getRecords();

        // 将 Cabinet 转换为 CabinetDto
        List<CabinetDto> cabinetList = records.stream()
                .map(cabinet -> {
                    CabinetDto cabinetDto = new CabinetDto();
                    BeanPlusUtil.copyProperties(cabinet, cabinetDto);
                    cabinetDto.setOrgName(pubOrg.getOrgName());
                    return cabinetDto;
                })
                .collect(Collectors.toList());

        // 构造一个新的 Page 对象，将 cabinetPage 的数据拷贝到新的对象中
        Page<CabinetDto> newPage = new Page<>(cabinetPage.getCurrent(), cabinetPage.getSize(), cabinetPage.getTotal());
        newPage.setRecords(cabinetList);

        // 使用新的 Page 对象构造返回的 PageResult 对象
        PageResult<CabinetDto> result = PageResultFactory.createPageResult(newPage);

        return result;
    }

    /**
     * 通过单警柜id查询单个单警柜及其箱门信息
     *
     * @param req
     * @return
     */
    @Override
    public CabinetDto showOneCabinet(CabinetReq req) {
        // 查询单警柜信息
        Cabinet cabinet = CabinetExistByNum(req.getServerNum());

        // 查询单警柜的箱门信息
        List<CabinetBox> list = cabinetBoxService.list(new LambdaQueryWrapper<CabinetBox>()
                .eq(ObjectUtil.isNotEmpty(cabinet.getId()), CabinetBox::getCabinetId, cabinet.getId())
                .eq(ObjectUtil.isNotEmpty(req.getContainType()), CabinetBox::getContainType, req.getContainType())
                .orderByAsc(CabinetBox::getNum));

        List<CabinetBoxDto> boxList = list.stream()
                .map(cabinetBox -> {
                    CabinetBoxDto cabinetBoxDto = new CabinetBoxDto();
                    BeanPlusUtil.copyProperties(cabinetBox, cabinetBoxDto);
                    return cabinetBoxDto;
                })
                .collect(Collectors.toList());

        // 将单警柜的信息和它的箱门信息返回
        CabinetDto cabinetDto = new CabinetDto();
        BeanPlusUtil.copyProperties(cabinet, cabinetDto);
        cabinetDto.setCabinetBoxList(boxList);

        return cabinetDto;
    }

    /**
     * 修改单警柜信息
     * 新增箱数
     * @param req
     * @return
     */
    @Override
    public boolean updateCabinetInfo(UpdateCabinetReq req) {
        //查询传入的组织机构id是否存在
        pubOrgService.PubOrgExist(req.getOrgId());
        Cabinet one = getById(req.getId());
        //查询是否有重复的单警柜编号
        List<Cabinet> list = this.list(new LambdaQueryWrapper<Cabinet>()
                .eq(Cabinet::getCabinetNum,req.getSerialNum()));
        if (list.size()>0 && !list.get(0).getCabinetNum().equals(one.getCabinetNum())) {
            //抛出单警柜重复异常
            throw new ServiceException(CabinetExceptionEnum.CABINETID_IS_EXISTS);
        }
        Cabinet cabinet = new Cabinet();
        BeanPlusUtil.copyProperties(req, cabinet);
        //后面还要进行消息推送
        MQ.SendMsg("cabinetMsg",req.getSerialNum(),"cabinetChange");
        return this.updateById(cabinet);
    }
    /**
     * 修改单警柜信息，警柜使用
     * 新增箱数
     * @param req
     * @return
     */
    @Override
    public boolean updateCabinetClient(UpdateCabinetReq req) {
        //查询传入的组织机构id是否存在
        pubOrgService.PubOrgExist(req.getOrgId());
        Cabinet one = getOne(new LambdaQueryWrapper<Cabinet>()
                .eq(Cabinet::getCabinetNum,req.getSerialNum()));

        if (one==null)
        {
            throw new ServiceException(CabinetExceptionEnum.CABINET_ISNOT_EXISTS);
        }
        //查询是否有重复的单警柜编号
        List<Cabinet> list = this.list(new LambdaQueryWrapper<Cabinet>()
                .eq(Cabinet::getCabinetNum,req.getSerialNum()));
        if (list.size()>0 && !list.get(0).getCabinetNum().equals(one.getCabinetNum())) {
            //抛出单警柜重复异常
            throw new ServiceException(CabinetExceptionEnum.CABINETID_IS_EXISTS);
        }
        Cabinet cabinet = new Cabinet();
        BeanPlusUtil.copyProperties(req, cabinet);
        //后面还要进行消息推送
        return this.updateById(cabinet);
    }

    /**
     * 箱门绑定人员
     * 箱门id-->人员
     * @param req
     * @return
     */
//    @Override
//    public boolean boxBindPolice(CabinetBoxReq req) {
//        //通过箱门id查询出箱门信息
//        CabinetBox one = cabinetBoxService.getOne(new LambdaQueryWrapper<CabinetBox>()
//                .eq(ObjectUtil.isNotEmpty(req.getId()), CabinetBox::getId, req.getId()));
//        if (ObjectUtil.isEmpty(one)){
//            //箱门id不存在
//            throw new ServiceException(CabinetExceptionEnum.CABINETBOX_ISNOT_EXISTS);
//        }
//        //获取箱门的主柜id
//        String cabinetId = one.getCabinetId();
//        //通过主柜id获取机构id
//        Cabinet one1 = getOne(new LambdaQueryWrapper<Cabinet>()
//                .eq(ObjectUtil.isNotEmpty(cabinetId), Cabinet::getId,cabinetId));
//        if (ObjectUtil.isEmpty(one1)){
//            //单警柜不存在异常
//            throw new ServiceException(CabinetExceptionEnum.CABINET_ISNOT_EXISTS);
//        }
//        long orgId = one1.getOrgIdInt();
//        //通过警员id获取警员所在的机构id
//        Policeman one2 = policemanService.getOne(new LambdaQueryWrapper<Policeman>()
//                .eq(ObjectUtil.isNotEmpty(req.getPoliceId()), Policeman::getId, req.getPoliceId()));
//        if (ObjectUtil.isEmpty(one2)){
//            //警员不存在异常
//            throw new ServiceException(PolicemanExceptionEnum.POLICEMAN_NOT_EXIST);
//        }
//        Long orgId1 = one2.getOrgId();
//        //判断两个机构id是否相同，相同则可以绑定，不相同则绑定失败
//        if (!(orgId1==orgId)){
//            return false;
//        }
//        one2.setCabinetBoxId(one.getId());
//        return policemanService.updateById(one2);
//    }


    /**
     * 修改单警柜箱门状态
     * @param req
     * @return
     */
    @Override
    public boolean ChangeCabinetState(UpdateCabinetReq req) {
        //查询单警柜是否存在
        CabinetExistByNum(req.getSerialNum());
        if (ObjectUtil.isNull(req.getCabinetBoxList()) || req.getCabinetBoxList().size()==0){
            throw new ServiceException(CabinetExceptionEnum.PARAMETER_ERROR);
        }
        List<UpdateCabinetBoxReq> cabinetBoxList = req.getCabinetBoxList();
        List<CabinetBox> list =new ArrayList<>();
        for (UpdateCabinetBoxReq updateCabinet:cabinetBoxList) {
            CabinetBox cabinetBox = new CabinetBox();
            BeanPlusUtil.copyProperties(updateCabinet,cabinetBox);
            list.add(cabinetBox);
        }
        return cabinetBoxService.updateBatchById(list);
    }

    //根据单警柜id查询出组织机构id
    @Override
    public Long SearchOrgId(CabinetReq req) {
        Cabinet cabinet = CabinetExistByNum(req.getServerNum());
        return cabinet.getOrgIdInt();
    }

    //根据单警柜id判断单警柜是否存在
    @Override
    public Cabinet CabinetExist(String id) {
        Cabinet one = getById(id);
        if (ObjectUtil.isNull(one)){
            throw new ServiceException(CabinetExceptionEnum.CABINET_ISNOT_EXISTS);
        }
        return one;
    }
    //根据单警柜id判断单警柜是否存在
    public Cabinet CabinetExistByNum(String serverNum) {
        Cabinet one = getOne(new LambdaQueryWrapper<Cabinet>()
                .eq(ObjectUtil.isNotEmpty(serverNum), Cabinet::getCabinetNum, serverNum));
        if (ObjectUtil.isNull(one)){
            throw new ServiceException(CabinetExceptionEnum.CABINET_ISNOT_EXISTS);
        }
        return one;
    }
    //设置单警柜库存数量信息
    @Override
    public boolean SetInventoryInfo(String id) {
        //统计单警柜总数，在库总数，出库总数，装备总价格
        cabinetMapper.SetInventoryInfo(id);
        return true;
    }



}