package com.njcn.csdevice.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
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.conditions.update.UpdateWrapper;
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.enums.AlgorithmResponseEnum;
import com.njcn.csdevice.mapper.AppProjectMapper;
import com.njcn.csdevice.mapper.CsLedgerMapper;
import com.njcn.csdevice.mapper.CsTopologyDiagramTemplateMapper;
import com.njcn.csdevice.pojo.param.*;
import com.njcn.csdevice.pojo.po.*;
import com.njcn.csdevice.pojo.vo.AppProjectVO;
import com.njcn.csdevice.pojo.vo.AppTopologyDiagramVO;
import com.njcn.csdevice.service.AppProjectService;
import com.njcn.csdevice.service.AppTopologyDiagramService;
import com.njcn.csdevice.service.CsLineTopologyTemplateService;
import com.njcn.csdevice.service.RoleEngineerDevService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Description:
 * 接口文档访问地址：http://serverIP:port/swagger-ui.html
 * Date: 2023/3/27  10:24【需求编号】
 *
 * @author clam
 * @version V1.0.0
 */
@Service
@RequiredArgsConstructor
class AppProjectServiceImpl extends ServiceImpl<AppProjectMapper, AppProjectPO> implements AppProjectService {

    private final AppProjectMapper appProjectMapper;
    private final AppTopologyDiagramService appTopologyDiagramService;
    private final CsLedgerMapper csLedgerMapper;
    private final CsTopologyDiagramTemplateMapper csTopologyDiagramTemplateMapper;
    private final CsLineTopologyTemplateService csLineTopologyDiagramTemplateService;
    private final RoleEngineerDevService roleEngineerDevService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AppProjectPO addAppProject(AppProjectAddParm appProjectAddOrAuditParm) {
        AppProjectPO appProjectPO = new AppProjectPO ( );

        if(checkName(appProjectAddOrAuditParm.getName(),"",appProjectAddOrAuditParm.getEngineeringId())){
            throw new BusinessException(AlgorithmResponseEnum.PROJECT_COMMON_ERROR);
        }
        BeanUtils.copyProperties (appProjectAddOrAuditParm, appProjectPO);
        appProjectPO.setStatus ("1");
        boolean save = this.save (appProjectPO);
        //如何使用拓扑图模板则将拓扑图模板复制绑定
        if(!CollectionUtils.isEmpty(appProjectAddOrAuditParm.getTopoIds()) ){
            List<AppTopologyDiagramPO> appTopologyDiagramPOS = new ArrayList<>();
            List<CsLineTopologyTemplate> csLineTopologyTemplates = new ArrayList<>();
            appProjectAddOrAuditParm.getTopoIds().forEach(temp->{
                AppTopologyDiagramPO appTopologyDiagramPO = new AppTopologyDiagramPO();
                CsTopologyDiagramTemplate csTopologyDiagramTemplate = csTopologyDiagramTemplateMapper.selectById(temp);
                appTopologyDiagramPO.setFilePath (csTopologyDiagramTemplate.getFilePath());
                appTopologyDiagramPO.setProjectId (appProjectPO.getId());
                appTopologyDiagramPO.setName (csTopologyDiagramTemplate.getName());
                appTopologyDiagramPO.setStatus ("1");
                appTopologyDiagramPO.setTopoId(temp);
                appTopologyDiagramService.save(appTopologyDiagramPO);
            });
            csLineTopologyDiagramTemplateService.saveBatch(csLineTopologyTemplates);
        }
        if(Objects.nonNull( appProjectAddOrAuditParm.getFiles ( ))){
            for (int i = 0; i < appProjectAddOrAuditParm.getFiles ( ).length; i++) {

                AppTopologyDiagramAddParm appTopologyDiagramAddParm = new AppTopologyDiagramAddParm ( );
                appTopologyDiagramAddParm.setProjectId (appProjectPO.getId ( ));
                appTopologyDiagramAddParm.setTopologyDiagramName (appProjectAddOrAuditParm.getFiles ( )[i].getOriginalFilename ( ));
                appTopologyDiagramAddParm.setFile (appProjectAddOrAuditParm.getFiles ( )[i]);
                appTopologyDiagramService.addAppTopologyDiagram (appTopologyDiagramAddParm);
            }
        }

        //云协议工程
        if (Objects.nonNull(appProjectAddOrAuditParm.getIcdEngineeringId())){
            CsLedger csLedger1 = new CsLedger();
            csLedger1.setId(appProjectPO.getId());
            csLedger1.setPid(appProjectAddOrAuditParm.getEngineeringId());
            csLedger1.setPids("0,"+appProjectAddOrAuditParm.getEngineeringId());
            csLedger1.setLevel(1);
            csLedger1.setName(appProjectPO.getName());
            csLedger1.setState(1);
            csLedger1.setSort(0);
            csLedgerMapper.insert(csLedger1);
        }
        //其他工程
        else {
            CsLedger csLedger = csLedgerMapper.selectById(appProjectAddOrAuditParm.getEngineeringId());
            Optional.ofNullable(csLedger).orElseThrow(()-> new BusinessException(AlgorithmResponseEnum.ENGINEERING_DATA_ERROR));
            CsLedger csLedger1 = new CsLedger();
            csLedger1.setId(appProjectPO.getId());
            csLedger1.setPid(appProjectAddOrAuditParm.getEngineeringId());
            csLedger1.setPids(csLedger.getPids()+ ","+appProjectAddOrAuditParm.getEngineeringId());
            csLedger1.setLevel(1);
            csLedger1.setName(appProjectPO.getName());
            csLedger1.setState(1);
            csLedger1.setSort(0);
            csLedgerMapper.insert(csLedger1);
        }
        return appProjectPO;
    }

    private Boolean checkName( String name,String id,String engineeringId) {
        QueryWrapper<CsLedger> queryWrapper = new QueryWrapper ( );
        queryWrapper.select ("1").
                eq ("state", 1).
                ne(StringUtils.isNotBlank(id),"id",id).eq("pid",engineeringId).
//                eq ("user_id", userId).
                eq ("name", name);
        Integer integer = csLedgerMapper.selectCount (queryWrapper);
        return integer > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean AuditAppProject(AppProjectAuditParm appProjectAuditParm) {
        AppProjectPO appProjectPO = new AppProjectPO ( );

        QueryWrapper<AppProjectPO> queryWrapper = new QueryWrapper ( );
        queryWrapper.eq ("id", appProjectAuditParm.getId ( ));
        AppProjectPO appProjectPO1 = appProjectMapper.selectOne (queryWrapper);
        //删除项目
        if(Objects.equals("0",appProjectAuditParm.getStatus())){
            QueryWrapper<CsLedger> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("state",1).eq("pid",appProjectAuditParm.getId());
            List<CsLedger> csLedgers = csLedgerMapper.selectList(queryWrapper1);
            if(!CollectionUtil.isEmpty(csLedgers)){
                throw new BusinessException(AlgorithmResponseEnum.CHIRLDREN2_EXIST.getMessage());
            }
            this.lambdaUpdate().eq(AppProjectPO::getId,appProjectAuditParm.getId()).set(AppProjectPO::getStatus,"0").update();
            appTopologyDiagramService.lambdaUpdate().eq(AppTopologyDiagramPO::getProjectId,appProjectAuditParm.getId()).set(AppTopologyDiagramPO::getStatus,"0").update();
            CsLedger csLedger1 = new CsLedger();
            csLedger1.setId(appProjectAuditParm.getId());
            csLedger1.setState(0);
            csLedger1.setState(0);
            csLedgerMapper.updateById(csLedger1);
        }

        if(checkName(appProjectAuditParm.getName(),appProjectAuditParm.getId(),appProjectAuditParm.getEngineeringId())){
            throw new BusinessException(AlgorithmResponseEnum.PROJECT_COMMON_ERROR);
        }

        BeanUtils.copyProperties (appProjectAuditParm, appProjectPO);
        UpdateWrapper<AppProjectPO> updateWrapper = new UpdateWrapper ( );
        updateWrapper.eq ("id", appProjectAuditParm.getId ( ));

        int i = appProjectMapper.update (appProjectPO, updateWrapper);
        //删除拓扑图
        if(CollectionUtils.isEmpty(appProjectAuditParm.getNewTopoIds())){
            appTopologyDiagramService.lambdaUpdate().eq(AppTopologyDiagramPO::getProjectId,appProjectAuditParm.getId()).set(AppTopologyDiagramPO::getStatus,"0").update();
        }else {
            appTopologyDiagramService.lambdaUpdate().eq(AppTopologyDiagramPO::getProjectId,appProjectAuditParm.getId()).notIn(AppTopologyDiagramPO::getId,appProjectAuditParm.getNewTopoIds()).set(AppTopologyDiagramPO::getStatus,"0").update();
        }

        //如何使用拓扑图模板则将拓扑图模板复制绑定
        if(!CollectionUtils.isEmpty(appProjectAuditParm.getTopoIds()) ){
            List<AppTopologyDiagramPO> appTopologyDiagramPOS = new ArrayList<>();
            List<CsLineTopologyTemplate> csLineTopologyTemplates = new ArrayList<>();
            appProjectAuditParm.getTopoIds().forEach(temp->{
                //活驴掉已经插入的模版
                List<AppTopologyDiagramPO> list = appTopologyDiagramService.lambdaQuery().eq(AppTopologyDiagramPO::getProjectId, appProjectAuditParm.getId()).eq(AppTopologyDiagramPO::getTopoId, temp).eq(AppTopologyDiagramPO::getStatus, "1").list();
                if(!CollectionUtils.isEmpty(list)){
                    return;
                }
                AppTopologyDiagramPO appTopologyDiagramPO = new AppTopologyDiagramPO();
                CsTopologyDiagramTemplate csTopologyDiagramTemplate = csTopologyDiagramTemplateMapper.selectById(temp);
                appTopologyDiagramPO.setFilePath (csTopologyDiagramTemplate.getFilePath());
                appTopologyDiagramPO.setProjectId (appProjectPO.getId());
                appTopologyDiagramPO.setName (csTopologyDiagramTemplate.getName());
                appTopologyDiagramPO.setStatus ("1");
                appTopologyDiagramPO.setTopoId(temp);
                appTopologyDiagramService.save(appTopologyDiagramPO);
            });
            csLineTopologyDiagramTemplateService.saveBatch(csLineTopologyTemplates);
        }
        if(Objects.nonNull( appProjectAuditParm.getFiles ( ))){
            for (int k = 0; k < appProjectAuditParm.getFiles ( ).length; k++) {
                AppTopologyDiagramAddParm appTopologyDiagramAddParm = new AppTopologyDiagramAddParm ( );
                appTopologyDiagramAddParm.setProjectId (appProjectPO.getId ( ));
                appTopologyDiagramAddParm.setTopologyDiagramName (appProjectAuditParm.getFiles ( )[k].getOriginalFilename ( ));
                appTopologyDiagramAddParm.setFile (appProjectAuditParm.getFiles ( )[k]);
                appTopologyDiagramService.addAppTopologyDiagram (appTopologyDiagramAddParm);
            }
        }

        CsLedger csLedger2 = new CsLedger();
        csLedger2.setId(appProjectAuditParm.getId());
        if(StringUtils.isNotBlank(appProjectAuditParm.getName())){
            csLedger2.setName(appProjectAuditParm.getName());
        }
        csLedgerMapper.updateById(csLedger2);
        return i == 1;
    }

    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public Boolean updateProject(AppProjectAuditParm appProjectAuditParm) {
        //修改项目表
        this.lambdaUpdate().set(AppProjectPO::getName,appProjectAuditParm.getName())
                .set(AppProjectPO::getArea,appProjectAuditParm.getArea())
                .set(AppProjectPO::getDescription,appProjectAuditParm.getDescription())
                .eq(AppProjectPO::getId,appProjectAuditParm.getId())
                .eq(AppProjectPO::getStatus,"1")
                .update();
        //修改台账表
        CsLedger csLedger = new CsLedger();
        csLedger.setId(appProjectAuditParm.getId());
        csLedger.setName(appProjectAuditParm.getName());
        csLedgerMapper.updateById(csLedger);
        return true;
    }

    @Override
    public IPage<AppProjectVO> queryProject(AppProjectQueryParm appProjectQueryParm) {

        Page<AppProjectVO> returnpage = new Page<> (appProjectQueryParm.getPageNum ( ), appProjectQueryParm.getPageSize ( ));
//        String userId = RequestUtil.getUserIndex();
//        if(Objects.equals(RequestUtil.getUsername(),"root")){
//            userId = null;
//        }
        /*如何为空前端没传，查询所有*/
        List<String> device = new ArrayList<>();
        device = roleEngineerDevService.getDevice();
        if(StringUtils.isEmpty(appProjectQueryParm.getEngineeringId())){
            List<String> roleengineer = roleEngineerDevService.getRoleengineer();

            appProjectQueryParm.setEngineeringIds(roleengineer);

            if(CollectionUtils.isEmpty(roleengineer)){
                return returnpage;
            }
        }else {
            appProjectQueryParm.setEngineeringIds(Stream.of(appProjectQueryParm.getEngineeringId()).collect(Collectors.toList()));
        }

        QueryWrapper<CsLedger> queryWrapper = new QueryWrapper<>();
        returnpage = appProjectMapper.getPageVo (returnpage, appProjectQueryParm);
        List<String> finalDevice = device;
        List<AppProjectVO> collect = returnpage.getRecords().stream().map(temp -> {
            AppTopologyDiagramQueryParm appTopologyDiagramQueryParm = new AppTopologyDiagramQueryParm();
            Integer integer =0;
            if(!CollectionUtils.isEmpty(finalDevice)){
                queryWrapper.clear();
                queryWrapper.lambda().eq(CsLedger::getPid,temp.getId()).eq(CsLedger::getState,1).in(CsLedger::getId, finalDevice);

                integer = csLedgerMapper.selectCount(queryWrapper);
            }

            temp.setDevNum(integer);
            appTopologyDiagramQueryParm.setProjectId(temp.getId());

            List<AppTopologyDiagramVO> appTopologyDiagramVOList = appTopologyDiagramService.queryAppTopologyDiagram(appTopologyDiagramQueryParm);
            temp.setTopologyDiagramPaths(appTopologyDiagramVOList);

            return temp;
        }).collect(Collectors.toList());
        returnpage.setRecords(collect);

//        Page<AppProjectPO> appProjectPOPage = new Page<> (appProjectQueryParm.getPageNum ( ), appProjectQueryParm.getPageSize ( ));
//        QueryWrapper<AppProjectPO> queryWrapper = new QueryWrapper ( );
//        queryWrapper.eq ("status", "1").
//                eq (StringUtils.isNotBlank (appProjectQueryParm.getProjectId ( )), "id", appProjectQueryParm.getProjectId ( )).
//                eq (StringUtils.isNotBlank (appProjectQueryParm.getEngineeringId ( )), "engineering_id", appProjectQueryParm.getEngineeringId ( )).
//                le (StringUtils.isNotBlank (appProjectQueryParm.getEndTime ( )), "create_time", appProjectQueryParm.getEndTime ( )).
//                ge (StringUtils.isNotBlank (appProjectQueryParm.getStartTime ( )), "create_time", appProjectQueryParm.getStartTime ( )).
//                like (StringUtils.isNotBlank (appProjectQueryParm.getSearchValue ( )), "name", appProjectQueryParm.getSearchValue ( ));
//        Page<AppProjectPO> appProjectPOPage1 = appProjectMapper.selectPage (appProjectPOPage, queryWrapper);
//        List<AppProjectVO> collect = appProjectPOPage1.getRecords ( ).stream ( ).map (temp -> {
//                    AppProjectVO vo = new AppProjectVO ( );
//                    BeanUtils.copyProperties (temp, vo);
//                    AppTopologyDiagramQueryParm appTopologyDiagramQueryParm = new AppTopologyDiagramQueryParm ( );
//                    appTopologyDiagramQueryParm.setProjectId (vo.getId ( ));
//                    List<AppTopologyDiagramVO> appTopologyDiagramVOList = appTopologyDiagramService.queryAppTopologyDiagram (appTopologyDiagramQueryParm);
//                    List<String> collect1 = appTopologyDiagramVOList.stream ( ).map (AppTopologyDiagramVO::getFilePath).collect (Collectors.toList ( ));
//                    vo.setTopologyDiagramPaths (collect1);
//                    return vo;
//                }
//
//        ).collect (Collectors.toList ( ));
        return returnpage;
    }

    @Override
    public List<AppProjectPO> getProjectByEngineering(List<String> list) {
        List<AppProjectPO> result = new ArrayList<>();
        QueryWrapper<CsLedger> csLedgerQueryWrapper = new QueryWrapper();
        csLedgerQueryWrapper.lambda().in(CsLedger::getPid, list).eq(CsLedger::getState,1);
        List<CsLedger> csLedgers = csLedgerMapper.selectList(csLedgerQueryWrapper);
        if (CollectionUtil.isNotEmpty(csLedgers)) {
            List<String> collect = csLedgers.stream().map(CsLedger::getId).collect(Collectors.toList());
            result = this.lambdaQuery().in(AppProjectPO::getId,collect).list();
        }
        return result;
    }

    @Override
    public AppProjectPO add(AppProjectAddParm param) {
        AppProjectPO po = new AppProjectPO ( );
        List<AppProjectPO> list = this.lambdaQuery().eq(AppProjectPO::getName, param.getName()).eq(AppProjectPO::getStatus, "1").list();
        if(!list.isEmpty()){
            throw new BusinessException("新增失败,项目名重复");
        }
        BeanUtils.copyProperties (param, po);
        po.setStatus ("1");
        this.save(po);
        return po;
    }

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

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

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


}
