package com.njcn.csdevice.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
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.njcn.common.pojo.exception.BusinessException;
import com.njcn.csdevice.api.CsDeviceUserFeignClient;
import com.njcn.csdevice.api.CsLedgerFeignClient;
import com.njcn.csdevice.enums.AlgorithmResponseEnum;
import com.njcn.csdevice.mapper.CsEngineeringMapper;
import com.njcn.csdevice.mapper.CsEngineeringUserMapper;
import com.njcn.csdevice.mapper.CsLedgerMapper;
import com.njcn.csdevice.mapper.CsMarketDataMapper;
import com.njcn.csdevice.pojo.dto.DevDetailDTO;
import com.njcn.csdevice.pojo.param.CsEngineeringAddParm;
import com.njcn.csdevice.pojo.param.CsEngineeringAuditParm;
import com.njcn.csdevice.pojo.param.CsEngineeringQueryPageParm;
import com.njcn.csdevice.pojo.param.CsEngineeringQueryParm;
import com.njcn.csdevice.pojo.po.*;
import com.njcn.csdevice.pojo.vo.CsEngineeringVO;
import com.njcn.csdevice.service.CsEngineeringService;
import com.njcn.csdevice.service.CsTouristDataPOService;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.system.api.AreaFeignClient;
import com.njcn.system.pojo.po.Area;
import com.njcn.user.enums.AppRoleEnum;
import com.njcn.web.utils.RequestUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

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

/**
 * 
 * Description:
 * 接口文档访问地址：http://serverIP:port/swagger-ui.html
 * Date: 2023/4/7  11:04【需求编号】
 *
 * @author clam
 * @version V1.0.0
 */
@Service
@RequiredArgsConstructor
public class CsEngineeringServiceImpl extends ServiceImpl<CsEngineeringMapper, CsEngineeringPO> implements CsEngineeringService{

    private final AreaFeignClient areaFeignClient;
    private final RedisUtil redisUtil;
    private final CsLedgerMapper csLedgerMapper;
    private final CsEngineeringUserMapper  csEngineeringUserMapper;
    private final RoleEngineerDevServiceImpl roleEngineerDevService;
    private final CsMarketDataMapper csMarketDataMapper;
    private final CsTouristDataPOService csTouristDataPOService;
    private final CsLedgerFeignClient csLedgerFeignClient;
    private final CsDeviceUserFeignClient csDeviceUserFeignClient;

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CsEngineeringPO addEngineering(CsEngineeringAddParm csEngineeringAddParm) {
        CsEngineeringPO csEngineeringPO = new CsEngineeringPO ();
        BeanUtils.copyProperties (csEngineeringAddParm, csEngineeringPO);

        csEngineeringPO.setStatus ("1");
        boolean save = this.save (csEngineeringPO);
        List<CsEngineeringPO> list = this.lambdaQuery().eq(CsEngineeringPO::getName, csEngineeringAddParm.getName()).eq(CsEngineeringPO::getStatus, "1").list();
        if(list.size()>1){
            throw new BusinessException("工程名重复");

        }
        CsLedger csLedger1 = new CsLedger();
        csLedger1.setId(csEngineeringPO.getId());
        csLedger1.setPid("0");
        csLedger1.setPids("0");
        csLedger1.setLevel(0);
        csLedger1.setName(csEngineeringPO.getName());
        csLedger1.setState(1);
        csLedger1.setSort(csEngineeringAddParm.getSort());
        csLedgerMapper.insert(csLedger1);
        //绑定用户
        CsEngineeringUserPO po = new CsEngineeringUserPO();
        po.setEngineeringId(csEngineeringPO.getId());
        po.setUserId(RequestUtil.getUserIndex());

        csEngineeringUserMapper.insert(po);
        //工程人员新增工程，默认把工程加入关注列表
        String role = RequestUtil.getUserRole();
        List<String> strings = JSONArray.parseArray(role, String.class);
        if(CollectionUtils.isEmpty(strings)){
            throw new BusinessException(AlgorithmResponseEnum.UNKNOW_ROLE);
        }
        role=strings.get(0);
        if(Objects.equals(role, AppRoleEnum.ENGINEERING_USER.getCode())){
            CsMarketData csMarketData = new CsMarketData();
            csMarketData.setEngineerId(csEngineeringPO.getId());
            csMarketData.setUserId(RequestUtil.getUserIndex());
            csMarketDataMapper.insert(csMarketData);
        }
        return csEngineeringPO;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Boolean auditEngineering(CsEngineeringAuditParm csEngineeringAuditParm) {

        CsEngineeringPO csEngineeringPO = new CsEngineeringPO ();
        BeanUtils.copyProperties (csEngineeringAuditParm, csEngineeringPO);
        boolean b = this.updateById (csEngineeringPO);
        CsLedger csLedger1 = new CsLedger();
        csLedger1.setId(csEngineeringAuditParm.getId());
        if(Objects.equals("0",csEngineeringAuditParm.getStatus())){
            QueryWrapper<CsLedger> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("state",1).eq("pid",csEngineeringAuditParm.getId());
            List<CsLedger> csLedgers = csLedgerMapper.selectList(queryWrapper);
            if(!CollectionUtil.isEmpty(csLedgers)){
                throw new BusinessException(AlgorithmResponseEnum.CHIRLDREN_EXIST.getMessage());
            }

            csLedger1.setState(0);
            //删除配置工程
            QueryWrapper<CsMarketData> csMarketData = new QueryWrapper<>();
            csMarketData.lambda().eq(CsMarketData::getEngineerId,csEngineeringAuditParm.getId());
            csMarketDataMapper.delete(csMarketData);
            QueryWrapper<CsTouristDataPO> queryWrap = new QueryWrapper<>();
            queryWrap.eq("enginer_id",csEngineeringAuditParm.getId());
            csTouristDataPOService.getBaseMapper().delete(queryWrap);

        }
        if(StringUtils.isNotBlank(csEngineeringAuditParm.getName())){
            csLedger1.setName(csEngineeringAuditParm.getName());
        }
        csLedger1.setSort(csEngineeringAuditParm.getSort());
        csLedgerMapper.updateById(csLedger1);
        List<CsEngineeringPO> list = this.lambdaQuery().eq(CsEngineeringPO::getName, csEngineeringAuditParm.getName()).eq(CsEngineeringPO::getStatus, "1").list();
        if(list.size()>1){
            throw new BusinessException("工程名重复");

        }

        return b;
    }

    @Override
    public List<CsEngineeringVO> queryEngineering(CsEngineeringQueryParm csEngineeringQueryParm) {
        List<CsEngineeringVO> csEngineeringVOList = new ArrayList<> ();
        QueryWrapper<CsEngineeringPO> queryWrapper = new QueryWrapper<> ();
        /*获取用户工程，设备信息过滤*/
        List<String> roleengineer = roleEngineerDevService.getRoleengineer();

        if(CollectionUtil.isEmpty(roleengineer)){
                return csEngineeringVOList;
        }
        queryWrapper.in("id",roleengineer);



        queryWrapper.eq (StringUtils.isNotBlank (csEngineeringQueryParm.getProvince ()),"province",csEngineeringQueryParm.getProvince ()).
                eq (StringUtils.isNotBlank (csEngineeringQueryParm.getCity ()),"city",csEngineeringQueryParm.getCity ()).
                eq ("status","1" )
                .ne("name","便携式工程").
                like (StringUtils.isNotBlank (csEngineeringQueryParm.getName ()),"name",csEngineeringQueryParm.getName ()).orderByAsc("sort");
        List<CsEngineeringPO> csEngineeringPOS = this.getBaseMapper ( ).selectList (queryWrapper);
        csEngineeringVOList = csEngineeringPOS.stream ().map (temp->{
            CsEngineeringVO vo = new CsEngineeringVO();
            BeanUtils.copyProperties (temp, vo);
            vo.setProvinceName (this.getAreaById (vo.getProvince ()));
            vo.setCityName (this.getAreaById (vo.getCity ()));
            return vo;
        }).collect(Collectors.toList());

        return csEngineeringVOList;
    }

    @Override
    public IPage<CsEngineeringVO> queryEngineeringPage(CsEngineeringQueryPageParm csEngineeringQueryPageParm) {
        Page<CsEngineeringPO> tempPage = new Page<> (csEngineeringQueryPageParm.getPageNum(), csEngineeringQueryPageParm.getPageSize ( ));
        Page<CsEngineeringVO> returnPage = new Page<> (csEngineeringQueryPageParm.getPageNum ( ), csEngineeringQueryPageParm.getPageSize ( ));

        QueryWrapper<CsEngineeringPO> queryWrapper = new QueryWrapper<> ();
        QueryWrapper<CsEngineeringUserPO> csEngineeringUserPOQueryWrapper = new QueryWrapper<> ();
        /*获取用户下的工程id*/
        List<String> roleengineer = roleEngineerDevService.getRoleengineer();

        if(CollectionUtil.isEmpty(roleengineer)){
            return returnPage;
        }
        queryWrapper.in("id",roleengineer);

        queryWrapper.eq (StringUtils.isNotBlank (csEngineeringQueryPageParm.getProvince ()),"province",csEngineeringQueryPageParm.getProvince ()).
                eq (StringUtils.isNotBlank (csEngineeringQueryPageParm.getCity ()),"city",csEngineeringQueryPageParm.getCity ()).
                eq ("status","1" ).
                ne("name","便携式工程").
                like (StringUtils.isNotBlank (csEngineeringQueryPageParm.getName ()),"name",csEngineeringQueryPageParm.getName ()).orderByDesc("create_time");
        Page<CsEngineeringPO> csEngineeringPOPage = this.getBaseMapper ( ).selectPage (tempPage, queryWrapper);
        List<CsEngineeringVO> collect = csEngineeringPOPage.getRecords ( ).stream ( ).map (temp -> {
            CsEngineeringVO vo = new CsEngineeringVO ( );
            BeanUtils.copyProperties (temp, vo);
            vo.setProvinceName (this.getAreaById (vo.getProvince ()));
            vo.setCityName (this.getAreaById (vo.getCity ()));
            return vo;
        }).collect (Collectors.toList ( ));
        returnPage.setRecords (collect);
        returnPage.setTotal(tempPage.getTotal());

        return returnPage;
    }

    @Override
    public List<CsEngineeringPO> getEngineerings(List<String> list) {
        return this.lambdaQuery().in(CsEngineeringPO::getId,list).eq(CsEngineeringPO::getStatus,"1").list();
    }

    @Override
    public CsEngineeringPO queryEngineeringById(String id) {
        return this.lambdaQuery().eq(CsEngineeringPO::getId,id).eq(CsEngineeringPO::getStatus,"1").one();
    }

    @Override
    public List<CsEngineeringPO> getUnlinkedEngineering(String userId) {
        List<CsEngineeringPO> result = new ArrayList<>();
        List<String> list1 = new ArrayList<>();
        //根据用户信息获取设备信息
        List<String> devList = csDeviceUserFeignClient.findDevByUserId(userId).getData();
        //根据设备查询工程信息
        if (CollectionUtil.isNotEmpty(devList)) {
            List<DevDetailDTO> ledger = csLedgerFeignClient.getInfoByIds(devList).getData();
            ledger.forEach(item->{
                if (!Objects.equals(item.getEngineeringid(),"/")) {
                    list1.add(item.getEngineeringid());
                }
            });
        }
        //获取有设备的工程信息
        LambdaQueryWrapper<CsEngineeringPO> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.eq(CsEngineeringPO::getStatus,"1");
        if (CollectionUtil.isNotEmpty(list1)) {
            queryWrapper2.notIn(CsEngineeringPO::getId,list1);
        }
        List<CsEngineeringPO> list = this.baseMapper.selectList(queryWrapper2);
        //剔除没有设备的工程
        if (CollectionUtil.isNotEmpty(list)) {
            Map<String, CsEngineeringPO> map = list.stream().collect(Collectors.toMap(CsEngineeringPO::getId, Function.identity()));
            List<String> list2 = list.stream().map(CsEngineeringPO::getId).collect(Collectors.toList());
            List<DevDetailDTO> ledger = csLedgerFeignClient.getEngineeringHaveDevs(list2).getData();
            if (CollectionUtil.isNotEmpty(ledger)) {
                ledger.forEach(item->{
                    CsEngineeringPO po = new CsEngineeringPO();
                    po.setId(item.getEngineeringid());
                    po.setName(map.get(item.getEngineeringid()).getName());
                    if (!Objects.equals(po.getName(), "便携式工程")) {
                        result.add(po);
                    }
                });
            }
        }
        return result;
    }

    @Override
    public CsEngineeringPO add(CsEngineeringAddParm csEngineeringAddParm) {
        List<CsEngineeringPO> list = this.lambdaQuery().eq(CsEngineeringPO::getName, csEngineeringAddParm.getName()).eq(CsEngineeringPO::getStatus, "1").list();
        if(!list.isEmpty()){
            throw new BusinessException("新增失败,工程名重复");
        }
        //新增工程
        CsEngineeringPO po = new CsEngineeringPO ();
        BeanUtils.copyProperties (csEngineeringAddParm, po);
        po.setStatus ("1");
        this.save(po);
        return po;
    }

    @Override
    public CsEngineeringPO updateData(CsEngineeringAuditParm csEngineeringAuditParm) {
        List<CsEngineeringPO> list = this.lambdaQuery()
                .eq(CsEngineeringPO::getName, csEngineeringAuditParm.getName())
                .eq(CsEngineeringPO::getStatus, "1")
                .ne(CsEngineeringPO::getId, csEngineeringAuditParm.getId())
                .list();
        if(!list.isEmpty()){
            throw new BusinessException("修改失败,工程名重复");
        }
        CsEngineeringPO po = new CsEngineeringPO();
        BeanUtils.copyProperties(csEngineeringAuditParm, po);
        this.updateById(po);
        return po;
    }

    @Override
    public boolean deleteData(String id) {
        LambdaUpdateWrapper<CsEngineeringPO> queryWrapper = new LambdaUpdateWrapper<>();
        queryWrapper.eq(CsEngineeringPO::getId,id).set(CsEngineeringPO::getStatus,"0");
        return this.update(queryWrapper);
    }

    @Override
    public CsEngineeringPO getEngineeringByName(String name) {
        LambdaQueryWrapper<CsEngineeringPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CsEngineeringPO::getName,name).eq(CsEngineeringPO::getStatus,1);
        return this.getOne(queryWrapper);
    }

    public String getAreaById(String id){

        String areaName =redisUtil.getStringByKey (id);
        areaName =Optional.ofNullable (areaName).orElseGet (() ->{
            Area data = areaFeignClient.selectIdArea (id).getData ( );
            redisUtil.saveByKey (id,data.getName ());
            return data.getName ();
        });

        return areaName;

    }


}
