package com.zcxk.rmcp.web.service.install.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.zcxk.core.common.enums.StatusEnum;
import com.zcxk.core.common.exception.BusinessException;
import com.zcxk.core.common.pojo.ResultMessage;
import com.zcxk.core.oauth2.pojo.LoginUser;
import com.zcxk.core.common.util.BeanCopyUtils;
import com.zcxk.core.common.util.SnowflakeIdWorker;
import com.zcxk.core.oauth2.util.UserUtil;
import com.zcxk.core.mysql.pageing.Pagination;
import com.zcxk.rmcp.api.dto.install.*;
import com.zcxk.rmcp.api.enums.RmcpErrorEnum;
import com.zcxk.rmcp.api.query.InstallPlanQueryCondition;
import com.zcxk.rmcp.api.vo.*;
import com.zcxk.rmcp.core.dao.*;
import com.zcxk.rmcp.core.entity.*;
import com.zcxk.rmcp.web.excel.download.adapter.InstallMeterExcelFillAdapter;
import com.zcxk.rmcp.web.excel.download.adapter.InstallPlanExcelFillAdapter;
import com.zcxk.rmcp.web.excel.download.service.InstallPlanExcelServiceImpl;
import com.zcxk.rmcp.web.excel.model.*;
import com.zcxk.rmcp.web.service.CommonService;
import com.zcxk.rmcp.web.service.CommunityService;
import com.zcxk.rmcp.web.service.OrgService;
import com.zcxk.rmcp.web.service.ProductService;
import com.zcxk.rmcp.web.service.install.InstallPlanService;
import com.zcxk.rmcp.web.util.TreeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.annotation.Transactional;

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

import static com.google.common.collect.Lists.newArrayList;

/**
 * 
 * @author linqingwei
 * @date 2021-07-21 10:03
 */
@Slf4j
@Service
public class InstallPlanServiceImpl implements InstallPlanService {

    @Resource
    private InstallPlanMapper installPlanMapper;
    @Resource
    private CommunityMapper communityMapper;
    @Autowired
    private SnowflakeIdWorker idWorker;
    @Resource
    private InstallListMapper installListMapper;
    @Resource
    private InstallPlanDataMapper installPlanDataMapper;
    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;
    @Autowired
    private CommonService commonService;
    @Autowired
    private InstallPlanExcelServiceImpl installPlanExcelService;
    @Autowired
    private CommunityService communityService;
    @Autowired
    private ProductService productService;
    @Autowired
    private OrgService orgService;
    @Autowired
    private MeterReadWaterRecordMapper meterReadWaterRecordMapper;


    @Override
    public int insertSelective(InstallPlan record) {
        record.setDoorNum(0);
        record.setInstallNum(0);
        record.setAcceptedNum(0);
        record.setPlanStatus(0);
        record.setAcceptStatus(0);
        record.setAcceptStatus(0);
        record.setStatus(StatusEnum.OK.getCode());
        record.setCreateBy(UserUtil.getUsername());
        record.setCreateDate(LocalDateTime.now());
        record.setUpdateBy(UserUtil.getUsername());
        record.setUpdateDate(LocalDateTime.now());
        return installPlanMapper.insertSelective(record);
    }

    @Override
    public int updateByPrimaryKeySelective(InstallPlan record) {
        return installPlanMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public Pagination<InstallPlanVo> getPage(InstallPlanQueryCondition condition, int pageNum, int pageSize) {

        PageHelper.startPage(pageNum,pageSize);
        List<InstallPlanVo> list = installPlanMapper.findList(condition,UserUtil.getCurrentUser().getUserCondition());
        return new Pagination<>(list);
    }

    @Override
    @Transactional
    public void add(InstallPlanInputDto dto) {
        log.info("begin InstallPlanServiceImpl add  : " + JSON.toJSONString(dto));
        LoginUser loginUser = UserUtil.getCurrentUser();

        //TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        Integer planId = null;
        try {

            // 1、小区更新
            Community community = new Community();
            community.setId(dto.getCommunityId());
            community.setAddress(dto.getAdrress());
            community.setLng(dto.getLng());
            community.setLat(dto.getLat());
            communityMapper.updateByPrimaryKeySelective(community);

            // 2、保存计划
            InstallPlan installPlan = new InstallPlan();
            BeanCopyUtils.copyProperties(dto, installPlan, InstallPlan.class);
            installPlan.setTenantId(loginUser.getTenantId());
            installPlan.setPlatformType(1);
            this.insertSelective(installPlan);

            // 3、添加计划清单数据
            addPlanData(installPlan.getId(),installPlan.getTenantId(),dto);
            planId = installPlan.getId();

            //dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            e.printStackTrace();
            //dataSourceTransactionManager.rollback(transactionStatus);
        }


        log.info("end InstallPlanServiceImpl add");
    }

    private void addPlanData(Integer planId, String tenantId, InstallPlanInputDto dto){
        int doorNum = 0;
        List<InstallPlanDataDto> list = dto.getInstallPlanDataList();
        if (list != null && list.size() > 0) {
            List<InstallList> installLists = newArrayList();
            List<InstallPlanData> installPlanDataList = newArrayList();
            for (InstallPlanDataDto installPlanBuilding : list) {
                InstallPlanData installPlanDataBuilding = new InstallPlanData();
                installPlanDataBuilding.setId(idWorker.nextId());
                installPlanDataBuilding.setName(installPlanBuilding.getName() + "栋");
                installPlanDataBuilding.setParentId(0L);
                installPlanDataBuilding.setInstallPlanId(planId);
                installPlanDataBuilding.setType(1);
                installPlanDataBuilding.setStatus(1);
                installPlanDataList.add(installPlanDataBuilding);
                //单元
                if (installPlanBuilding.getChildren() != null && installPlanBuilding.getChildren().size() > 0) {
                    for (InstallPlanDataDto installPlanUnit : installPlanBuilding.getChildren()) {
                        InstallPlanData installPlanDataUnit = new InstallPlanData();
                        installPlanDataUnit.setName(installPlanUnit.getName() != null ? installPlanUnit.getName() + "单元" : "");
                        installPlanDataUnit.setId(idWorker.nextId());
                        installPlanDataUnit.setParentId(installPlanDataBuilding.getId());
                        installPlanDataUnit.setInstallPlanId(planId);
                        installPlanDataUnit.setType(2);
                        installPlanDataUnit.setStatus(1);
                        installPlanDataList.add(installPlanDataUnit);

                        //安装楼层
                        if (installPlanUnit.getChildren() != null && installPlanUnit.getChildren().size() > 0) {
                            for (InstallPlanDataDto installPlanFloor : installPlanUnit.getChildren()) {
                                InstallPlanData installPlanDataFloor = new InstallPlanData();
                                installPlanDataFloor.setName(installPlanFloor.getName() + "层");
                                installPlanDataFloor.setId(idWorker.nextId());
                                installPlanDataFloor.setParentId(installPlanDataUnit.getId());
                                installPlanDataFloor.setInstallPlanId(planId);
                                installPlanDataFloor.setType(3);
                                installPlanDataFloor.setStatus(1);
                                installPlanDataList.add(installPlanDataFloor);
                                //安装清单
                                if (installPlanFloor.getChildren() != null && installPlanFloor.getChildren().size() > 0) {
                                    for (InstallPlanDataDto installPlanDoor : installPlanFloor.getChildren()) {
                                        InstallList installList = new InstallList();
                                        installList.setTenantId(tenantId);
                                        installList.setInstallPlanId(planId);
                                        installList.setInstallPlanDataId(installPlanDataFloor.getId());
                                        installList.setDoorNo(installPlanDoor.getName());
                                        installList.setIsInstalled(0);
                                        installList.setIsAccepted(0);

                                        installList.setRemark("");
                                        installList.setStatus(StatusEnum.OK.getCode());
                                        installList.setCreateDate(LocalDateTime.now());
                                        installList.setUpdateDate(LocalDateTime.now());
                                        installList.setCreateBy(UserUtil.getUsername());
                                        installList.setUpdateBy(UserUtil.getUsername());
                                        installLists.add(installList);
                                        doorNum++;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            installListMapper.batchInsert(installLists);
            installPlanDataMapper.batchInsert(installPlanDataList);
        }
        //更新数量
        InstallPlan updateInstallPlan = new InstallPlan();
        updateInstallPlan.setId(planId);
        updateInstallPlan.setDoorNum(doorNum);
        this.updateByPrimaryKeySelective(updateInstallPlan);
    }


    @Override
    public void batchDelete(List<Integer> ids) {
        installPlanMapper.batchDelete(ids);
    }

    @Override
    public void allDel(InstallPlanQueryCondition condition) {
        List<InstallPlanVo> list = installPlanMapper.findList(condition,UserUtil.getCurrentUser().getUserCondition());
        List<Integer> ids = new ArrayList<>();
        if (list != null && list.size() > 0) {
            for (InstallPlanVo vo : list) {
                ids.add(vo.getId());
            }
            this.batchDelete(ids);
        }
    }

    @Override
    public InstallDetailDto getInstallDetail(Integer id) {
        //InstallDetailDto installDetail = new InstallDetailDto();
        List<InstallPlanDataDto> installPlanDataDTOList = newArrayList();

        //1、计划信息
        //InstallPlan installPlan = installPlanMapper.findById(id);
        InstallDetailDto installDetail = installPlanMapper.findDetail(id);


        //2、计划数据(楼栋、单元、楼层)
        List<InstallPlanData> installPlanDataList = installPlanDataMapper.fondByPlanId(id);
        if (installPlanDataList != null && installPlanDataList.size() > 0) {
            for (InstallPlanData installPlanData : installPlanDataList) {
                InstallPlanDataDto installPlanDataDTO = new InstallPlanDataDto();
                installPlanDataDTO.setId(installPlanData.getId());
                installPlanDataDTO.setParentId(installPlanData.getParentId());
                installPlanDataDTO.setName(installPlanData.getName());
                installPlanDataDTO.setType(installPlanData.getType());
                installPlanDataDTOList.add(installPlanDataDTO);
            }
        }

        //3、计划清单
        List<InstallListDto> installLists = installListMapper.getList(id);
        if (installLists != null && installLists.size() > 0) {
            Integer installedNumber = 0;
            for (InstallListDto installList : installLists) {
                InstallPlanDataDto installPlanDataDTO = new InstallPlanDataDto();
                installPlanDataDTO.setId(Long.valueOf(installList.getId()));
                installPlanDataDTO.setParentId(installList.getInstallPlanDataId());
                installPlanDataDTO.setName(installList.getDoorNo());
                installPlanDataDTO.setDeviceId(installList.getDeviceId());
                installPlanDataDTO.setType(4);
                installPlanDataDTO.setIsInstalled(installList.getIsInstalled());
                installPlanDataDTO.setIsAccepted(installList.getIsAccepted());
                installPlanDataDTO.setDeviceStatus(installList.getDeviceStatus());
                installPlanDataDTOList.add(installPlanDataDTO);
                if (installList.getIsInstalled() == 1) {
                    installedNumber++;
                }
            }
            //installDetail.setTotalNumber(installLists.size());
            //installDetail.setInstalledNumber(installedNumber);
        }

        //4、组装树形数据
        List<InstallPlanDataDto> list = TreeUtil.getInstallPlanDataTree(installPlanDataDTOList, 0L, 1);
        TreeUtil.postorderTraversal(list);
        installDetail.setInstallPlanDataList(list);


        return installDetail;
    }

    @Override
    public void downPlanTemplate(HttpServletResponse response) {
        DownloadExcelData downloadExcelData = new DownloadExcelData();
        downloadExcelData.setResponse(response);
        InstallPlanExcelFillAdapter template = new InstallPlanExcelFillAdapter();
        template.build(downloadExcelData).setParam(installPlanExcelService).fillData().downloadExcel();
    }

    @Override
    public void downInstallMeterTemplate(Integer id, HttpServletResponse response) {

        InstallPlan plan = installPlanMapper.findById(id);
        List<InstallListVo> list = installListMapper.getUnInstallList(id);

        DownloadExcelData data = new DownloadExcelData();
        data.setId(id);
        data.setResponse(response);
        data.setDownloadName(plan.getPlanName()+"批量导入模板");
        data.setFilePath(commonService.getExcelFilePath("template"));
        data.setInstallMeterDataList(convertInstallMeterData(list));

        InstallMeterExcelFillAdapter template = new InstallMeterExcelFillAdapter();
        template.build(data).fillData().downloadExcel();
    }

    private List<InstallMeterData> convertInstallMeterData(List<InstallListVo> list){
        return list.stream().map(
                item -> new InstallMeterData(item.getId(),item.getDoorNo(),item.getMeterCode(),item.getUserName(),item.getUserPhone(),item.getIdCard())
        ).collect(Collectors.toList());
    }

    @Override
    public InstallPlan createPlanExcel(ExcelData excelData) {
        InstallPlanInfoData infoData = excelData.getInstallPlanInfoData();
        // 2、小区查询
        Community community = null;
        if(StringUtils.isNotEmpty(infoData.getCommunityName())){
            community = communityService.findByName(excelData.getImportFile().getTenantId(),infoData.getCommunityName());
            if (community == null) throw BusinessException.builder("小区不存在");
        }


        // 3、公司部门查询
        Org companyOrg = orgService.findByName(excelData.getImportFile().getTenantId(),infoData.getCompanyName());
        if (companyOrg == null) throw BusinessException.builder("公司不存在");

        Org deptOrg = null;
        if(StringUtils.isNotEmpty(infoData.getDeptName())){
            deptOrg = orgService.findByParentIdAndName(companyOrg.getId(),infoData.getDeptName());
            if (deptOrg == null) throw BusinessException.builder("部门不存在");
        }

        // 4、产品（设备类型）查询
        String[] deviceType  = StringUtils.split(infoData.getDeviceTypeName(),"/");
        Product product = productService.getByName(deviceType[1],deviceType[2]);
        if (product == null) throw BusinessException.builder("设备型号不存在");

        InstallPlan installPlan = new InstallPlan();
        installPlan.setTenantId(excelData.getImportFile().getTenantId());
        installPlan.setPlanName(infoData.getCommunityName());
        if(community!=null)installPlan.setCommunityId(community.getId());
        installPlan.setCompanyOrgId(companyOrg.getId());
        if(deptOrg!=null)installPlan.setDeptOrgId(deptOrg.getId());
        installPlan.setProductId(product.getId());
        installPlan.setUnit(infoData.getUnit());
        installPlan.setPhone(infoData.getPhone());


        this.insertSelective(installPlan);

        return installPlan;
    }

    @Override
    public ResultMessage handleExcelData(InstallPlanExcelData data, ExcelData excelData) {
        log.info("installPlan saveExcelData data = {}",JSON.toJSONString(data));

        ResultMessage resultMessage = new ResultMessage();

        InstallPlanData InstallPlanDataBuilding = new InstallPlanData();
        if(excelData.getBuildingMap().containsKey(data.getBuildingName())){
            InstallPlanDataBuilding = excelData.getBuildingMap().get(data.getBuildingName());
        }else {
            InstallPlanDataBuilding.setId(idWorker.nextId());
            InstallPlanDataBuilding.setName(data.getBuildingName());
            InstallPlanDataBuilding.setParentId(0L);
            InstallPlanDataBuilding.setInstallPlanId(excelData.getInstallPlan().getId());
            InstallPlanDataBuilding.setType(1);
            InstallPlanDataBuilding.setStatus(1);
            excelData.getInstallPlanDataList().add(InstallPlanDataBuilding);
            excelData.getBuildingMap().put(data.getBuildingName(),InstallPlanDataBuilding);
        }




        if(StringUtils.isAllBlank(data.getUnitName()))excelData.setEnableUnit(1);

        InstallPlanData InstallPlanDataUnit = new InstallPlanData();
        String unitKey = data.getBuildingName() +"-"+ data.getUnitName();
        if(excelData.getUnitMap().containsKey(unitKey)){
            InstallPlanDataUnit = excelData.getUnitMap().get(unitKey);
        }else {
            InstallPlanDataUnit.setName(data.getUnitName());
            InstallPlanDataUnit.setId(idWorker.nextId());
            InstallPlanDataUnit.setParentId(InstallPlanDataBuilding.getId());
            InstallPlanDataUnit.setInstallPlanId(excelData.getInstallPlan().getId());
            InstallPlanDataUnit.setType(2);
            InstallPlanDataUnit.setStatus(1);
            excelData.getInstallPlanDataList().add(InstallPlanDataUnit);
            excelData.getUnitMap().put(unitKey,InstallPlanDataUnit);

        }


        InstallPlanData InstallPlanDataFloor = new InstallPlanData();
        String floorKey = data.getBuildingName() +"-"+ data.getUnitName()+"-"+data.getFloorName();
        if(excelData.getFloorMap().containsKey(floorKey)){
            InstallPlanDataFloor = excelData.getFloorMap().get(floorKey);
        }else {
            InstallPlanDataFloor.setName(data.getFloorName());
            InstallPlanDataFloor.setId(idWorker.nextId());
            InstallPlanDataFloor.setParentId(InstallPlanDataUnit.getId());
            InstallPlanDataFloor.setInstallPlanId(excelData.getInstallPlan().getId());
            InstallPlanDataFloor.setType(3);
            InstallPlanDataFloor.setStatus(1);
            excelData.getInstallPlanDataList().add(InstallPlanDataFloor);
            excelData.getFloorMap().put(floorKey,InstallPlanDataFloor);
        }


        InstallList installList = new InstallList();
        installList.setTenantId(excelData.getInstallPlan().getTenantId());
        installList.setInstallPlanId(excelData.getInstallPlan().getId());
        installList.setInstallPlanDataId(InstallPlanDataFloor.getId());
        installList.setDoorNo(data.getDoorNo());
        installList.setMeterCode(data.getFileNo());
        installList.setUserName(data.getUsername());
        installList.setUserPhone(data.getPhone());
        installList.setIdCard(data.getIdCard());
        installList.setIsInstalled(0);
        installList.setIsAccepted(0);
        installList.setStatus(1);
        installList.setCreateDate(LocalDateTime.now());
        installList.setUpdateDate(LocalDateTime.now());
        installList.setCreateBy("system");
        installList.setUpdateBy("system");
        excelData.getInstallList().add(installList);

        resultMessage.setStatus(true);
        return resultMessage;
    }


    @Override
    @Transactional
    public void saveExcelData(ExcelData excelData) {

        log.info("saveExcelData excelData:{}",JSON.toJSONString(excelData));

        if (!excelData.getInstallList().isEmpty()) {
            installListMapper.batchInsert(excelData.getInstallList());
        }
        if (!excelData.getInstallPlanDataList().isEmpty()) {
            installPlanDataMapper.batchInsert(excelData.getInstallPlanDataList());
        }

        //更新
        InstallPlan updateInstallPlan = new InstallPlan();
        updateInstallPlan.setId(excelData.getInstallPlan().getId());
        updateInstallPlan.setEnableUnit(excelData.getEnableUnit());
        this.updateByPrimaryKeySelective(updateInstallPlan);
    }

    @Override
    public PlanStatisticsVo statistics(Integer planId) {
        PlanStatisticsVo planStatisticsVo = new PlanStatisticsVo();
        StatisticsDeviceStatusVo deviceStatusVo = installPlanMapper.totalDeviceStatus(planId);

        StatisticsReadRateVo readRateVo =  meterReadWaterRecordMapper.totalReadRate(planId);

        planStatisticsVo.setReadRate(readRateVo);
        planStatisticsVo.setDeviceStatus(deviceStatusVo);
        return planStatisticsVo;
    }
}
