package com.prolog.cs.biz.outbound.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.NumberChineseFormatter;
import com.prolog.cs.biz.outbound.core.Constants;
import com.prolog.cs.biz.outbound.dao.*;
import com.prolog.cs.biz.outbound.model.OmsDoBillHDO;
import com.prolog.cs.biz.outbound.model.dto.FaceOrderItemDTO;
import com.prolog.cs.biz.outbound.model.entity.InvoicePdfDO;
import com.prolog.cs.biz.outbound.model.print.PrintDataWithMark;
import com.prolog.cs.biz.outbound.model.vo.PrintQnSaleVO;
import com.prolog.cs.biz.outbound.model.vo.faceorder.FaceOrderItemVO;
import com.prolog.cs.biz.outbound.model.vo.faceorder.ItemInfoVo;
import com.prolog.cs.biz.outbound.service.PrintService;
import com.prolog.framework.authority.core.dto.UserDTO;
import com.prolog.framework.authority.user.UserTemplate;
import com.prolog.framework.bz.common.print.PrintData;
import com.prolog.framework.bz.common.print.ReportData;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zzz
 * @desc 打印服务实现
 * @date 2021/4/30
 */
@Service
public class PrintServiceImpl implements PrintService {

    private static Logger log = LoggerFactory.getLogger(PrintServiceImpl.class);

    @Autowired
    private UserTemplate userTemplate;

    @Autowired
    private OmsDoBillDMapper omsDoBillDMapper;

    @Autowired
    private OmsDoBillHMapper omsDoBillHMapper;
    @Autowired
    private FaceOrderMapper faceOrderMapper;
    @Autowired
    private InvoicePdfMapper invoicePdfMapper;
    @Autowired
    private BarcodeHMapper barcodeHMapper;

    @Override
    public PrintData printQnSalesData(String billId) {

        if(StringUtils.isEmpty(billId)){
            throw new BizException("单据编号不能为空");
        }
        UserDTO userDTO = userTemplate.getUserDTO();
        Criteria cr = Criteria.forClass(OmsDoBillHDO.class);
        Restriction restriction = Restrictions.eq("billid", billId);
        cr.setRestriction(restriction);
        List<OmsDoBillHDO> billHList = omsDoBillHMapper.findByCriteria(cr);
        if(billHList.isEmpty()){
            throw new BizException("为查询到订单信息");
        }
        OmsDoBillHDO omsDoBillHDO = billHList.get(0);
        List<PrintQnSaleVO> dobList = omsDoBillDMapper.queryQnSalesData(billId);
        return getPrintData(omsDoBillHDO,dobList);
    }

    @Override
    public List<PrintData> printYmSalesData(String billId) {
        if(StringUtils.isEmpty(billId)){
            throw new BizException("单据编号不能为空");
        }
        UserDTO userDTO = userTemplate.getUserDTO();
        Criteria cr = Criteria.forClass(OmsDoBillHDO.class);
        Restriction restriction = Restrictions.eq("billid", billId);
        cr.setRestriction(restriction);
        List<OmsDoBillHDO> billHList = omsDoBillHMapper.findByCriteria(cr);
        if(billHList.isEmpty()){
            throw new BizException("为查询到订单信息");
        }
        OmsDoBillHDO omsDoBillHDO = billHList.get(0);
        List<Map<String,Object>> allList = omsDoBillDMapper.queryYmSalesData(billId);
        for (Map<String, Object> drugMap : allList) {
            String stockStatus = (String) drugMap.get("stockStatus");
            if(StringUtils.isNotEmpty(stockStatus)){
                drugMap.put("stockStatus",Constants.StockStatusEnum.find(stockStatus));
            }
        }
        List<Map<String,Object>> drugList = allList.stream().filter(item->"001".equals(item.get("itemCateGory"))).collect(Collectors.toList());
        List<Map<String,Object>> appList = allList.stream().filter(item->"013".equals(item.get("itemCateGory"))).collect(Collectors.toList());
        List<Map<String,Object>> foodList = allList.stream().filter(item->"014".equals(item.get("itemCateGory"))).collect(Collectors.toList());
        List<PrintData> result = new ArrayList<>();
        if(!drugList.isEmpty()){
            PrintData drugData = getPrintDataByMap(omsDoBillHDO,drugList);
            drugData.setTempType("001");
            result.add(drugData);
        }
        if(!appList.isEmpty()){
            PrintData appData = getPrintDataByMap(omsDoBillHDO,appList);
            appData.setTempType("013");
            result.add(appData);
        }
        if(!foodList.isEmpty()){
            PrintData footData = getPrintDataByMap(omsDoBillHDO,foodList);
            footData.setTempType("014");
            result.add(footData);
        }
        return result;
    }

    @Override
    public PrintData printLogisticData(String billId) {
        if(StringUtils.isEmpty(billId)){
            throw new BizException("单据编号不能为空");
        }
        UserDTO userDTO = userTemplate.getUserDTO();
        Criteria cr = Criteria.forClass(OmsDoBillHDO.class);
        Restriction restriction = Restrictions.eq("billid", billId);
        cr.setRestriction(restriction);
        List<OmsDoBillHDO> billHList = omsDoBillHMapper.findByCriteria(cr);
        if(billHList.isEmpty()){
            throw new BizException("为查询到订单信息");
        }
        OmsDoBillHDO omsDoBillHDO = billHList.get(0);
        List<Map<String,Object>> dobList = omsDoBillDMapper.queryLogisticData(billId);
        return getPrintLogisticData(omsDoBillHDO,dobList);
    }

    @Override
    public Map<String, Object> printPdfData(List<Map<String,String>> fileInfo) {
        Map<String,Object> result = new HashMap<>();
        List<Map<String,String>> data = new ArrayList<>();
        for (Map<String, String> fileMap : fileInfo) {
            Map<String,String> pdf = new HashMap<>();
            String fileUrl = fileMap.get("fileUrl");
            String fileName = fileMap.get("fileName");
            if(StringUtils.isEmpty(fileUrl) || StringUtils.isEmpty(fileName)){
                throw new BizException("附件地址或名称不能为空");
            }
            pdf.put("url",fileUrl);
            pdf.put("fileName",fileName);
            data.add(pdf);
        }
        result.put("url","");
        result.put("printSolution","");
        result.put("preview",false);
        result.put("count",1);
        result.put("printName","Microsoft Print to PDF");
        result.put("templateType","file");
        result.put("data",data);
        return result;
    }

    @Override
    public PrintDataWithMark printExpressData(List<String> waybillCode) {
        List<FaceOrderItemDTO> result = faceOrderMapper.queryFaceItem(waybillCode);
        if(result.isEmpty()){
            throw new BizException("未查询到面单信息");
        }
        List<ReportData> reportDatas = new ArrayList<>();
        Map<String, List<FaceOrderItemDTO>> results = result.stream().collect(Collectors.groupingBy(FaceOrderItemDTO::getWaybillCode));
        for (Map.Entry<String, List<FaceOrderItemDTO>> stringListEntry : results.entrySet()) {
            ReportData reportData = new ReportData();
            FaceOrderItemDTO faceOrderItemDTO = stringListEntry.getValue().get(0);
            FaceOrderItemVO faceOrderItemVO = new FaceOrderItemVO();
            BeanUtil.copyProperties(faceOrderItemDTO,faceOrderItemVO);
            List<ItemInfoVo> items = new ArrayList<>();
            for (FaceOrderItemDTO orderItemDTO : stringListEntry.getValue()) {
                ItemInfoVo itemInfoVo = new ItemInfoVo();
                BeanUtil.copyProperties(orderItemDTO,itemInfoVo);
                items.add(itemInfoVo);
            }
            faceOrderItemVO.setItems(items);
            reportData.setHead(BeanUtil.beanToMap(faceOrderItemVO));
            reportDatas.add(reportData);
        }
        PrintData printData = new PrintData();
        printData.setData(reportDatas);

        return new PrintDataWithMark(printData,null);
    }

    @Override
    public Map<String, Object> printInvoiceData(String orderNo) {
        Criteria cr = Criteria.forClass(InvoicePdfDO.class);
        Restriction r1 = Restrictions.eq(InvoicePdfDO::getOrderNo, orderNo);
        cr.setRestriction(r1);
        List<InvoicePdfDO> pdfs = invoicePdfMapper.findByCriteria(cr);
        if(pdfs.isEmpty()){
            throw new BizException("未查询到发票pdf信息");
        }
        InvoicePdfDO invoicePdfDO = pdfs.get(0);
        Map<String,Object> result = new HashMap<>();
        List<Map<String,String>> data = new ArrayList<>();
        Map<String,String> pdf = new HashMap<>();
        String fileUrl = invoicePdfDO.getPdfUrl();
        if(StringUtils.isEmpty(fileUrl)){
            throw new BizException("附件地址或名称不能为空");
        }
        String fileName = fileUrl.substring(fileUrl.lastIndexOf("/")+1);

        pdf.put("url",fileUrl);
        pdf.put("fileName",fileName);
        data.add(pdf);
        result.put("url","");
        result.put("printSolution","");
        result.put("preview",false);
        result.put("count",1);
        result.put("printName","Microsoft Print to PDF");
        result.put("templateType","file");
        result.put("data",data);
        return result;
    }

    @Override
    public PrintDataWithMark printLabelData(List<String> billGroupIds) {
        List<Map<String,Object>> barcodeHs = barcodeHMapper.queryByBillGroupIds(billGroupIds);
        if(barcodeHs.isEmpty()){
            throw new BizException("未查询到标签信息");
        }
        Map<String, List<Map<String,Object>>> collect = barcodeHs.stream()
                .collect(Collectors.groupingBy(item -> String.valueOf(item.get("billGroupId")),
                        HashMap::new,
                        Collectors.toList()));
        PrintData printData = new PrintData();
        List<ReportData> reportDatas = new ArrayList<>();
        for (Map.Entry<String, List<Map<String,Object>>> stringListEntry : collect.entrySet()) {
            ReportData reportData = new ReportData();
            int index = 1;
            for (Map<String, Object> stringObjectMap : stringListEntry.getValue()) {
                Map<String,Object> barcodeMap = new HashMap<>();
                barcodeMap.put("billGroupId",stringObjectMap.get("billGroupId"));
                barcodeMap.put("barcode",stringObjectMap.get("barcode"));
                barcodeMap.put("shipperName",stringObjectMap.get("shipperName"));
                barcodeMap.put("pcs",index + "/" + stringListEntry.getValue().size());
                index++;
                reportData.setHead(barcodeMap);
            }
            reportDatas.add(reportData);
        }
        printData.setData(reportDatas);
        return new PrintDataWithMark(printData,null);
    }

    private PrintData getPrintDataByMap(OmsDoBillHDO omsDoBillHDO, List<Map<String, Object>> list) {
        PrintData printData = new PrintData();
        List<ReportData> reportDatas = new ArrayList<>();
        List<List<Map<String, Object>>> partition = ListUtils.partition(list, 5);
        BigDecimal amtSum = list.stream()
                .map(item->(BigDecimal)item.get("amt")).reduce(BigDecimal.ZERO, BigDecimal::add);
        String amtSumStr = "";
        if(amtSum.compareTo(BigDecimal.ZERO) > 0){
            amtSumStr = NumberChineseFormatter.format(amtSum.doubleValue(), true, true);
        }
        int index = 1;
        for (List<Map<String, Object>> maps : partition) {
            ReportData reportData = new ReportData();
            reportData.setTable(maps);
            Map<String, Object> head = new HashMap<>();
            head.put("shipperName",omsDoBillHDO.getShippername());
            head.put("receiveAddress",omsDoBillHDO.getReceiveAddress());
            head.put("custPerson",omsDoBillHDO.getCustPerson());
            head.put("billNo",omsDoBillHDO.getBillno());
            head.put("planDeliveryDate",omsDoBillHDO.getPlanDeliveryDate());
            head.put("transportMode",omsDoBillHDO.getTransportMode());
            head.put("preparedBy",omsDoBillHDO.getPreparedBy());
            head.put("amtSum",amtSum);
            head.put("amtSumStr",amtSumStr);
            head.put("page",index);
            head.put("total",partition.size());
            head.put("checkerName",maps.get(0).get("checkerName"));
            index++;
            reportData.setHead(head);
            reportDatas.add(reportData);
        }
        printData.setData(reportDatas);
        return printData;
    }


    private PrintData getPrintData(OmsDoBillHDO omsDoBillHDO, List<PrintQnSaleVO> dobList) {
        PrintData printData = new PrintData();
        List<ReportData> reportDatas = new ArrayList<>();
        List<Map<String, Object>> table = new ArrayList<>();
        for (PrintQnSaleVO printQnSaleVO : dobList) {
            printQnSaleVO.setStockStatus(Constants.StockStatusEnum.find(printQnSaleVO.getStockStatus()));
            table.add(BeanUtil.beanToMap(printQnSaleVO));
        }
        List<List<Map<String, Object>>> partition = ListUtils.partition(table, 12);
        int index = 1;
        //实收金额
        BigDecimal amtSum = dobList.stream()
                .map(PrintQnSaleVO::getActualQty).reduce(BigDecimal.ZERO, BigDecimal::add);
        //折扣
        BigDecimal discountAmtSum = dobList.stream()
                .map(PrintQnSaleVO::getDiscountQty).reduce(BigDecimal.ZERO, BigDecimal::add);
        String amtSumStr = "";
        if(amtSum.compareTo(BigDecimal.ZERO) > 0){
            amtSumStr = NumberChineseFormatter.format(amtSum.doubleValue(), true, true);
        }
        for (List<Map<String, Object>> maps : partition) {
            ReportData reportData = new ReportData();
            reportData.setTable(maps);
            Map<String, Object> head = new HashMap<>();
            head.put("shipperName",omsDoBillHDO.getShippername());
            head.put("receiveAddress",omsDoBillHDO.getReceiveAddress());
            head.put("custPerson",omsDoBillHDO.getCustPerson());
            head.put("billNo",omsDoBillHDO.getBillno());
            head.put("planDeliveryDate",omsDoBillHDO.getPlanDeliveryDate());
            head.put("page",index);
            head.put("total",partition.size());
            head.put("amtSum",amtSum);
            head.put("discountAmtSum",discountAmtSum);
            head.put("amtSumStr",amtSumStr);
            index++;
            reportData.setHead(head);
            reportDatas.add(reportData);
        }
        printData.setData(reportDatas);
        return printData;
    }


    private PrintData getPrintLogisticData(OmsDoBillHDO omsDoBillHDO, List<Map<String, Object>> dobList) {
        PrintData printData = new PrintData();
        List<ReportData> reportDatas = new ArrayList<>();

        List<List<Map<String, Object>>> partition = ListUtils.partition(dobList, 5);
        int index = 1;
        BigDecimal amtSum = dobList.stream()
                .map(item -> (BigDecimal)item.get("amt")).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal itemPcs = dobList.stream()
                .map(item -> (BigDecimal)item.get("itemPcs")).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal volume = dobList.stream()
                .map(item -> (BigDecimal)item.get("volume")).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal weight = dobList.stream()
                .map(item -> (BigDecimal)item.get("weight")).reduce(BigDecimal.ZERO, BigDecimal::add);
        String amtSumStr = "";
        if(amtSum.compareTo(BigDecimal.ZERO) > 0){
            amtSumStr = NumberChineseFormatter.format(amtSum.doubleValue(), true, true);
        }
        for (List<Map<String, Object>> maps : partition) {
            ReportData reportData = new ReportData();
            reportData.setTable(maps);
            Map<String, Object> head = new HashMap<>();
            head.put("shipperName",omsDoBillHDO.getShippername());
            head.put("receiveAddress",omsDoBillHDO.getReceiveAddress());
            head.put("custPerson",omsDoBillHDO.getCustPerson());
            head.put("custPersonTel",omsDoBillHDO.getCustPersonTel());
            head.put("billNo",omsDoBillHDO.getBillno());
            head.put("planDeliveryDate",omsDoBillHDO.getPlanDeliveryDate());
            head.put("page",index);
            head.put("total",partition.size());
            head.put("amtSum",amtSum);
            head.put("amtSumStr",amtSumStr);
            head.put("itemPcs",itemPcs);
            head.put("volume",volume);
            head.put("weight",weight);
            head.put("transportMode",omsDoBillHDO.getTransportMode());
            head.put("freight",omsDoBillHDO.getFreight());
            head.put("deliveryName",omsDoBillHDO.getDeliveryName());
            head.put("preparedBy",omsDoBillHDO.getPreparedBy());
            head.put("salespersonName",omsDoBillHDO.getSalespersonName());
            index++;
            reportData.setHead(head);
            reportDatas.add(reportData);
        }
        printData.setData(reportDatas);
        return printData;
    }
}
