package com.tofly.third.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tofly.common.core.util.StringUtil;
import com.tofly.third.common.exception.BusinessException;
import com.tofly.third.common.req.Cbxx;
import com.tofly.third.common.req.FkztReq;
import com.tofly.third.common.req.ZnbZlReq;
import com.tofly.third.common.res.FkztRes;
import com.tofly.third.common.res.WzxZlRes;
import com.tofly.third.common.res.ZnbRes;
import com.tofly.third.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class YccbService {

    @Autowired
    private YhKhjbxxService khjbxxService;
    @Autowired
    private YhCbkxxService cbkxxService;
    @Autowired
    private ZnbCbLogService znbCbLogService;
    @Autowired
    private ZnbCsjsLogService znbCsjsLogService;
    @Autowired
    private YyCblrService cblrService;
    @Autowired
    private YyZjzhService zjzhService;
    @Autowired
    private ZnbZlLogService znbZlLogService;
    @Autowired
    private ZnbHdLogService znbHdLogService;

    /**
     * 智能表抄表结算
     */
    @Transactional
    public ZnbRes cbtb(Cbxx cbxx) {
        String bjbh = cbxx.getBjbh();
        String yhbh = cbxx.getYhbh();
        YhCbkxx cbkxx = new YhCbkxx();
        YhKhjbxx yhKhjbxx;


        if (StringUtil.isNotEmpty(yhbh)) {
            yhKhjbxx = khjbxxService.getById(yhbh);
            if (ObjectUtil.isNull(yhKhjbxx)) {
                throw new BusinessException("用户信息不存在");
            }
            cbkxx = cbkxxService.lambdaQuery()
                    .eq(YhCbkxx::getYhbh, yhbh)
                    .eq(YhCbkxx::getJfzt, "1")
                    .list().stream().findFirst().orElse(null);
            if (ObjectUtil.isNull(cbkxx)) {
                throw new BusinessException("未查询到水表信息");
            }
            if (!cbkxx.getSbbh().equals(bjbh)) {
                cbxx.setBjbhpp("1");
            }
        } else {
            if (StringUtil.isNotEmpty(bjbh)) {
                cbkxx = cbkxxService.getCbkBySbbh(bjbh);
                if (ObjectUtil.isNull(cbkxx)) {
                    throw new BusinessException("未查询到水表信息");
                }
            }
            yhbh = cbkxx.getYhbh();
            yhKhjbxx = khjbxxService.getById(yhbh);
            if (ObjectUtil.isNull(yhKhjbxx)) {
                throw new BusinessException("用户信息不存在");
            }
        }

        // 1、自动抄表;
        ZnbCbLog znbcb = znbCbLogService.znbcb(yhKhjbxx, cbkxx, cbxx);
        BigDecimal znbcbCbZs = znbcb.getCbZs();
        cblrService.updateZnbZxds(cbkxx.getCbkid(), cbxx.getCbsj(), znbcbCbZs);

        // 2、水表算费,更新计算标志
        ZnbCsjsLog znbsf = znbCsjsLogService.znbsf(cbxx, znbcb, yhKhjbxx, cbkxx);
        znbcb.setJsbz("1");
        znbCbLogService.updateById(znbcb);

        // 3、自动扣费,更新资金账户、抄表结算中金额记录
        BigDecimal ye = zjzhService.znbkf(znbsf, yhbh);
        if (ye.compareTo(BigDecimal.ZERO) < 0) {
            // 4、扣减后余额小于零，发送关阀指令
            ZnbZlLog znbZlLog = znbZlLogService.addZlLog(ye, znbcb);
            ZnbRes znbRes = ZnbRes.buildByZlLog(bjbh, ye.toPlainString(), znbZlLog.getZlvalue());
            znbRes.setZlId(znbZlLog.getId());
            return znbRes;
        }
        return null;
    }

    /**
     * 智能表阀控指令同步
     */
    public void fkzlhd(ZnbZlReq znbZlReq) {
        ZnbZlLog zlLog = znbZlLogService.getById(znbZlReq.getZlId());
        if (ObjectUtil.isNull(zlLog)) {
            throw new BusinessException("未找到指令");
        }

        zlLog.setClCljg(znbZlReq.getClCljg());
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN);
        LocalDateTime clsj = LocalDateTime.parse(znbZlReq.getZlClSj(), formatter);
        zlLog.setClClsj(clsj);
        zlLog.setClRemessage(znbZlReq.getClRemessage());

        znbZlLogService.updateById(zlLog);

        // 回调指令
        znbHdLogService.hdzl(zlLog);
        cbkxxService.lambdaUpdate()
                .set(YhCbkxx::getFmzt, zlLog.getZlvalue().equals("1") ? "0" : "2")
                .in(YhCbkxx::getCbkid, zlLog.getCbkid())
                .update();
    }

    /**
     * 查询水表阀控状态
     */
    public FkztRes getFkzt(FkztReq fkztReq) {
        String zlId = fkztReq.getZlId();
        String bjbh = fkztReq.getBjbh();

        LambdaQueryWrapper<ZnbZlLog> wrapper = Wrappers.<ZnbZlLog>lambdaQuery()
                .eq(ZnbZlLog::getId, zlId)
                .eq(StrUtil.isNotEmpty(bjbh), ZnbZlLog::getBjbh, bjbh);
        ZnbZlLog znbZlLog = znbZlLogService.getOne(wrapper);

        if (ObjectUtil.isNull(znbZlLog)) {
            throw new BusinessException("未找到阀控指令");
        }

        FkztRes fkztRes = FkztRes.build(zlId, znbZlLog.getZlvalue());
        return fkztRes;
    }

    /**
     * 查询未执行指令
     */
    public WzxZlRes wzxml() {
        WzxZlRes wzxZlRes = new WzxZlRes();

        LambdaQueryWrapper<ZnbZlLog> queryWrapper = Wrappers.<ZnbZlLog>lambdaQuery()
                .eq(ZnbZlLog::getClCljg, "0")
                .eq(ZnbZlLog::getZltype, "1");
        List<ZnbZlLog> undoList = znbZlLogService.list(queryWrapper);

        if (CollectionUtil.isEmpty(undoList)) {
            return wzxZlRes;
        }

        Map<String, List<ZnbZlLog>> zlMap = undoList.stream().collect(Collectors.groupingBy(ZnbZlLog::getZlvalue));

        List<ZnbZlLog> gfZls = zlMap.get("0");
        if (CollectionUtil.isNotEmpty(gfZls)) {
            List<WzxZlRes.WzxZl> gfWzxZls = new ArrayList<>();
            gfZls.forEach(o -> {
                WzxZlRes.WzxZl wzxZl = WzxZlRes.WzxZl.build(o);
                gfWzxZls.add(wzxZl);
            });
            wzxZlRes.setGfWzxZls(gfWzxZls);
        }

        List<ZnbZlLog> kfZls = zlMap.get("1");
        if (CollectionUtil.isNotEmpty(kfZls)) {
            List<WzxZlRes.WzxZl> kfWzxZls = new ArrayList<>();
            kfZls.forEach(o -> {
                WzxZlRes.WzxZl wzxZl = WzxZlRes.WzxZl.build(o);
                kfWzxZls.add(wzxZl);
            });
            wzxZlRes.setKfWzxZls(kfWzxZls);
        }

        return wzxZlRes;
    }

}
