package com.yeejoin.amos.boot.module.elevator.biz.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yeejoin.amos.boot.module.elevator.api.dto.RescueStationDto;
import com.yeejoin.amos.boot.module.elevator.api.dto.TzBaseEnterpriseInfoDto;
import com.yeejoin.amos.boot.module.elevator.api.entity.RescueStation;
import com.yeejoin.amos.boot.module.elevator.api.mapper.RescueStationMapper;
import com.yeejoin.amos.boot.module.elevator.api.service.IRescueStationService;
import com.yeejoin.amos.boot.module.elevator.api.vo.RescueStationImportVo;
import com.yeejoin.amos.boot.module.elevator.biz.utils.BeanDtoVoUtils;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.RegionModel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.utils.ResponseHelper;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

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

/**
*  服务实现类
*
* @author tb
* @date 2021-06-01
*/
@Service
public class RescueStationServiceImpl extends BaseService<RescueStationDto, RescueStation, RescueStationMapper> implements IRescueStationService {

    @Autowired
    RescueStationMapper rescueStationMapper;
    @Autowired
    IRescueStationService iRescueStationService;
    @Autowired
    TzBaseEnterpriseInfoServiceImpl baseEnterpriseInfoService;

    private final String excelErrorStr = "Excel 第[%s]行：%s";

    @Override
    public List<RescueStationDto> getListByLatLonDistance(String lat, String lon, Integer distance) {
        return rescueStationMapper.getListByLatLonDistance(lat,lon,distance);
    }

    @Override
    public List<RescueStationDto> selectExportData(String exportId) {
        List<String> ids = null;
        if(StringUtils.isNotEmpty(exportId)) {
            String[] idStr = exportId.split(",");
            ids = Arrays.asList(idStr);
        }
        return baseMapper.selectExportData(ids);
    }

    @Override
    public IPage<RescueStation> getRescueStationList(IPage<RescueStation> page,RescueStationDto dto) {
        return rescueStationMapper.getRescueStationList(page,dto);
    }



    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseModel<Object> expertDataImport(MultipartFile file, AgencyUserModel userModel) {

        List<RegionModel> regionModels1 = Systemctl.regionClient.queryByLevel("1").getResult();
        Map<String, String> provinceResult = regionModels1.stream().collect(Collectors.toMap(RegionModel::getRegionName, region -> String.valueOf(region.getRegionCode())));

        List<RegionModel> regionModels2 = Systemctl.regionClient.queryByLevel("2").getResult();
        Map<String, String> cityResult = regionModels2.stream().collect(Collectors.toMap(RegionModel::getRegionName, region -> String.valueOf(region.getRegionCode())));

        List<RegionModel> regionModels3 = Systemctl.regionClient.queryByLevel("3").getResult();
        Map<String, String> districtResult = regionModels3.stream().collect(Collectors.toMap(RegionModel::getRegionName, region -> String.valueOf(region.getRegionCode())));


        try {
            InputStream inputStream = file.getInputStream();
            ExcelReader excelReader = EasyExcel.read(inputStream).build();
            List<ReadSheet> sheetList = excelReader.excelExecutor().sheetList();

            ReadSheet sheet = sheetList.get(0);
            if (ValidationUtil.isEmpty(sheet)) {
                throw new BadRequest("Excel导入模板有误，请重写下载导入！");
            }

            ArrayList<RescueStation> dataList = new ArrayList<>();

            EasyExcel.read(file.getInputStream(), RescueStationImportVo.class, new AnalysisEventListener<RescueStationImportVo>() {
                @Override
                public void invoke(RescueStationImportVo data, AnalysisContext context) {
                    // 数据检查
                    checkExcelData(data, context);
                    // 数据处理
                    RescueStation rescueStation = JSON.parseObject(JSON.toJSONString(data), RescueStation.class);
                    dataList.add(rescueStation);
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                }
            }).headRowNumber(2).sheet().doRead();

            excelReader.finish();

            // 完善数据 + 保存数据
            for (RescueStation rescueStation : dataList) {
                rescueStation.setRegionCode(provinceResult.get(rescueStation.getProvince()) + "#" + cityResult.get(rescueStation.getCity()) + "#" + districtResult.get(rescueStation.getDistrict()));
                rescueStation.setIsDelete(Boolean.FALSE);
                rescueStation.setRecDate(new Date());
                rescueStation.setRecUserName(userModel.getUserName());
                rescueStation.setRecUserId(userModel.getUserId());
            }
            this.saveOrUpdateBatch(dataList);

            return ResponseHelper.buildResponse("success");
        } catch (Exception e) {
            throw new BadRequest(e.getCause().getMessage());
        }
    }

    public void checkExcelData(RescueStationImportVo data, AnalysisContext context) {
        ReadRowHolder readRowHolder = context.readRowHolder();
        int rowIndex = readRowHolder.getRowIndex() + 1;
        checkNotBlank(data.getName(), "应急救援机构名称不能为空！", rowIndex);
        checkNotBlank(data.getProvince(), "所属省不能为空！", rowIndex);
        checkNotBlank(data.getCity(), "所属地市不能为空！", rowIndex);
        checkNotBlank(data.getDistrict(), "所属区县不能为空！", rowIndex);
        checkNotBlank(data.getAddress(), "地址不能为空！", rowIndex);
        checkNotBlank(data.getAffiliatedUnitCreditCode(), "所属单位统一行用代码不能为空！", rowIndex);
        checkNotBlank(data.getAffiliatedUnit(), "所属单位名称不能为空！", rowIndex);
        // 所属单位检查
        TzBaseEnterpriseInfoDto infoByUseCode = baseEnterpriseInfoService.getInfoByUseCode(data.getAffiliatedUnitCreditCode());
        if (ValidationUtil.isEmpty(infoByUseCode)) {
            throw new BadRequest(String.format(excelErrorStr, rowIndex,"所属单位系统中不存在！"));
        }
        data.setAffiliatedUnit(infoByUseCode.getUseUnit());
        data.setAffiliatedUnitId(infoByUseCode.getSequenceNbr());
    }

    /**
     * 检查字段是否为空，如果为空则追加错误信息到result
     *
     * @param value        待检查字段
     * @param errorMessage 错误信息
     * @param rowIndex     行
     */
    private void checkNotBlank(String value, String errorMessage, int rowIndex) {
        if (StringUtils.isBlank(value)) {
            throw new BadRequest(String.format(excelErrorStr, rowIndex,errorMessage));
        }
    }


    public Boolean saveRescueStation(RescueStationDto rescueStationDto){
        RescueStation rescueStation = BeanDtoVoUtils.convert(rescueStationDto, RescueStation.class);
        rescueStation.setRecUserId(RequestContext.getExeUserId());
        rescueStation.setRecDate(new Date());
        boolean save =false;
        LambdaQueryWrapper<RescueStation> wrapper = new LambdaQueryWrapper<>();
        if (!ValidationUtil.isEmpty(rescueStation)) {
            wrapper.eq(!ValidationUtil.isEmpty(rescueStation.getName()),RescueStation::getName,rescueStation.getName())
                    .eq(!ValidationUtil.isEmpty(rescueStation.getCity()),RescueStation::getCity,rescueStation.getCity())
                    .eq(!ValidationUtil.isEmpty(rescueStation.getDistrict()),RescueStation::getDistrict,rescueStation.getDistrict())
                    .eq(!ValidationUtil.isEmpty(rescueStation.getAffiliatedUnit()),RescueStation::getAffiliatedUnit,rescueStation.getAffiliatedUnit())
                    .eq(!ValidationUtil.isEmpty(rescueStation.getAddress()),RescueStation::getAddress,rescueStation.getAddress())
                    .eq(!ValidationUtil.isEmpty(rescueStation.getAffiliatedUnitId()),RescueStation::getAffiliatedUnitId,rescueStation.getAffiliatedUnitId())
                    .eq(!ValidationUtil.isEmpty(rescueStation.getLatitude()),RescueStation::getLatitude,rescueStation.getLatitude())
                    .eq(!ValidationUtil.isEmpty(rescueStation.getLongitude()),RescueStation::getLongitude,rescueStation.getLongitude())
                    .eq(!ValidationUtil.isEmpty(rescueStation.getPrincipal()),RescueStation::getPrincipal,rescueStation.getPrincipal())
                    .eq(!ValidationUtil.isEmpty(rescueStation.getPrincipalPhone()),RescueStation::getPrincipalPhone,rescueStation.getPrincipalPhone())
                    .eq(!ValidationUtil.isEmpty(rescueStation.getProvince()),RescueStation::getProvince,rescueStation.getProvince())
                    .eq(!ValidationUtil.isEmpty(rescueStation.getRegionCode()),RescueStation::getRegionCode,rescueStation.getRegionCode())
                    .eq(!ValidationUtil.isEmpty(rescueStation.getRescueLeader()),RescueStation::getRescueLeader,rescueStation.getRescueLeader())
                    .eq(!ValidationUtil.isEmpty(rescueStation.getRescueLeaderPhone()),RescueStation::getRescueLeaderPhone,rescueStation.getRescueLeaderPhone());
            List<RescueStation> rescueStations = rescueStationMapper.selectList(wrapper);
            if (ValidationUtil.isEmpty(rescueStations) ) {
                save = iRescueStationService.save(rescueStation);
            }

        }
        return save;
    }
}
