package com.iformall.schedule;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.iformall.domain.dto.KwMeterDataDto;
import com.iformall.domain.po.*;
import com.iformall.domain.vo.KwMeterDataVo;
import com.iformall.enums.*;
import com.iformall.mapper.KwMerchantMeterMapper;
import com.iformall.mapper.WxMerchantPowerBillConfigMapper;
import com.iformall.mapper.WxMerchantShopMapper;
import com.iformall.mapper.WxPowerBillAutoConfigMapper;
import com.iformall.service.WxBillDailyService;
import com.iformall.service.kw.KwMeterDataService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author gongbiao
 */

@Component
public class PowerBillAutoBuildSchedule {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private WxPowerBillAutoConfigMapper wxPowerBillAutoConfigMapper;

    @Autowired
    private WxMerchantPowerBillConfigMapper wxMerchantPowerBillConfigMapper;

    @Autowired
    private WxBillDailyService wxBillDailyService;

    @Autowired
    private WxMerchantShopMapper wxMerchantShopMapper;

    @Autowired
    KwMeterDataService kwMeterDataService;

    @Autowired
    KwMerchantMeterMapper kwMerchantMeterMapper;

    /**
     * 每天5点执行
     */
    @Scheduled(cron = "0 0 5 * * ?")
    public void powerBillAutoConfigStart() {
        logger.info("自动生成电费账单开始....");
        int dayOfMonth = LocalDate.now().getDayOfMonth();
        List<WxPowerBillAutoConfig> wxPowerBillAutoConfigs = wxPowerBillAutoConfigMapper.selectList(new QueryWrapper(null));
        wxPowerBillAutoConfigs = wxPowerBillAutoConfigs.stream().filter(config -> StringUtils.isNotEmpty(config.getUnitPrice())
                        && StringUtils.isNotEmpty(config.getBuildDay())
                        && StringUtils.isNotEmpty(config.getReceiveDay()))
                .collect(Collectors.toList());
        for (int i = 0; i < wxPowerBillAutoConfigs.size(); i++) {
            WxPowerBillAutoConfig wxPowerBillAutoConfig = wxPowerBillAutoConfigs.get(i);
            if (String.valueOf(dayOfMonth).equals(wxPowerBillAutoConfig.getBuildDay())) {
                merchantPowerBillConfigStart(wxPowerBillAutoConfig);
            }
        }
        logger.info("自动生成电费账单结束....");
    }

    private void merchantPowerBillConfigStart(WxPowerBillAutoConfig wxPowerBillAutoConfig) {
        WxMerchantPowerBillConfig wxMerchantPowerBillConfig = new WxMerchantPowerBillConfig();
        wxMerchantPowerBillConfig.setTenantId(wxPowerBillAutoConfig.getTenantId());
        List<WxMerchantPowerBillConfig> wxMerchantPowerBillConfigs = wxMerchantPowerBillConfigMapper.selectList(new QueryWrapper(wxMerchantPowerBillConfig));
        for (int i = 0; i < wxMerchantPowerBillConfigs.size(); i++) {
            buildPowerBill(wxMerchantPowerBillConfigs.get(i), wxPowerBillAutoConfig);
        }
    }

    private void buildPowerBill(WxMerchantPowerBillConfig wxMerchantPowerBillConfig, WxPowerBillAutoConfig wxPowerBillAutoConfig) {

        Map<String, Date> monthDate = getLastMonthDate();
        Date startdate = monthDate.get("startdate");
        Date enddate = monthDate.get("enddate");
        Date lastdate = monthDate.get("lastdate");
        MallUserInfo mallUserInfo = getMallUserInfo();
        WxBillDaily wxBillDaily = getBillDaily(wxMerchantPowerBillConfig);
        Date receiveDate = getReceiveDate(Integer.parseInt(wxPowerBillAutoConfig.getReceiveDay()));
        long receivePay;
        String unitPrice;
        long usedPower = 0L;
        Long merchantId = wxMerchantPowerBillConfig.getMerchantId();
        if (wxMerchantPowerBillConfig.getBuildWay().equals(EnumPowerBillBuildWay.METER.getCode())) {
            //根据日期拉取电量 单价 * 电量 = 电费
            usedPower = getUsedPower(startdate, lastdate, merchantId);
            if (usedPower == 0) {
                logger.info("没有电量使用，不生成账单>>>>商户ID：" + merchantId);
                return;
            }
            //按电表 单价从商户配置表中取 因为会修改
            unitPrice = wxMerchantPowerBillConfig.getPrice();
            receivePay = new BigDecimal(unitPrice).multiply(new BigDecimal(usedPower))
                    .setScale(0, RoundingMode.HALF_EVEN).longValue();
        } else {
            //按固定金额 单位从统一配置表中取
            unitPrice = wxPowerBillAutoConfig.getUnitPrice();
            String price = wxMerchantPowerBillConfig.getPrice();
            receivePay = new BigDecimal(price).multiply(new BigDecimal(100)).longValue();
        }

        JSONArray priceDetals = new JSONArray();
        JSONObject priceDetal = new JSONObject();
        priceDetal.put("key", "unitPrice");
        priceDetal.put("value", unitPrice);
        priceDetals.add(priceDetal);
        priceDetal = new JSONObject();
        priceDetal.put("key", "power");
        priceDetal.put("value", new BigDecimal(usedPower).divide(new BigDecimal(100)).toPlainString());
        priceDetals.add(priceDetal);

        wxBillDaily.setReceivePay(receivePay);
        wxBillDaily.setNeedPay(receivePay);
        wxBillDaily.setReceiveDate(receiveDate);
        wxBillDaily.setStarttime(startdate);
        wxBillDaily.setEndtime(enddate);
        wxBillDaily.setPriceDetail(priceDetals.toJSONString());
        wxBillDaily.setBuildWay(EnumBillDailyBuildWay.AUTO.getCode());
        wxBillDailyService.saveOrUpdate(wxBillDaily, mallUserInfo);

    }

    private int getUsedPower(Date startdate, Date lastdate, Long merchantId) {
        KwMerchantMeter kwMerchantMeter = new KwMerchantMeter();
        kwMerchantMeter.setMerchantId(merchantId);
        kwMerchantMeter.setStatus(EnumMerchantMeterStatus.VALID.getCode());
        List<KwMerchantMeter> merchantMeterList = kwMerchantMeterMapper.selectList(new QueryWrapper(kwMerchantMeter));
        int usedPower = 0;
        if (!merchantMeterList.isEmpty()) {
            int size = merchantMeterList.size();
            for (int i = 0; i < size; i++) {
                KwMerchantMeter merchantMeter = merchantMeterList.get(i);
                KwMeterDataDto kwMeterDataDto = new KwMeterDataDto();
                kwMeterDataDto.setTenantId(merchantMeter.getTenantId());
                kwMeterDataDto.setMeterId(merchantMeter.getMeterId());
                kwMeterDataDto.setStartTime(startdate);
                kwMeterDataDto.setEndTime(lastdate);
                KwMeterDataVo power = kwMeterDataService.getPower(kwMeterDataDto);
                if (power != null) {
                    Optional<Integer> usedPowerOptional = Optional.ofNullable(power.getUsedPower());
                    Integer integer = usedPowerOptional.orElse(0);
                    usedPower += integer;
                }
            }
        }
        return usedPower;
    }

    private WxBillDaily getBillDaily(WxMerchantPowerBillConfig wxMerchantPowerBillConfig) {
        WxBillDaily wxBillDaily = new WxBillDaily();
        Long merchantId = wxMerchantPowerBillConfig.getMerchantId();
        wxBillDaily.setShopId(getShopId(merchantId));
        wxBillDaily.setTenantId(wxMerchantPowerBillConfig.getTenantId());
        wxBillDaily.setMerchantId(merchantId);
        wxBillDaily.setMerchantName(wxMerchantPowerBillConfig.getMerchantName());
        wxBillDaily.setType(EnumBillDailyType.POWER.getCode());
        wxBillDaily.setRentShopType(wxMerchantPowerBillConfig.getMerchantType());
        wxBillDaily.setPay(0L);
        wxBillDaily.setPayWay(EnumBillPayWay.OTHER.getCode());
        return wxBillDaily;
    }

    private Map<String, Date> getLastMonthDate() {
        ZoneId zoneId = ZoneOffset.systemDefault();
        LocalDate now = LocalDate.now().minusMonths(1L);
        now = now.with(TemporalAdjusters.firstDayOfMonth());
        Instant start = now.atStartOfDay().atZone(zoneId).toInstant();
        Date first = Date.from(start);
        now = now.with(TemporalAdjusters.lastDayOfMonth());
        Instant end = now.atStartOfDay().atZone(zoneId).toInstant();
        Date last = Date.from(end);
        now = now.with(TemporalAdjusters.firstDayOfNextMonth());
        Instant lastday = now.atStartOfDay().atZone(zoneId).toInstant();
        Date next = Date.from(lastday);
        Map<String, Date> dateMap = new HashMap<>(3);
        dateMap.put("startdate", first);
        dateMap.put("enddate", last);
        dateMap.put("lastdate", next);
        return dateMap;
    }

    private Date getReceiveDate(int day) {
        ZoneId zoneId = ZoneOffset.systemDefault();
        LocalDate of = LocalDate.of(LocalDate.now().getYear(), LocalDate.now().getMonth(), day);
        Instant instant = of.atStartOfDay().atZone(zoneId).toInstant();
        return Date.from(instant);
    }

    private Long getShopId(Long merchantId) {
        WxMerchantShop wxMerchantShop = new WxMerchantShop();
        wxMerchantShop.setMerchantId(merchantId);
        wxMerchantShop.setIsDel(EnumDelStatus.NOT_DEL.getCode());
        List<WxMerchantShop> select = wxMerchantShopMapper.selectList(new QueryWrapper(wxMerchantShop));
        if (!select.isEmpty()) {
            return select.get(0).getShopId();
        }
        return 0L;
    }

    private MallUserInfo getMallUserInfo() {
        MallUserInfo mallUserInfo = new MallUserInfo();
        mallUserInfo.setId(0L);
        mallUserInfo.setName("系统生成");
        mallUserInfo.setPhone("0");
        return mallUserInfo;
    }

}