package com.jjt.order.controller;

import com.jjt.biz.vo.GramMassDetail;
import com.jjt.calc.domain.TwinCalcDay;
import com.jjt.calc.domain.TwinFormulaInfo;
import com.jjt.calc.service.ITwinCalcDayService;
import com.jjt.calc.service.ITwinFormulaInfoService;
import com.jjt.common.constant.CacheConstants;
import com.jjt.common.core.controller.BaseController;
import com.jjt.common.core.redis.RedisCache;
import com.jjt.common.utils.DateUtils;
import com.jjt.order.domain.TwinOrder;
import com.jjt.order.domain.TwinOrderDetail;
import com.jjt.order.domain.VmsStock;
import com.jjt.order.service.ITwinOrderService;
import com.jjt.order.utils.OrderExportUtil;
import com.jjt.order.utils.OrderGsmExportUtil;
import com.jjt.order.vo.BomVO;
import com.jjt.utils.MssqlService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author ruoyi
 */
@Api(tags = "订单数据接口")
@RestController
@Slf4j
@RequestMapping()
public class OrderApiController extends BaseController {
    @Resource
    private RedisCache redisCache;
    @Resource
    private ITwinOrderService orderService;
    @Resource
    private ITwinFormulaInfoService formulaInfoService;
    @Resource
    private ITwinCalcDayService dayService;
    @Resource
    private MssqlService mssqlService;

    @ApiOperation("查看当前库存")
    @GetMapping("/api/stock")
    @CrossOrigin(origins = "*")
    @ResponseBody
    public Map<String, Object> mesStock() {
        return redisCache.getCacheObject(CacheConstants.VMS_STOCK);
    }

    @ApiOperation("导出白坯预测")
    @RequestMapping("/api/export/order")
    @CrossOrigin(origins = "*")
    public void orderExport(@RequestParam String start, @RequestParam String end, @RequestParam Integer days, HttpServletResponse response) {
        //查询订单
        List<TwinOrder> orderList = orderService.selectTwinOrderListByDate(start, end);
        //按订单ID分组
        Map<Long, TwinOrder> orderMap = orderList.stream().collect(Collectors.toMap(TwinOrder::getOderId, o -> o));
        List<GramMassDetail> infos = redisCache.getCacheObject(CacheConstants.INDEX_GRAM_MASS_DETAIL);
        Date sd = DateUtils.toDate(LocalDateTime.now().minusHours(7).toLocalDate().minusDays(1));
        List<TwinCalcDay> dayList = dayService.selectTwinCalcDayListByTime(sd, sd);
        //按设备ID分组
        Map<Long, TwinCalcDay> dayMap = dayList.stream().collect(Collectors.toMap(TwinCalcDay::getDeviceId, o -> o));
        List<VmsStock> stocks = mssqlService.vmsStock();
        try (OutputStream outputStream = new BufferedOutputStream(response.getOutputStream()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ZipOutputStream zipOut = new ZipOutputStream(bos);) {
            // 创建临时输出流
            response.reset();
            response.setCharacterEncoding("UTF-8");
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("白坯布靶向预测" + start + "至" + end + ".zip", "UTF-8"));
            response.setContentType("application/octet-stream");

            try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("tpl/order.xlsx"); XSSFWorkbook wb = new XSSFWorkbook(inputStream);) {
                OrderExportUtil oe = new OrderExportUtil();
                String title = "白坯布靶向生产测算-" + days + "天（" + start + " 至 " + end + "）\n按重量匹配";
                oe.process(wb, title, orderList, infos, orderMap, dayMap, stocks, days);
                // 将第一个工作簿写入 ZIP
                ZipEntry entry = new ZipEntry("按重量匹配.xlsx");
                zipOut.putNextEntry(entry);
                wb.write(zipOut);
                zipOut.closeEntry();

            } catch (IOException ex) {
                ex.printStackTrace();
            }

            try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("tpl/order-gsm.xlsx"); XSSFWorkbook wb = new XSSFWorkbook(inputStream);) {
                OrderGsmExportUtil oe = new OrderGsmExportUtil();
                String title = "白坯布靶向生产测算-" + days + "天（" + start + " 至 " + end + "）\n按平方米克重匹配";
                oe.process(wb, title, orderList, infos, orderMap, dayMap, stocks, days);
                // 将第二个工作簿写入 ZIP
                ZipEntry entry = new ZipEntry("按平方米克重匹配.xlsx");
                zipOut.putNextEntry(entry);
                wb.write(zipOut);
                zipOut.closeEntry();
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            // 完成 ZIP 文件
            zipOut.finish();
            outputStream.write(bos.toByteArray());
            outputStream.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @ApiOperation("查询最近一个月有订单的时间")
    @GetMapping("/api/order/date")
    @CrossOrigin(origins = "*")
    @ResponseBody
    public List<LocalDate> orderDate() {
        LocalDate end = LocalDate.now();
        LocalDate start = end.minusMonths(1);
        List<TwinOrder> orderList = orderService.selectTwinOrderListByDate(start.toString(), end.toString());
        List<LocalDate> result = orderList.stream()
                .map(order -> order.getOrderDate().toInstant()
                        .atZone(ZoneId.systemDefault())
                        .toLocalDate())
                .distinct()
                .collect(Collectors.toList());
        return result;
    }

    @ApiOperation("按照时间查询订单")
    @GetMapping("/api/order/query")
    @CrossOrigin(origins = "*")
    @ResponseBody
    public List<TwinOrder> query(@RequestParam String start, @RequestParam String end, @RequestParam Integer days) {
        List<TwinOrder> orderList = orderService.selectTwinOrderListByDate(start, end);

        //白柸布库存
        List<VmsStock> stocks = mssqlService.vmsStock();
        //设备配方信息
        List<GramMassDetail> infos = redisCache.getCacheObject(CacheConstants.INDEX_GRAM_MASS_DETAIL);
//        List<TwinFormulaInfo> infos = formulaInfoService.selectTwinFormulaInfoList(new TwinFormulaInfo());
        //当前产量处理
        Date sd = DateUtils.toDate(LocalDateTime.now().minusHours(7).toLocalDate().minusDays(1));
        List<TwinCalcDay> dayList = dayService.selectTwinCalcDayListByTime(sd, sd);
        //按设备ID分组
        Map<Long, TwinCalcDay> dayMap = dayList.stream().collect(Collectors.toMap(TwinCalcDay::getDeviceId, o -> o));

        for (TwinOrder twinOrder : orderList) {
            List<BomVO> bomVOList = new ArrayList<>();
            //过滤掉规格为空的，并按规格分组
            Map<String, List<TwinOrderDetail>> allMap = twinOrder.getTwinOrderDetailList().stream().filter(tod -> tod.getBomSpec() != null).collect(Collectors.groupingBy(TwinOrderDetail::getBomSpec, LinkedHashMap::new, Collectors.toList()));
            OrderExportUtil oe = new OrderExportUtil();
            for (String spec : allMap.keySet()) {
                List<TwinOrderDetail> todList = allMap.get(spec);
                //匹配白坯布库存
                Float kc = 0f;
                VmsStock stock = oe.matchStock(spec, stocks);
                if (stock != null) {
                    kc = stock.getQty();
                }
                //匹配生产设备
                List<GramMassDetail> matchFormula = oe.matchFormula(spec, infos);
                BigDecimal cl = BigDecimal.ZERO;
                for (GramMassDetail match : matchFormula) {
                    TwinCalcDay day = dayMap.get(match.getFormula_data_2());
                    if (day != null) {
                        cl = cl.add(day.getWeight());
                    }
                }

                cl = cl.multiply(BigDecimal.valueOf(1000));
                double totalWeight = todList.stream().mapToDouble(o -> o.getWeight().doubleValue()).sum();
                TwinOrderDetail tod = todList.get(0);

                BomVO bom = new BomVO();
                bom.setLast(cl.doubleValue());
                bom.setBomCode(tod.getBomCode());
                bom.setBomName(tod.getBomName());
                bom.setBomSpec(spec);
                bom.setXql(totalWeight);
                bom.setKcl(kc);
                double ycl = cl.multiply(BigDecimal.valueOf(days)).doubleValue();
                double cz = totalWeight - kc - ycl;
                bom.setYcl(ycl);
                bom.setCz(cz);
                bomVOList.add(bom);
            }
            twinOrder.setBomList(bomVOList);
            twinOrder.setTwinOrderDetailList(null);
        }
        return orderList;
    }

//    @ApiOperation("按订单号查询预测信息")
//    @GetMapping("/api/order/detail")
//    @CrossOrigin(origins = "*")
//    @ResponseBody
//    public List<TwinOrder> detail(@RequestParam List<String> code) {
////        List<TwinOrder> orderList = orderService.selectTwinOrderListByDate(date, date);
//        return null;
//    }


}
