package com.energy.manage.service.service.windfield.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import com.alibaba.excel.EasyExcel;
import com.energy.manage.common.base.BaseServiceImpl;
import com.energy.manage.common.base.Page;
import com.energy.manage.common.constant.Constants;
import com.energy.manage.common.constant.redis.ManagerRedisKeyConstant;
import com.energy.manage.common.enums.DataSourceTypeEnum;
import com.energy.manage.common.enums.DeleteStatusEnum;
import com.energy.manage.common.enums.IdPrefixEnum;
import com.energy.manage.common.enums.TypeRelationEnum;
import com.energy.manage.common.po.area.AreaPO;
import com.energy.manage.common.po.company.WindCompanyPO;
import com.energy.manage.common.po.windenginemill.WindEngineMillPO;
import com.energy.manage.common.po.windfield.WindFieldPO;
import com.energy.manage.common.reponse.ResultResp;
import com.energy.manage.common.util.IdGeneratorUtil;
import com.energy.manage.service.domain.dto.anemometertower.AnemometerTowerDto;
import com.energy.manage.service.domain.dto.anemometertower.AnemometerTowerRelationDto;
import com.energy.manage.service.domain.dto.company.WindCompanyDelDto;
import com.energy.manage.service.domain.dto.company.WindCompanyDto;
import com.energy.manage.service.domain.dto.system.RoleUpdateOrganizationDto;
import com.energy.manage.service.domain.dto.windfield.*;
import com.energy.manage.service.domain.dto.windrelation.WindRelationDelDto;
import com.energy.manage.service.domain.dto.windrelation.WindRelationDto;
import com.energy.manage.service.domain.vo.anemometertower.AnemometerTowerByFieldVo;
import com.energy.manage.service.domain.vo.company.WindCompanyVo;
import com.energy.manage.service.domain.vo.excel.WindFieldExceVo;
import com.energy.manage.service.domain.vo.windenginegroup.WindFieldRatedCapacityVo;
import com.energy.manage.service.domain.vo.windenginemill.WindEngineMillVo;
import com.energy.manage.service.domain.vo.windfield.WindFieldNameVo;
import com.energy.manage.service.domain.vo.windfield.WindFieldPageVo;
import com.energy.manage.service.domain.vo.windfield.WindFieldResourceVo;
import com.energy.manage.service.domain.vo.windfield.WindFieldVo;
import com.energy.manage.service.domain.vo.windrelation.WindRelationVo;
import com.energy.manage.service.mappers.windfield.WindFieldMapper;
import com.energy.manage.service.service.anemometertower.AnemometerTowerService;
import com.energy.manage.service.service.area.AreaApiService;
import com.energy.manage.service.service.cache.CacheService;
import com.energy.manage.service.service.company.WindCompanyService;
import com.energy.manage.service.service.system.SysOrganizationAuthService;
import com.energy.manage.service.service.system.SysPermissionService;
import com.energy.manage.service.service.windfield.WindFieldResourceService;
import com.energy.manage.service.service.windfield.WindFieldService;
import com.energy.manage.service.service.windrelation.WindRelationService;
import com.energy.manage.service.util.DateUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;

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


@Slf4j
@Service
public class WindFieldServiceImpl extends BaseServiceImpl<WindFieldPO> implements WindFieldService {

    @Autowired
    private AreaApiService areaApiService;

    @Autowired
    private CacheService cacheService;

    @Autowired
    private WindCompanyService windCompanyService;

    @Autowired
    private WindFieldMapper windFieldMapper;

    @Autowired
    private WindRelationService windRelationServic;

    @Autowired
    private AnemometerTowerService anemometerTowerService;

    @Autowired
    private WindFieldResourceService windFieldResourceService;

    @Autowired
    private WindRelationService windRelationService;


    @Autowired
    private SysOrganizationAuthService sysOrganizationAuthService;

    @Autowired
    private SysPermissionService permissionService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createWindField(WindFieldDto windFieldDto, Integer roleId, Integer userId) {

        WindFieldPO windFieldPO = new WindFieldPO();
        BeanUtil.copyProperties(windFieldDto, windFieldPO);
        String number = IdPrefixEnum.WIND_FIELD_NUMBER.getCode().concat(windFieldDto.getAreaCode() + IdGeneratorUtil.zeroFillUtil(cacheService.incr(ManagerRedisKeyConstant.build(ManagerRedisKeyConstant.IDGENERATOR_CONSTANTS_KEY, IdPrefixEnum.WIND_FIELD_NUMBER.getCode()))));
        windFieldPO.setFieldCode(number);
        windFieldPO.setCreateTime(new Date());
        windFieldPO.setUpdateTime(new Date());
        windFieldPO.setState(Constants.GLOBAL_IN_USE);
        windFieldPO.setDelState(DeleteStatusEnum.NODELETE.getCode());
        windFieldPO.setDataSource(DataSourceTypeEnum.TERRACE_SOURCE.getCode());
        if (windFieldMapper.insertUseGeneratedKeys(windFieldPO) <= 0) {
            return false;
        }

        // 处理测风塔数据
        if (!CollectionUtils.isEmpty(windFieldDto.getAnemometerTowerRelationDtos())) {
            AnemometerTowerRelationDto anemometerTowerRelationDto = null;
            List<AnemometerTowerRelationDto> anemometerTowerDtos = Lists.newArrayList();
            for (WindFieldDto.AnemometerTowerRelationDto anemometerTowerRelationDto1 : windFieldDto.getAnemometerTowerRelationDtos()) {
                anemometerTowerRelationDto = new AnemometerTowerRelationDto();
                BeanUtils.copyProperties(anemometerTowerRelationDto1, anemometerTowerRelationDto);
                anemometerTowerRelationDto.setFieldCode(windFieldPO.getFieldCode());
                anemometerTowerDtos.add(anemometerTowerRelationDto);
            }
            anemometerTowerService.bathAnemometerTowerRelation(anemometerTowerDtos);
        }

        // 处理风场对应角色数据权限
        RoleUpdateOrganizationDto.OrganizationCode organizationCode = new RoleUpdateOrganizationDto.OrganizationCode();
        List<RoleUpdateOrganizationDto.OrganizationCode> organizationCodes = Lists.newArrayList();
        organizationCode.setCodeNumber(windFieldPO.getFieldCode());
        organizationCode.setCodeType(TypeRelationEnum.WIND_FIELD_NUMBER.getCode());
        organizationCodes.add(organizationCode);
        permissionService.updateRoleOrganization(roleId, organizationCodes, userId,0);

        return createWindRelation(windFieldPO);
    }


    /**
     * 创建关系数据
     *
     * @param po
     * @return
     */
    private boolean createWindRelation(WindFieldPO po) {
        WindRelationDto windRelationDto = new WindRelationDto();
        windRelationDto.setCodeNumber(po.getFieldCode());
        windRelationDto.setCodeName(po.getFieldName());
        windRelationDto.setParentCode(po.getCompanyCode());
        windRelationDto.setType(TypeRelationEnum.WIND_FIELD_NUMBER.getCode());
        return windRelationServic.createWindRelation(windRelationDto);
    }

    @SneakyThrows
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultResp windFieldImportData(MultipartFile file, WindFieldImportDataDto windFieldImportDataDto, Integer roleId, Integer userId) {
        List<WindFieldExceVo> windFieldExceVos = EasyExcel.read(file.getInputStream()).head(WindFieldExceVo.class).sheet().doReadSync();
        if (CollectionUtils.isEmpty(windFieldExceVos)) {
            return ResultResp.FAIL("未读取到文件数据，请核对数据准确性！");
        }
        // 过滤空数据
        List<WindFieldExceVo> windFieldExceVoList = windFieldExceVos.stream().filter(item -> !StringUtils.isEmpty(item.getFieldName())).collect(Collectors.toList());

        // 校验数据非空
        for (WindFieldExceVo exceVo : windFieldExceVoList) {
            if (StringUtils.isEmpty(exceVo.getCityName()) || StringUtils.isEmpty(exceVo.getProvinceName()) || StringUtils.isEmpty(exceVo.getAreaCode())) {
                return ResultResp.FAIL("当前导入风场数据未填写区域，请核查导入数据！");
            }
            if (exceVo.getLongitude() == null || exceVo.getLatitude() == null) {
                return ResultResp.FAIL("当前导入风场数据未填写经纬度，请核查导入数据！");
            }
        }

        // 校验是否有重复的风场名称
        Set<String> fieldNameStrings = windFieldExceVoList.stream().map(item -> item.getFieldName()).collect(Collectors.toSet());
        if (windFieldExceVoList.size() != fieldNameStrings.size()) {
            return ResultResp.FAIL("当前导入风场数据有重复风场名称，请核查导入数据！");
        }
        // 数据校验是否有重名风场
        List<String> fieldNames = windFieldExceVoList.stream().map(item -> item.getFieldName()).collect(Collectors.toList());
        Example queryExample = new Example(WindFieldPO.class);
        Example.Criteria criteria = queryExample.createCriteria();
        criteria.andIn("fieldName", fieldNames);
        criteria.andEqualTo("companyCode", windFieldImportDataDto.getCompanyCode());
        criteria.andEqualTo("delState", DeleteStatusEnum.NODELETE.getCode());
        int count = windFieldMapper.selectCountByExample(queryExample);
        if (count > 0) {
            return ResultResp.FAIL("当前项目公司中有已经存在的风场，请核查导入数据！");
        }

        // 查询区域id并赋值
        this.setWindFieldExceAreaId(windFieldExceVoList);

        WindFieldPO windFieldPO = null;
        List<WindFieldPO> list = Lists.newArrayList();
        for (WindFieldExceVo windFieldExceVo : windFieldExceVoList) {
            windFieldPO = new WindFieldPO();
            BeanUtil.copyProperties(windFieldExceVo, windFieldPO);
            String number = IdPrefixEnum.WIND_FIELD_NUMBER.getCode().concat(windFieldExceVo.getAreaCode() + IdGeneratorUtil.zeroFillUtil(cacheService.incr(ManagerRedisKeyConstant.build(ManagerRedisKeyConstant.IDGENERATOR_CONSTANTS_KEY, IdPrefixEnum.WIND_FIELD_NUMBER.getCode()))));
            windFieldPO.setFieldCode(number);
            windFieldPO.setCompanyCode(windFieldImportDataDto.getCompanyCode());
            windFieldPO.setCreateTime(new Date());
            windFieldPO.setUpdateTime(new Date());
            windFieldPO.setState(Constants.GLOBAL_IN_USE);
            windFieldPO.setDelState(DeleteStatusEnum.NODELETE.getCode());
            windFieldPO.setCreateBy(windFieldImportDataDto.getCreateBy());
            windFieldPO.setDataSource(DataSourceTypeEnum.UPLOAD_SOURCE.getCode());
            windFieldPO.setRatedCapacityNumber(Double.valueOf(0));
            list.add(windFieldPO);
        }
        if (CollectionUtils.isEmpty(list)) {
            return ResultResp.FAIL("数据处理异常！");
        }
        if (windFieldMapper.insertList(list) <= 0) {
            return ResultResp.FAIL();
        }

        // 处理风场对应角色数据权限
        RoleUpdateOrganizationDto.OrganizationCode organizationCode = null;
        List<RoleUpdateOrganizationDto.OrganizationCode> organizationCodes = Lists.newArrayList();
        for (WindFieldPO po : list) {
            organizationCode = new RoleUpdateOrganizationDto.OrganizationCode();
            organizationCode.setCodeNumber(po.getFieldCode());
            organizationCode.setCodeType(TypeRelationEnum.WIND_FIELD_NUMBER.getCode());
            organizationCodes.add(organizationCode);
        }
        permissionService.updateRoleOrganization(roleId, organizationCodes, userId,0);

        return bathCreateWindRelation(list) ? ResultResp.SUCCESS() : ResultResp.FAIL();
    }

    /**
     * 查询区域id并赋值
     *
     * @param windFieldExceVos
     */
    private void setWindFieldExceAreaId(List<WindFieldExceVo> windFieldExceVos) {
        // 区域id 赋值
        List<String> provinceNames = windFieldExceVos.stream().map(WindFieldExceVo::getProvinceName).distinct().collect(Collectors.toList());
        List<AreaPO> areaProvinces = areaApiService.getAllProvinceByName(1, provinceNames);
        for (WindFieldExceVo windFieldExceVo : windFieldExceVos) {
            for (AreaPO areaPO : areaProvinces) {
                if (windFieldExceVo.getProvinceName().equals(areaPO.getProvince())) {
                    windFieldExceVo.setProvinceId(areaPO.getAreaId());
                }

            }
        }
        List<String> cityNames = windFieldExceVos.stream().map(WindFieldExceVo::getCityName).distinct().collect(Collectors.toList());
        List<AreaPO> areaCitys = areaApiService.getAllProvinceByName(2, cityNames);
        for (WindFieldExceVo windFieldExceVo : windFieldExceVos) {
            for (AreaPO areaPO : areaCitys) {
                if (windFieldExceVo.getCityName().equals(areaPO.getCity())) {
                    windFieldExceVo.setCityId(areaPO.getAreaId());
                }
            }
        }
    }

    /**
     * 批量创建关系数据
     *
     * @param list
     * @return
     */
    private boolean bathCreateWindRelation(List<WindFieldPO> list) {

        WindRelationDto windRelationDto = null;
        List<WindRelationDto> windRelationDtos = Lists.newArrayList();
        for (WindFieldPO po : list) {
            windRelationDto = new WindRelationDto();
            windRelationDto.setCodeNumber(po.getFieldCode());
            windRelationDto.setCodeName(po.getFieldName());
            windRelationDto.setParentCode(po.getCompanyCode());
            windRelationDto.setType(TypeRelationEnum.WIND_FIELD_NUMBER.getCode());
            windRelationDtos.add(windRelationDto);
        }
        return windRelationServic.createWindRelationList(windRelationDtos);
    }


    @Override
    public Page<WindFieldPageVo> WindFieldListPage(WindFieldPageDto windFieldPageDto) {

        // 处理风场容量数据
        List<WindFieldRatedCapacityVo> windFieldRatedCapacityVos = windFieldMapper.selectRatedCapacityByState();
        if(!CollectionUtils.isEmpty(windFieldRatedCapacityVos)){
            windFieldMapper.batchUpdateRatedCapacity(windFieldRatedCapacityVos);
        }

        PageHelper.startPage(windFieldPageDto.getPageNum(), windFieldPageDto.getPageSize());
        List<WindFieldPageVo> list = windFieldMapper.selectWindFieldPageByfield(windFieldPageDto);
        Long total = org.apache.commons.collections.CollectionUtils.isEmpty(list) ? 0L : new PageInfo<>(list).getTotal();
        return Page.build(windFieldPageDto.getPageNum(), windFieldPageDto.getPageSize(), total, list);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delWindFieldByCompanyCode(String companyCode) {
        WindFieldPO windFieldPO = new WindFieldPO();
        windFieldPO.setDelState(DeleteStatusEnum.DELETE.getCode());
        Example queryExample = new Example(WindFieldPO.class);
        Example.Criteria criteria = queryExample.createCriteria();
        criteria.andEqualTo("companyCode", companyCode);
        return windFieldMapper.updateByExampleSelective(windFieldPO, queryExample) > 0;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delWindFieldById(String fieldCode) {
        WindFieldPO windFieldPO = new WindFieldPO();
        windFieldPO.setDelState(DeleteStatusEnum.DELETE.getCode());
        Example queryExample = new Example(WindFieldPO.class);
        Example.Criteria criteria = queryExample.createCriteria();
        criteria.andEqualTo("fieldCode", fieldCode);

        if (windFieldMapper.updateByExampleSelective(windFieldPO, queryExample) <= 0) {
            return false;
        }

        // 删除数据权限
        sysOrganizationAuthService.delSysOrganizationAuth(fieldCode, TypeRelationEnum.WIND_FIELD_NUMBER.getCode());

        WindRelationDelDto windRelationDelDto = new WindRelationDelDto();
        windRelationDelDto.setCodeNumber(fieldCode);
        windRelationDelDto.setType(TypeRelationEnum.WIND_FIELD_NUMBER.getCode());
        return windRelationService.delWindRelation(windRelationDelDto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateWindFieldStateById(WindFieldUpdateStateDto windFieldUpdateStateDto) {
        WindFieldPO windFieldPO = new WindFieldPO();
        windFieldPO.setState(windFieldUpdateStateDto.getState());
        Example queryExample = new Example(WindFieldPO.class);
        Example.Criteria criteria = queryExample.createCriteria();
        criteria.andEqualTo("fieldCode", windFieldUpdateStateDto.getFieldCode());
        return windFieldMapper.updateByExampleSelective(windFieldPO, queryExample) > 0;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateWindFieldNumber(String fieldCode) {
        return windFieldMapper.updateWindFieldEngineNumberByFieldCode(fieldCode) > 0;
    }

    @Override
    public WindFieldVo getWindFieldVo(WindFieldCodeDto windFieldCodeDto) {
        WindFieldPO windFieldPO = new WindFieldPO();
        windFieldPO.setFieldCode(windFieldCodeDto.getFieldCode());
        WindFieldPO po = windFieldMapper.selectOne(windFieldPO);
        if (po == null) {
            return null;
        }
        WindFieldVo windFieldVo = new WindFieldVo();
        BeanUtil.copyProperties(po, windFieldVo);

        // 查询企业对象
        WindCompanyDelDto windCompanyDelDto = new WindCompanyDelDto();
        windCompanyDelDto.setCompanyCode(po.getCompanyCode());
        WindCompanyVo windCompanyVo = windCompanyService.getWindCompany(windCompanyDelDto);
        if (windCompanyVo != null) {
            windFieldVo.setCompanyName(windCompanyVo.getCompanyName());
        }

        //测风塔数据
        List<AnemometerTowerByFieldVo> list = anemometerTowerService.getAnemometerTowerByField(windFieldCodeDto.getFieldCode());
        if (!CollectionUtils.isEmpty(list)) {
            windFieldVo.setAnemometerTowerByFieldVos(list);
        }

        //查询风场对应资源信息
        List<WindFieldResourceVo> windFieldResourceVos = windFieldResourceService.getWindFieldResourceByFieldCode(windFieldCodeDto.getFieldCode());
        if (!CollectionUtils.isEmpty(windFieldResourceVos)) {
            windFieldVo.setWindFieldResourceVos(windFieldResourceVos);
        }

        return windFieldVo;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateWindField(WindFieldUpdateDto windFieldUpdateDto) {

        WindFieldPO windFieldPO = new WindFieldPO();
        BeanUtil.copyProperties(windFieldUpdateDto, windFieldPO);

        Example queryExample = new Example(WindFieldPO.class);
        Example.Criteria criteria = queryExample.createCriteria();
        criteria.andEqualTo("fieldCode", windFieldPO.getFieldCode());

        boolean flg = true;
        if (windFieldMapper.updateByExampleSelective(windFieldPO, queryExample) <= 0) {
            return false;
        }

        // 修改树关系表
        if (!StringUtils.isEmpty(windFieldUpdateDto.getFieldCode()) && !StringUtils.isEmpty(windFieldUpdateDto.getFieldName())) {
            WindRelationDto windRelationDto = new WindRelationDto();
            windRelationDto.setCodeName(windFieldUpdateDto.getFieldName());
            windRelationDto.setCodeNumber(windFieldUpdateDto.getFieldCode());
            flg = windRelationServic.updateWindRelationName(windRelationDto);
            if (!flg) {
                log.warn("修改风场关系树表失败！");
            }
        }

        // 处理测风塔数据
        if (!CollectionUtils.isEmpty(windFieldUpdateDto.getAnemometerTowerRelationDtos())) {
            anemometerTowerService.deltAnemometerTowerRelationByField(windFieldUpdateDto.getFieldCode());
            // 处理测风塔数据
            if (!CollectionUtils.isEmpty(windFieldUpdateDto.getAnemometerTowerRelationDtos())) {
                AnemometerTowerRelationDto anemometerTowerRelationDto = null;
                List<AnemometerTowerRelationDto> anemometerTowerDtos = Lists.newArrayList();
                for (WindFieldUpdateDto.AnemometerTowerRelationDto anemometerTowerRelationDto1 : windFieldUpdateDto.getAnemometerTowerRelationDtos()) {
                    anemometerTowerRelationDto = new AnemometerTowerRelationDto();
                    BeanUtils.copyProperties(anemometerTowerRelationDto1, anemometerTowerRelationDto);
                    anemometerTowerRelationDto.setFieldCode(windFieldUpdateDto.getFieldCode());
                    anemometerTowerDtos.add(anemometerTowerRelationDto);
                }
                flg = anemometerTowerService.bathAnemometerTowerRelation(anemometerTowerDtos);
                if (!flg) {
                    log.warn("修改测风塔关系表失败！");
                }
            }
        }

        return true;
    }

    @Override
    public List<WindFieldVo> getWindFieldVos(String companyCode) {
        WindFieldPO windFieldPO = new WindFieldPO();
        windFieldPO.setCompanyCode(companyCode);
        List<WindFieldPO> list = windFieldMapper.select(windFieldPO);

        WindFieldVo windFieldVo = null;
        List<WindFieldVo> windFieldVos = Lists.newArrayList();
        for (WindFieldPO windFieldPO1 : list) {
            windFieldVo = new WindFieldVo();
            BeanUtil.copyProperties(windFieldPO1, windFieldVo);
            windFieldVos.add(windFieldVo);
        }
        return windFieldVos;
    }

    @Override
    public List<WindFieldNameVo> getWindFieldNames(Integer userId, Integer roleId) {
        List<WindFieldNameVo> list = windFieldMapper.selectWindFieldNamesByUserId(userId, roleId);
        return list;
    }

    @Override
    public List<Map<String, Object>> getWindFieldTree() {
        return windRelationServic.getWindRelationTree();
    }


    @Override
    public WindFieldPO getWindFieldPOByFieldName(String fieldName) {
        Example queryExample = new Example(WindFieldPO.class);
        Example.Criteria criteria = queryExample.createCriteria();
        criteria.andEqualTo("fieldName", fieldName);
        criteria.andEqualTo("delState", DeleteStatusEnum.NODELETE.getCode());
        return windFieldMapper.selectOneByExample(queryExample);

    }


}
