package com.xhpc.activity.service.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.xhpc.activity.domain.XhpcClearingHistoryOrderDomain;
import com.xhpc.activity.domain.XhpcOperatorDomain;
import com.xhpc.activity.mapper.XhpcClearingBankMapper;
import com.xhpc.activity.mapper.XhpcClearingCheckoutMapper;
import com.xhpc.activity.mapper.XhpcClearingHistoryOrderMapper;
import com.xhpc.activity.mapper.XhpcHistoryOrderMapper;
import com.xhpc.activity.mapper.XhpcOperatorMapper;
import com.xhpc.activity.service.XhpcClearingHistoryOrderService;
import com.xhpc.activity.task.AsyncService;
import com.xhpc.activity.vo.ClearingOrderVo;
import com.xhpc.common.core.exception.CustomException;
import com.xhpc.common.core.utils.StringUtils;
import com.xhpc.common.core.web.service.BaseService;
import com.xhpc.common.security.service.TokenService;
import com.xhpc.common.util.UserTypeUtil;
import com.xhpc.system.api.domain.SysUser;
import com.xhpc.system.api.model.LoginUser;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;


@Service
@Transactional
public class XhpcClearingHistoryOrderServiceImpl extends BaseService implements XhpcClearingHistoryOrderService {

    @Resource
    XhpcClearingHistoryOrderMapper historyOrderMapper;

    @Resource
    XhpcClearingCheckoutMapper checkoutMapper;

    @Resource
    XhpcClearingBankMapper bankMapper;

    @Resource
    XhpcHistoryOrderMapper orderMapper;

    @Resource
    XhpcOperatorMapper operatorMapper;

    @Resource
    TokenService tokenService;

    @Resource
    AsyncService asyncService;

    private final ExecutorService executorService = Executors.newFixedThreadPool(20);

    @Override
    public List<XhpcClearingHistoryOrderDomain> getPage(Map<String, Object> params) {
        LoginUser loginUser = tokenService.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        Long sysUserId = sysUser.getUserId();
        if (!UserTypeUtil.SYS_USER_TYPE_ADMIN.equals(sysUser.getUserId())) {

            if (UserTypeUtil.SYS_USER_TYPE_ONE.equals(sysUser.getUserType())) {
                Long logOperatorId = sysUser.getOperatorId();
                //运营商看自己的场站
                params.put("type", 1);
                params.put("logOperatorId", logOperatorId);
                return historyOrderMapper.getListPage(params);
            } else {
                //查询赋值的场站
                params.put("type", 2);
                params.put("logOperatorId", sysUserId);
                return historyOrderMapper.getListPage(params);
            }
        } else {
            params.put("type", 0);
            params.put("logOperatorId", sysUserId);
            return historyOrderMapper.getListPage(params);
        }
    }


    @Override
    public boolean checkDomainList(ClearingOrderVo orderVo) {
        if (StringUtils.isEmpty(orderVo.getOrderIds())) {
            throw new CustomException("缺少订单ID");
        }
        Map<String, Object> params = new HashMap<>();
        params.put("startTime", orderVo.getStartTime());
        params.put("endTime", orderVo.getEndTime());
        params.put("orderNo", orderVo.getOrderNo());
        params.put("userType", orderVo.getUserType());
        params.put("internetName", orderVo.getInternetName());
        params.put("operatorId", orderVo.getOperatorId());
        params.put("tenantId", orderVo.getTenantId());
        params.put("orderIds", orderVo.getOrderIds());
        params.put("chargingStationId", orderVo.getChargingStationId());
        params.put("chargingPileId", orderVo.getChargingPileId());
        params.put("terminalId", orderVo.getTerminalId());

        List<XhpcClearingHistoryOrderDomain> orderDomainList = historyOrderMapper.getListPage(params);
        String orderIds = orderDomainList.stream().map(n -> n.getClearingOrderId().toString()).collect(Collectors.joining(","));

        if (StringUtils.isNotEmpty(orderIds)){
            asyncService.updateCheckStatusAsync(orderIds, orderVo.getStatus(), orderVo.getCheckBy());
        }
//        executorService.execute(new Runnable() {
//            @Override
//            public void run() {
//                String clearingOrderIds = historyOrderMapper.getClearingOrderIds(params);
//                if (StringUtils.isNotEmpty(clearingOrderIds)){
//                    asyncService.updateCheckStatusAsync(clearingOrderIds, orderVo.getStatus(), orderVo.getCheckBy());
//                }
//            }
//        });
        return true;
    }



    @Override
    public void export(HttpServletResponse response, Map<String, Object> params) throws IOException {
        List<XhpcClearingHistoryOrderDomain> list = historyOrderMapper.getListPage(params);

        // 通过工具类创建writer，默认创建xls格式
        ExcelWriter writer = ExcelUtil.getWriter(true);
        writer.addHeaderAlias("serialNumber", "订单号");
        writer.addHeaderAlias("sourceName", "用户类型");
        writer.addHeaderAlias("chargingModeName", "流量方名称");
        writer.addHeaderAlias("stationName", "电站名称");
        writer.addHeaderAlias("operatorName", "运营商");
        writer.addHeaderAlias("powerPriceTotal", "电费（元）");
        writer.addHeaderAlias("servicePriceTotal", "服务费（元）");
        writer.addHeaderAlias("totalPrice", "订单总金额（元）");
        writer.addHeaderAlias("promotionDiscount", "抵扣总金额（元）");
        writer.addHeaderAlias("actPrice", "用户支付的金额（元）");
        writer.addHeaderAlias("internetCommission", "流量方总金额抽成（元）");
        writer.addHeaderAlias("internetSvcCommission", "流量方服务费抽成（元）");
        writer.addHeaderAlias("internetDegreeCommission", "流量方电量抽成（元）");
        writer.addHeaderAlias("platformCommission", "平台总金额抽成（元）");
        writer.addHeaderAlias("platformSvcCommisssion", "平台服务费抽成（元）");
        writer.addHeaderAlias("operationCommission", "运维总抽成（元）");
        writer.addHeaderAlias("operationSvcCommission", "运维服务费抽成（元）");
        writer.addHeaderAlias("actPowerPrice", "运营商实收电费（元）");
        writer.addHeaderAlias("actServicePrice", "运营商实收服务费（元）");
        writer.addHeaderAlias("actTotalPrice", "运营商实收总费用（元）");
        writer.addHeaderAlias("clearingPrice", "运营商不参与清分金额（元）");
        writer.addHeaderAlias("actClearingPrice", "运营商清分金额（元）");
        writer.addHeaderAlias("startSoc", "启动SOC");
        writer.addHeaderAlias("endSoc", "结算SOC");
        writer.addHeaderAlias("startTime", "开始充电时间");
        writer.addHeaderAlias("endTime", "结束充电时间");
        writer.addHeaderAlias("totalPower", "电量");
        // 默认的，未添加alias的属性也会写出，如果想只写出加了别名的字段，可以调用此方法排除之
        writer.setOnlyAlias(true);
        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(list, true);
        //out为OutputStream，需要写出到的目标流
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
//        //response为HttpServletResponse对象
//        response.setContentType("application/vnd.ms-excel;charset=utf-8");
//        //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
//        response.setHeader("Content-Disposition", "attachment;filename=历史订单列表.xls");
        ServletOutputStream out = response.getOutputStream();

        writer.flush(out, true);
        // 关闭writer，释放内存
        writer.close();
        //此处记得关闭输出Servlet流
        IoUtil.close(out);
    }


    // ===========================
    @Override
    public List<Map<String, Object>> getOrderPage(Map<String, Object> params) {
        startPage();
        return historyOrderMapper.selectOrderPage(params);
    }


    @Override
    public Map<String, Object> getOperatorData(Map<String, Object> params) {

        String operatorId = params.get("operatorId").toString();

        Map<String, Object> bankDomain = bankMapper.selectOneMapByOperatorId(operatorId);
        // 待清分金额
        BigDecimal unClearingAmount = orderMapper.selectUnclearingAmount(operatorId);

        // 已审核通过金额
        BigDecimal checkedAmount = historyOrderMapper.selectCheckedAmount(operatorId);

        // 已提现金额
        BigDecimal cashedAmount = checkoutMapper.selectAmountByStatus(operatorId, 6);

        // 提现中金额
        BigDecimal cashingAmount = checkoutMapper.selectAmountByStatus(operatorId, 1);

        // 可提现金额
        Map<String, Object> cashMap = historyOrderMapper.selectCashAmount(operatorId);

        if (bankDomain == null) {
            bankDomain = new HashMap<>();

            XhpcOperatorDomain operatorDomain = operatorMapper.selectByPrimaryKey(Long.parseLong(operatorId));
            if (operatorDomain != null) {
                bankDomain.put("operatorName", operatorDomain.getName());
            }
        }

        bankDomain.put("cashedAmount", cashedAmount);
        bankDomain.put("unclearingAmount", unClearingAmount);
        bankDomain.put("cashingAmount", cashingAmount);
        // 可提现金额
        BigDecimal bankRate = new BigDecimal("0.006");
        BigDecimal handlingAmount = BigDecimal.TEN;
        //剔除不参与清分金额
        Map<String, Object> cashMapYu = historyOrderMapper.selectCashAmountYu(operatorId.toString());
        BigDecimal powerAmountYu = new BigDecimal(cashMapYu.get("powerAmount").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal serviceAmountYu =  new BigDecimal(cashMapYu.get("serviceAmount").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal bankFeeYu = powerAmountYu.add(serviceAmountYu).multiply(bankRate).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal receivedServiceAmountYu = serviceAmountYu.subtract(handlingAmount).subtract(bankFeeYu);

        bankDomain.put("cashAmount", powerAmountYu.add(receivedServiceAmountYu).compareTo(BigDecimal.ZERO) >= 0 ? powerAmountYu.add(receivedServiceAmountYu) : BigDecimal.ZERO);
        // 不参与清分金额
        bankDomain.put("clearingPrice", cashMap.get("clearingPrice"));
        return bankDomain;
    }

}
