package com.ruoyi.ems.service.impl;

import com.huashe.common.utils.DateUtils;
import com.ruoyi.ems.domain.Area;
import com.ruoyi.ems.domain.AreaAttr;
import com.ruoyi.ems.domain.CoChargingConfig;
import com.ruoyi.ems.domain.MeterDevice;
import com.ruoyi.ems.enums.MeterObjType;
import com.ruoyi.ems.mapper.ElecConsumptionMapper;
import com.ruoyi.ems.mapper.MeterReadingMapper;
import com.ruoyi.ems.mapper.WaterConsumptionMapper;
import com.ruoyi.ems.model.ChargingBillVO;
import com.ruoyi.ems.model.ElecConsumptionVO;
import com.ruoyi.ems.model.QueryChargingBill;
import com.ruoyi.ems.model.QueryDevice;
import com.ruoyi.ems.model.QueryMeter;
import com.ruoyi.ems.model.WaterConsumptionVO;
import com.ruoyi.ems.service.IAreaAttrService;
import com.ruoyi.ems.service.IAreaService;
import com.ruoyi.ems.service.IChargingBillService;
import com.ruoyi.ems.service.ICoChargingConfigService;
import com.ruoyi.ems.service.IMeterDeviceService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 计费账单服务实现
 *
 * @author ruoyi
 * @date 2024-12-20
 */
@Service
public class ChargingBillServiceImpl implements IChargingBillService {

    private static final Logger logger = LoggerFactory.getLogger(ChargingBillServiceImpl.class);

    @Autowired
    private IAreaService areaService;

    @Autowired
    private IAreaAttrService attrService;

    @Autowired
    private ElecConsumptionMapper elecConsumptionMapper;

    @Autowired
    private WaterConsumptionMapper waterConsumptionMapper;

    @Autowired
    private MeterReadingMapper meterReadingMapper;

    @Autowired
    private ICoChargingConfigService coChargingConfigService;

    @Autowired
    private IMeterDeviceService meterDeviceService;

    @Override
    public ChargingBillVO selectOverviewTotal(QueryChargingBill param) {
        ChargingBillVO vo = new ChargingBillVO();

        try {
            Area area = areaService.selectAreaByCode(param.getAreaCode());
            CoChargingConfig config = coChargingConfigService.selectByArea(area.getAreaCode());
            vo.setObjCode(param.getAreaCode());
            vo.setObjName(area.getAreaName());
            vo.setMeteredTime(param.getStartTime());

            // 1. 商户自用数据计算
            if (param.getIncludeAuto()) {
                // 1.1 商户用电-自动抄表数据
                List<MeterDevice> elecADevs = meterDeviceService.selectMeterDeviceByObj(area.getAreaCode(), 45, 0,
                    MeterObjType.METER_AREA, null);
                ChargingBillVO.ElecAutoStatistics elecAStatistics = selectElecAutoStats(param, config, elecADevs);
                vo.setElecAutoStats(elecAStatistics);

                // 1.2 商户用水-自动抄表数据
                List<MeterDevice> waterADevs = meterDeviceService.selectMeterDeviceByObj(area.getAreaCode(), 70, 0,
                    MeterObjType.METER_AREA, null);
                ChargingBillVO.WaterStatistics waterAStatistics = selectWaterAutoStats(param, config, waterADevs);
                vo.setWaterAutoStats(waterAStatistics);
            }

            if (param.getIncludeManual()) {
                // 1.3 商户用电-手动抄表数据
                List<MeterDevice> elecMDevs = meterDeviceService.selectMeterDeviceByObj(area.getAreaCode(), 45, 1,
                    MeterObjType.METER_AREA, null);
                ChargingBillVO.ElecManualStatistics elecMStatistics = selectElecManualStats(param, config, elecMDevs);
                vo.setElecManualStats(elecMStatistics);

                // 1.4 商户用水-手动抄表数据
                List<MeterDevice> waterMDevs = meterDeviceService.selectMeterDeviceByObj(area.getAreaCode(), 70, 1,
                    MeterObjType.METER_AREA, null);
                ChargingBillVO.WaterStatistics waterMStatistics = selectWaterManualStats(param, config, waterMDevs);
                vo.setWaterManualStats(waterMStatistics);
            }

            if (param.getIncludeShared()) {
                // 2. 公摊数据计算
                ChargingBillVO.SharedData sharedData = calculateSharedData(param, config, false);
                vo.setSharedData(sharedData);
            }

            ChargingBillVO.TotalStatistics total = calculateTotal(vo);
            vo.setTotalStats(total);
        }
        catch (Exception e) {
            logger.error("查询个总览异常", e);
        }

        return vo;
    }

    @Override
    public List<ChargingBillVO> selectOverviewList(QueryChargingBill param) {
        List<ChargingBillVO> resultList = new ArrayList<>();

        try {
            // 解析时间范围
            Date startDate = DateUtils.stringToDate(param.getStartTime(), "yyyyMM");
            Date endDate = DateUtils.stringToDate(param.getEndTime(), "yyyyMM");

            // 按月循环查询
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startDate);

            while (!calendar.getTime().after(endDate)) {
                QueryChargingBill monthQuery = new QueryChargingBill();
                BeanUtils.copyProperties(param, monthQuery);
                String monthStr = DateUtils.dateToString(calendar.getTime(), "yyyyMM");
                monthQuery.setStartTime(monthStr);
                monthQuery.setEndTime(monthStr);

                ChargingBillVO bill = selectOverviewTotal(monthQuery);
                bill.setMeteredTime(monthStr);
                resultList.add(bill);

                // 下一个月
                calendar.add(Calendar.MONTH, 1);
            }

        }
        catch (Exception e) {
            logger.error("查询总览列表异常", e);
        }

        return resultList;
    }

    @Override
    public ChargingBillVO selectSellerEmsBill(QueryChargingBill param) {
        ChargingBillVO vo = new ChargingBillVO();

        try {
            Area area = areaService.selectAreaByCode(param.getAreaCode());
            String rootArea = getRootArea(area);
            CoChargingConfig config = coChargingConfigService.selectByArea(rootArea);
            vo.setObjCode(param.getAreaCode());
            vo.setObjName(area.getAreaName());
            vo.setMeteredTime(param.getStartTime());

            // 1. 商户自用数据计算
            if (param.getIncludeAuto()) {
                // 1.1 商户用电-自动抄表数据
                List<MeterDevice> elecADevs = meterDeviceService.selectMeterDeviceByObj(rootArea, 45, 0,
                    MeterObjType.METER_AREA, param.getAreaCode());
                ChargingBillVO.ElecAutoStatistics elecAStatistics = selectElecAutoStats(param, config, elecADevs);
                vo.setElecAutoStats(elecAStatistics);

                // 1.2 商户用水-自动抄表数据
                List<MeterDevice> waterADevs = meterDeviceService.selectMeterDeviceByObj(rootArea, 70, 0,
                    MeterObjType.METER_AREA, param.getAreaCode());
                ChargingBillVO.WaterStatistics waterAStatistics = selectWaterAutoStats(param, config, waterADevs);
                vo.setWaterAutoStats(waterAStatistics);
            }

            if (param.getIncludeManual()) {
                // 1.3 商户用电-手动抄表数据
                List<MeterDevice> elecMDevs = meterDeviceService.selectMeterDeviceByObj(rootArea, 45, 1,
                    MeterObjType.METER_AREA, param.getAreaCode());
                ChargingBillVO.ElecManualStatistics elecMStatistics = selectElecManualStats(param, config, elecMDevs);
                vo.setElecManualStats(elecMStatistics);

                // 1.4 商户用水-手动抄表数据
                List<MeterDevice> waterMDevs = meterDeviceService.selectMeterDeviceByObj(rootArea, 70, 1,
                    MeterObjType.METER_AREA, param.getAreaCode());
                ChargingBillVO.WaterStatistics waterMStatistics = selectWaterManualStats(param, config, waterMDevs);
                vo.setWaterManualStats(waterMStatistics);
            }

            if (param.getIncludeShared()) {
                // 2. 公摊数据计算
                ChargingBillVO.SharedData sharedData = calculateSharedData(param, config, true);
                vo.setSharedData(sharedData);
            }

            ChargingBillVO.TotalStatistics total = calculateTotal(vo);
            vo.setTotalStats(total);
        }
        catch (Exception e) {
            logger.error("查询个户账单异常", e);
        }

        return vo;
    }

    @Override
    public List<ChargingBillVO> selectSellerHistoryBills(QueryChargingBill param) {
        List<ChargingBillVO> resultList = new ArrayList<>();

        try {
            // 解析时间范围
            Date startDate = DateUtils.stringToDate(param.getStartTime(), "yyyyMM");
            Date endDate = DateUtils.stringToDate(param.getEndTime(), "yyyyMM");

            // 按月循环查询
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startDate);

            while (!calendar.getTime().after(endDate)) {
                QueryChargingBill monthQuery = new QueryChargingBill();
                BeanUtils.copyProperties(param, monthQuery);
                String monthStr = DateUtils.dateToString(calendar.getTime(), "yyyyMM");
                monthQuery.setStartTime(monthStr);
                monthQuery.setEndTime(monthStr);

                ChargingBillVO bill = selectSellerEmsBill(monthQuery);
                bill.setMeteredTime(monthStr);
                resultList.add(bill);

                // 下一个月
                calendar.add(Calendar.MONTH, 1);
            }

        }
        catch (Exception e) {
            logger.error("查询历史账单列表异常", e);
        }

        return resultList;
    }

    /**
     * 商户用电-自动抄表数据统计
     *
     * @param param     查询条件
     * @param elecADevs 商户绑定表计列表
     * @return 商用用电-自动抄表数据统计
     */
    private ChargingBillVO.ElecAutoStatistics selectElecAutoStats(QueryChargingBill param, CoChargingConfig config,
        List<MeterDevice> elecADevs) {
        ChargingBillVO.ElecAutoStatistics stats = new ChargingBillVO.ElecAutoStatistics();

        if (CollectionUtils.isNotEmpty(elecADevs)) {
            // 构建查询参数
            QueryMeter queryMeter = buildQueryMeter(param, 45);

            // 获取区域绑定的设备
            Set<String> devices = elecADevs.stream().map(MeterDevice::getDeviceCode).collect(Collectors.toSet());

            // 查询电量数据
            ElecConsumptionVO consumption = elecConsumptionMapper.selectAreaElecConsumptionSummaryByDevices(queryMeter,
                devices);

            if (consumption != null && consumption.getTotalElecQuantity() != null) {
                BeanUtils.copyProperties(consumption, stats);
                stats.setTotalQuantity(consumption.getTotalElecQuantity());
                stats.setTotalCost(calculateCost(consumption.getTotalElecQuantity(), 45, config));
            }
            else {
                stats.setTotalQuantity(BigDecimal.ZERO);
                stats.setTotalCost(BigDecimal.ZERO);
            }
        }
        else {
            stats.setTotalQuantity(BigDecimal.ZERO);
            stats.setTotalCost(BigDecimal.ZERO);
        }

        return stats;
    }

    /**
     * 商户用水-自动抄表数据统计
     *
     * @param param      查询条件
     * @param waterADevs 商户绑定表计列表
     * @return 商用用水-自动抄表数据统计
     */
    private ChargingBillVO.WaterStatistics selectWaterAutoStats(QueryChargingBill param, CoChargingConfig config,
        List<MeterDevice> waterADevs) {
        ChargingBillVO.WaterStatistics stats = new ChargingBillVO.WaterStatistics();

        if (CollectionUtils.isNotEmpty(waterADevs)) {
            // 构建查询参数
            QueryMeter queryMeter = buildQueryMeter(param, 70);

            // 获取区域绑定的设备
            Set<String> devices = waterADevs.stream().map(MeterDevice::getDeviceCode).collect(Collectors.toSet());

            // 查询电量数据
            WaterConsumptionVO consumption = waterConsumptionMapper.selectAreaWaterConsumptionSummaryByDevices(
                queryMeter, devices);

            if (consumption != null && consumption.getTotalWaterQuantity() != null) {
                stats.setTotalQuantity(consumption.getTotalWaterQuantity());
                stats.setTotalCost(calculateCost(consumption.getTotalWaterQuantity(), 70, config));
            }
            else {
                stats.setTotalQuantity(BigDecimal.ZERO);
                stats.setTotalCost(BigDecimal.ZERO);
            }
        }
        else {
            stats.setTotalQuantity(BigDecimal.ZERO);
            stats.setTotalCost(BigDecimal.ZERO);
        }

        return stats;
    }

    /**
     * 商户用电-自动抄表数据统计
     *
     * @param param     查询条件
     * @param elecMDevs 商户绑定表计列表
     * @return 商用用电-手动动抄表数据统计
     */
    private ChargingBillVO.ElecManualStatistics selectElecManualStats(QueryChargingBill param, CoChargingConfig config,
        List<MeterDevice> elecMDevs) {
        ChargingBillVO.ElecManualStatistics stats = new ChargingBillVO.ElecManualStatistics();

        if (CollectionUtils.isNotEmpty(elecMDevs)) {
            QueryMeter queryMeter = new QueryMeter();
            queryMeter.setAreaCode(param.getAreaCode());
            queryMeter.setStartRecTime(param.getStartTime());
            queryMeter.setEndRecTime(param.getEndTime());

            // 获取区域绑定的设备
            Set<String> devices = elecMDevs.stream().map(MeterDevice::getDeviceCode).collect(Collectors.toSet());

            BigDecimal quantity = meterReadingMapper.selectSummaryByDevices(queryMeter, devices);

            if (quantity != null) {
                stats.setTotalQuantity(quantity);
                stats.setTotalCost(calculateCost(quantity, 45, config));
            }
            else {
                stats.setTotalQuantity(BigDecimal.ZERO);
                stats.setTotalCost(BigDecimal.ZERO);
            }
        }
        else {
            stats.setTotalQuantity(BigDecimal.ZERO);
            stats.setTotalCost(BigDecimal.ZERO);
        }

        return stats;
    }

    /**
     * 商户用水-手动抄表数据统计
     *
     * @param param      查询条件
     * @param waterMDevs 商户绑定表计列表
     * @return 商用用水-手动抄表数据统计
     */
    private ChargingBillVO.WaterStatistics selectWaterManualStats(QueryChargingBill param, CoChargingConfig config,
        List<MeterDevice> waterMDevs) {
        ChargingBillVO.WaterStatistics stats = new ChargingBillVO.WaterStatistics();

        if (CollectionUtils.isNotEmpty(waterMDevs)) {
            QueryMeter queryMeter = new QueryMeter();
            queryMeter.setAreaCode(param.getAreaCode());
            queryMeter.setStartRecTime(param.getStartTime());
            queryMeter.setEndRecTime(param.getEndTime());

            // 获取区域绑定的设备
            Set<String> devices = waterMDevs.stream().map(MeterDevice::getDeviceCode).collect(Collectors.toSet());

            BigDecimal quantity = meterReadingMapper.selectSummaryByDevices(queryMeter, devices);

            if (quantity != null) {
                stats.setTotalQuantity(quantity);
                stats.setTotalCost(calculateCost(quantity, 70, config));
            }
            else {
                stats.setTotalQuantity(BigDecimal.ZERO);
                stats.setTotalCost(BigDecimal.ZERO);
            }
        }
        else {
            stats.setTotalQuantity(BigDecimal.ZERO);
            stats.setTotalCost(BigDecimal.ZERO);
        }

        return stats;
    }

    /**
     * 计算公摊数据
     */
    private ChargingBillVO.SharedData calculateSharedData(QueryChargingBill param, CoChargingConfig config,
        boolean isGtForArea) {
        ChargingBillVO.SharedData sharedData = new ChargingBillVO.SharedData();

        try {
            // 1. 查询公摊用量
            BigDecimal totalElecShared = BigDecimal.ZERO;
            BigDecimal totalWaterShared = BigDecimal.ZERO;

            // 查询公摊电表-自动表统计数据
            QueryDevice queryElecMDev = buildQueryDev(param.getAreaCode(), 45, 1, 0);
            List<MeterDevice> sharedElecMDevs = meterDeviceService.selectMeterDevByTag("MeterDev_Gt_45", queryElecMDev);
            ChargingBillVO.ElecAutoStatistics elecAStatistics = selectElecAutoStats(param, config, sharedElecMDevs);
            totalElecShared = totalElecShared.add(elecAStatistics.getTotalQuantity());

            // 查询公摊电表-手动表统计数据
            queryElecMDev = buildQueryDev(param.getAreaCode(), 45, 1, 1);
            sharedElecMDevs = meterDeviceService.selectMeterDevByTag("MeterDev_Gt_45", queryElecMDev);
            ChargingBillVO.ElecManualStatistics elecManualStatistics = selectElecManualStats(param, config,
                sharedElecMDevs);
            totalElecShared = totalElecShared.add(elecManualStatistics.getTotalQuantity());

            // 查询公摊水表-自动表统计数据
            QueryDevice queryWaterMDev = buildQueryDev(param.getAreaCode(), 70, 1, 0);
            List<MeterDevice> sharedWaterMDevs = meterDeviceService.selectMeterDevByTag("MeterDev_Gt_70",
                queryWaterMDev);
            ChargingBillVO.WaterStatistics waterAStatistics = selectWaterAutoStats(param, config, sharedWaterMDevs);
            totalWaterShared = totalWaterShared.add(waterAStatistics.getTotalQuantity());

            // 查询公摊电表-手动表统计数据
            queryWaterMDev = buildQueryDev(param.getAreaCode(), 70, 1, 1);
            sharedWaterMDevs = meterDeviceService.selectMeterDevByTag("MeterDev_Gt_70", queryWaterMDev);
            ChargingBillVO.WaterStatistics waterMStatistics = selectWaterManualStats(param, config, sharedWaterMDevs);
            totalWaterShared = totalWaterShared.add(waterMStatistics.getTotalQuantity());

            // 3. 计算当前区域应承担的公摊
            if (isGtForArea) {
                BigDecimal elecSharedForArea = calculateSharedForArea(totalElecShared, config.getElecGtComputeType(),
                    config.getAreaCode(), param.getAreaCode());
                BigDecimal waterSharedForArea = calculateSharedForArea(totalWaterShared, config.getWaterGtComputeType(),
                    config.getAreaCode(), param.getAreaCode());

                sharedData.setElecSharedQuantity(elecSharedForArea);
                sharedData.setElecSharedCost(calculateCost(elecSharedForArea, 45, config));
                sharedData.setWaterSharedQuantity(waterSharedForArea);
                sharedData.setWaterSharedCost(calculateCost(waterSharedForArea, 70, config));
                sharedData.setElecSharedType(config.getElecGtComputeType());
                sharedData.setWaterSharedType(config.getWaterGtComputeType());
                sharedData.setElecSharedTypeName(getSharedTypeName(config.getElecGtComputeType()));
                sharedData.setWaterSharedTypeName(getSharedTypeName(config.getWaterGtComputeType()));
            }
            else {
                sharedData.setElecSharedQuantity(totalElecShared);
                sharedData.setElecSharedCost(calculateCost(totalElecShared, 45, config));
                sharedData.setWaterSharedQuantity(totalWaterShared);
                sharedData.setWaterSharedCost(calculateCost(totalWaterShared, 70, config));
            }
        }
        catch (Exception e) {
            logger.error("计算公摊数据异常", e);
        }

        return sharedData;
    }

    /**
     * 计算合计
     */
    private ChargingBillVO.TotalStatistics calculateTotal(ChargingBillVO billVO) {
        ChargingBillVO.TotalStatistics total = new ChargingBillVO.TotalStatistics();

        // 电量合计
        BigDecimal elecQuantity = BigDecimal.ZERO;
        BigDecimal elecCost = BigDecimal.ZERO;

        if (billVO.getElecAutoStats() != null) {
            elecQuantity = elecQuantity.add(billVO.getElecAutoStats().getTotalQuantity() != null ?
                billVO.getElecAutoStats().getTotalQuantity() :
                BigDecimal.ZERO);
            elecCost = elecCost.add(billVO.getElecAutoStats().getTotalCost() != null ?
                billVO.getElecAutoStats().getTotalCost() :
                BigDecimal.ZERO);
        }

        if (billVO.getElecManualStats() != null) {
            elecQuantity = elecQuantity.add(billVO.getElecManualStats().getTotalQuantity() != null ?
                billVO.getElecManualStats().getTotalQuantity() :
                BigDecimal.ZERO);
            elecCost = elecCost.add(billVO.getElecManualStats().getTotalCost() != null ?
                billVO.getElecManualStats().getTotalCost() :
                BigDecimal.ZERO);
        }

        // 水量合计
        BigDecimal waterQuantity = BigDecimal.ZERO;
        BigDecimal waterCost = BigDecimal.ZERO;

        if (billVO.getWaterAutoStats() != null) {
            waterQuantity = waterQuantity.add(billVO.getWaterAutoStats().getTotalQuantity() != null ?
                billVO.getWaterAutoStats().getTotalQuantity() :
                BigDecimal.ZERO);
            waterCost = waterCost.add(billVO.getWaterAutoStats().getTotalCost() != null ?
                billVO.getWaterAutoStats().getTotalCost() :
                BigDecimal.ZERO);
        }

        if (billVO.getWaterManualStats() != null) {
            waterQuantity = waterQuantity.add(billVO.getWaterManualStats().getTotalQuantity() != null ?
                billVO.getWaterManualStats().getTotalQuantity() :
                BigDecimal.ZERO);
            waterCost = waterCost.add(billVO.getWaterManualStats().getTotalCost() != null ?
                billVO.getWaterManualStats().getTotalCost() :
                BigDecimal.ZERO);
        }

        // 公摊合计
        BigDecimal sharedCost = BigDecimal.ZERO;

        if (billVO.getSharedData() != null) {
            elecQuantity = elecQuantity.add(billVO.getSharedData().getElecSharedQuantity() != null ?
                billVO.getSharedData().getElecSharedQuantity() :
                BigDecimal.ZERO);
            elecCost = elecCost.add(billVO.getSharedData().getElecSharedCost() != null ?
                billVO.getSharedData().getElecSharedCost() :
                BigDecimal.ZERO);
            waterQuantity = waterQuantity.add(billVO.getSharedData().getWaterSharedQuantity() != null ?
                billVO.getSharedData().getWaterSharedQuantity() :
                BigDecimal.ZERO);
            waterCost = waterCost.add(billVO.getSharedData().getWaterSharedCost() != null ?
                billVO.getSharedData().getWaterSharedCost() :
                BigDecimal.ZERO);

            sharedCost = sharedCost.add(billVO.getSharedData().getElecSharedCost() != null ?
                billVO.getSharedData().getElecSharedCost() :
                BigDecimal.ZERO);
            sharedCost = sharedCost.add(billVO.getSharedData().getWaterSharedCost() != null ?
                billVO.getSharedData().getWaterSharedCost() :
                BigDecimal.ZERO);
        }

        total.setElecTotalQuantity(elecQuantity);
        total.setElecTotalCost(elecCost);
        total.setWaterTotalQuantity(waterQuantity);
        total.setWaterTotalCost(waterCost);
        total.setSharedTotalCost(sharedCost);
        total.setGrandTotalCost(elecCost.add(waterCost));

        return total;
    }

    /**
     * 构建QueryMeter参数
     */
    private QueryMeter buildQueryMeter(QueryChargingBill queryParam, Integer meterCls) {
        QueryMeter queryMeter = new QueryMeter();
        BeanUtils.copyProperties(queryParam, queryMeter);
        queryMeter.setMeterCls(meterCls);

        // 处理起始日期
        LocalDateTime startDateTime = YearMonth.parse(queryParam.getStartTime(), DateTimeFormatter.ofPattern("yyyyMM"))
            .atDay(1).atStartOfDay();
        queryMeter.setStartRecTime(startDateTime.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        // 处理结束日期
        LocalDateTime endDateTime = YearMonth.parse(queryParam.getEndTime(), DateTimeFormatter.ofPattern("yyyyMM"))
            .atEndOfMonth().atTime(23, 59, 59);
        queryMeter.setEndRecTime(endDateTime.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        return queryMeter;
    }

    /**
     * 计算费用
     */
    private BigDecimal calculateCost(BigDecimal quantity, Integer meterCls, CoChargingConfig config) {
        if (quantity == null || quantity.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }

        try {
            if (config == null) {
                return BigDecimal.ZERO;
            }

            BigDecimal unitPrice = BigDecimal.ZERO;
            if (meterCls == 45) {
                unitPrice = new BigDecimal(String.valueOf(config.getElecUnitPrice()));
            }
            else if (meterCls == 70) {
                unitPrice = new BigDecimal(String.valueOf(config.getWaterUnitPrice()));
            }

            return quantity.multiply(unitPrice).setScale(2, RoundingMode.HALF_UP);

        }
        catch (Exception e) {
            logger.error("计算费用异常", e);
            return BigDecimal.ZERO;
        }
    }

    private QueryDevice buildQueryDev(String areaCode, Integer meterCls, Integer enable, Integer colMode) {
        QueryDevice queryDevice = new QueryDevice();
        queryDevice.setAreaCode(areaCode);
        queryDevice.setMeterCls(meterCls);
        queryDevice.setDeviceEnable(enable);
        queryDevice.setColMode(colMode);
        return queryDevice;
    }

    /**
     * 根据公摊方式计算区域应承担的公摊量
     */
    private BigDecimal calculateSharedForArea(BigDecimal totalShared, Integer sharedType, String rootArea,
        String areaCode) {
        if (totalShared == null || totalShared.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }

        try {
            switch (sharedType) {
                case 0: // 不计入
                    return BigDecimal.ZERO;

                case 1: // 户数均摊
                    // 查询需要公摊的商户数量
                    List<Area> areas1 = areaService.selectAreaByTag("Area_Seller");
                    areas1 = areas1.stream()
                        .filter(area -> ArrayUtils.contains(StringUtils.split(area.getAncestors(), ","), rootArea))
                        .collect(Collectors.toList());
                    int count = areas1.size();
                    if (count > 0) {
                        return totalShared.divide(new BigDecimal(count), 2, RoundingMode.HALF_UP);
                    }
                    return BigDecimal.ZERO;

                case 2: // 面积均摊
                    List<Area> areas2 = areaService.selectAreaByTag("Area_Seller");
                    List<String> areaCodes = areas2.stream()
                        .filter(area -> ArrayUtils.contains(StringUtils.split(area.getAncestors(), ","), rootArea))
                        .map(Area::getAreaCode).collect(Collectors.toList());
                    List<AreaAttr> attrList = attrService.selectAreaAttrList(areaCodes);

                    BigDecimal totalA = BigDecimal.ZERO;
                    BigDecimal currentA = BigDecimal.ZERO;

                    for (AreaAttr attr : attrList) {
                        if (StringUtils.equals(areaCode, attr.getAreaCode())) {
                            currentA = new BigDecimal(String.valueOf(attr.getUsableArea()));
                        }

                        // 计算总面积
                        totalA = totalA.add(new BigDecimal(String.valueOf(attr.getUsableArea())));
                    }

                    if (totalA.compareTo(BigDecimal.ZERO) > 0) {
                        return totalShared.multiply(currentA).divide(totalA, 2, RoundingMode.HALF_UP);
                    }
                    return BigDecimal.ZERO;

                default:
                    return BigDecimal.ZERO;
            }
        }
        catch (Exception e) {
            logger.error("计算区域公摊异常", e);
            return BigDecimal.ZERO;
        }
    }

    /**
     * 获取公摊类型名称
     */
    private String getSharedTypeName(Integer type) {
        if (type == null) {
            return "未知";
        }

        switch (type) {
            case 0:
                return "不计入";
            case 1:
                return "户数均摊";
            case 2:
                return "面积均摊";
            default:
                return "未知";
        }
    }

    private String getRootArea(Area area) {
        String ancestors = area.getAncestors();
        String[] ancestorsArr = StringUtils.split(ancestors, ",");

        if (ancestorsArr.length < 2) {
            return area.getAreaCode();
        }
        else {
            return ancestorsArr[1];
        }
    }
}