package cn.ezhizao.project.business.controller;

import cn.ezhizao.common.utils.PdfUtil;
import cn.ezhizao.common.utils.poi.ExcelUtil;
import cn.ezhizao.framework.aspectj.lang.annotation.Log;
import cn.ezhizao.framework.aspectj.lang.enums.BusinessType;
import cn.ezhizao.framework.redis.RedisCache;
import cn.ezhizao.framework.web.controller.BaseController;
import cn.ezhizao.framework.web.domain.AjaxResult;
import cn.ezhizao.framework.web.page.TableDataInfo;
import cn.ezhizao.project.business.domain.*;
import cn.ezhizao.project.business.service.*;
import cn.hutool.extra.template.TemplateException;
import freemarker.template.Template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 收回单主表
 *
 * @author 庄德政
 * date    2024-04-26
 */
@RestController
@RequestMapping("/business/returnReceipt")
public class BizReturnReceiptController extends BaseController
{
    @Resource
    private IBizReturnReceiptService bizReturnReceiptService;
    @Resource
    private IBizReturnReceiptDetailService bizReturnReceiptDetailService;
    @Resource
    private IBizOutsourcedOrderDetailProcessService bizOutsourcedOrderDetailProcessService;
    @Resource
    private IBizSupplierService bizSupplierService;
    @Resource
    private RedisCache redisCache;
    @Resource
    HttpServletRequest request;

    /**
     * 生成pdf
     */
    @Autowired
    private FreeMarkerConfigurer freeMarkerConfigurer;
    /**
     * 查询收回单主
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:list')")
    @GetMapping("/list")
    public TableDataInfo list(BizReturnReceipt bizReturnReceipt) throws NoSuchFieldException, IllegalAccessException
    {
        if(bizReturnReceipt.getStartTime()!=null) {
            bizReturnReceipt.setStartTime(bizReturnReceipt.getStartTime()+ " 00:00:00");
        }
        if(bizReturnReceipt.getEndTime()!=null) {
            bizReturnReceipt.setEndTime(bizReturnReceipt.getEndTime()+ " 23:59:59");
        }
        final String supplierId = request.getHeader("tenantId");
        bizReturnReceipt.setSupplierId(Long.parseLong(supplierId));
        startPage();
        List<BizReturnReceipt> list = bizReturnReceiptService.getList(bizReturnReceipt);
        return getDataTable(list);
    }

    /**
     * 导出收回单主
带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子列表
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:export')")
    @Log(title = "收回单主带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, BizReturnReceipt bizOutsourcedOrder) throws NoSuchFieldException, IllegalAccessException
    {
        setTenantId(bizOutsourcedOrder);
        List<BizReturnReceipt> list = bizReturnReceiptService.getList(bizOutsourcedOrder);
        ExcelUtil<BizReturnReceipt> util = new ExcelUtil<>(BizReturnReceipt.class);
        util.exportExcel(response, list, "收回单主带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子数据");
    }
    /**
     * 新增外协单主
     带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:add')")
    @Transactional
    @PostMapping
    public AjaxResult addReceipt(@RequestBody BizReturnReceipt bizReturnReceipt)
    {
        final String supplierId = request.getHeader("tenantId");
        bizReturnReceipt.setSupplierId(Long.parseLong(supplierId));
        //若有id，则说将之前的明细删除不生成新的单号
        if (bizReturnReceipt.getId() != null) {
            List<Long> ids = new ArrayList<>();
        } else {
            /* 生成单号 */
            SimpleDateFormat dateFormat = new SimpleDateFormat("yy"); // 定义日期格式
            String formattedDate = dateFormat.format(new Date());
            String codeValue;
            String codeType = "returnReceiveCode";
            //查询redis中外协单号的值
            String previous = redisCache.hasKey(codeType) ? redisCache.getCacheObject(codeType) :"";
            //若不存在，则直接存入
            if (previous.isEmpty()) {
                previous = ("SHD" + formattedDate + "000001");
            } else {
                codeValue=previous;
                int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                lastFourDigits += 1; // 加1
                codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                previous=codeValue;
            }
            //存到redis中
            redisCache.setCacheObject(codeType, previous);
            bizReturnReceipt.setFormCode(previous);
        }
        //向收回单主表存
        bizReturnReceiptService.save(bizReturnReceipt);
        //向收回单明细表存
        bizReturnReceipt.getDetails().stream()
                .forEach(bizReturnReceiptDetail -> {
                    bizReturnReceiptDetail.setMasterId(bizReturnReceipt.getId());
                    bizReturnReceiptDetail.setFormCode(bizReturnReceipt.getFormCode());
                    bizReturnReceiptDetail.setSupplierId(bizReturnReceipt.getSupplierId());
                    bizReturnReceiptDetail.setSupplierName(bizReturnReceipt.getSupplierName());
                    bizReturnReceiptDetail.setFormDate(bizReturnReceipt.getFormDate());
                });
        return success(bizReturnReceiptDetailService.saveBatch(bizReturnReceipt.getDetails()));
    }
    /**
     * 修改外协单主
     带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:edit')")
    @Transactional
    @PutMapping
    public AjaxResult updateReceipt(@RequestBody BizReturnReceipt bizReturnReceipt)
    {
        //向收回单主表存
        bizReturnReceiptService.updateById(bizReturnReceipt);
        //向收回单明细表存
        List<BizReturnReceiptDetail> oldList = bizReturnReceiptDetailService.query().eq("master_id",bizReturnReceipt.getId()).list();
        bizReturnReceipt.getDetails().stream()
                .forEach(bizReturnReceiptDetail -> {
                    bizReturnReceiptDetail.setMasterId(bizReturnReceipt.getId());
                    bizReturnReceiptDetail.setFormCode(bizReturnReceipt.getFormCode());
                    bizReturnReceiptDetail.setSupplierId(bizReturnReceipt.getSupplierId());
                    bizReturnReceiptDetail.setSupplierName(bizReturnReceipt.getSupplierName());
                    bizReturnReceiptDetail.setFormDate(bizReturnReceipt.getFormDate());
                });
        saveOrUpdateBatch(bizReturnReceiptDetailService,bizReturnReceipt.getDetails(),oldList);
        return success();
    }
    /**
     * 获取收回单主 带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子详细信息
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        // 根据 id 获取到收回订单
        BizReturnReceipt returnReceipt = bizReturnReceiptService.getById(id);

        // 根据收回订单id，获取到该收回订单的所有明细
        List<BizReturnReceiptDetail> returnReceiptDetails = bizReturnReceiptDetailService.query()
                .eq("master_id", id)
                .list();

        // 将得到的收回明细的id，组合成一个集合，用于查询这个订单下的，所有收回出来的工序，
        // 这里得到的工序清单，是混合的，并没有根据各自对应的明细，进行分组，仅仅是获取全部，为后续分组做准备
        List<Long> detailIds = returnReceiptDetails.stream()
                .map(BizReturnReceiptDetail::getOutsourceDetailId)
                .collect(Collectors.toList());
        List<BizOutsourcedOrderDetailProcess> detailProcesses = bizOutsourcedOrderDetailProcessService.query()
                .in("detail_id", detailIds)
                .orderByAsc(Arrays.asList("detail_id", "process_step_number"))
                .list();

        // 遍历明细，将对应的工序，与订单明细进行匹配
        returnReceiptDetails.forEach(item -> {
            // 根据明细的id，获取到该明细对应的收回工序，并将得到的工序，组成中文逗号分割的字符串
            String processNames = detailProcesses.stream()
                    .filter(dp -> dp.getDetailId().equals(item.getOutsourceDetailId()))
                    .sorted(Comparator.comparing((BizOutsourcedOrderDetailProcess::getProcessStepNumber)))
                    .map(BizOutsourcedOrderDetailProcess::getProcessAlias)
                    .collect(Collectors.joining("，"));

            item.setProcessNames(processNames);
        });

        // 将收回明细赋值给收回订单
        returnReceipt.setDetails(returnReceiptDetails);

        return success(returnReceipt);
    }
    /**
     * 删除外协单主
     带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:remove')")
    @Log(title = "外协单主带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子", businessType = BusinessType.DELETE)
    @Transactional
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable List<Long> ids)
    {
        bizReturnReceiptService.removeBatchByIds(ids);
        List<BizReturnReceiptDetail> bizReturnReceiptDetailList = bizReturnReceiptDetailService.query().in("master_id", ids).list();
        List<Long> bizReturnReceiptDetailIds = bizReturnReceiptDetailList.stream().map(BizReturnReceiptDetail::getId).collect(Collectors.toList());
        return toAjax(bizReturnReceiptDetailService.removeBatchByIds(bizReturnReceiptDetailIds));
    }


    @Log(title = "外协打印", businessType = BusinessType.EXPORT)
    @PostMapping("/printDetailPdf")
    public void SocialSecurityPdf(BizReturnReceipt bizReturnReceipt, HttpServletResponse response) throws IOException, TemplateException, freemarker.template.TemplateException {

        /** 正常打印 **/
        //查询回收单数据
        bizReturnReceipt=bizReturnReceiptService.getById(bizReturnReceipt);
        //查询回收单明细
//        List<BizReturnReceiptDetail> detailList=bizReturnReceiptDetailService.query().in("master_id", bizReturnReceipt.getId()).list();
        // 根据收回订单id，获取到该收回订单的所有明细
        List<BizReturnReceiptDetail> returnReceiptDetails = bizReturnReceiptDetailService.query()
                .eq("master_id", bizReturnReceipt.getId())
                .list();

        // 将得到的收回明细的id，组合成一个集合，用于查询这个订单下的，所有收回出来的工序，
        // 这里得到的工序清单，是混合的，并没有根据各自对应的明细，进行分组，仅仅是获取全部，为后续分组做准备
        List<Long> detailIds = returnReceiptDetails.stream()
                .map(BizReturnReceiptDetail::getOutsourceDetailId)
                .collect(Collectors.toList());
        List<BizOutsourcedOrderDetailProcess> detailProcesses = bizOutsourcedOrderDetailProcessService.query()
                .in("detail_id", detailIds)
                .orderByAsc(Arrays.asList("detail_id", "process_step_number"))
                .list();

        // 遍历明细，将对应的工序，与订单明细进行匹配
        returnReceiptDetails.forEach(item -> {
            // 根据明细的id，获取到该明细对应的收回工序，并将得到的工序，组成中文逗号分割的字符串
            String processNames = detailProcesses.stream()
                    .filter(dp -> dp.getDetailId().equals(item.getOutsourceDetailId()))
                    .sorted(Comparator.comparing((BizOutsourcedOrderDetailProcess::getProcessStepNumber)))
                    .map(BizOutsourcedOrderDetailProcess::getProcessAlias)
                    .collect(Collectors.joining("，"));

            item.setProcessNames(processNames);
        });

        //查询外协厂code
        BizSupplier supplier=bizSupplierService.getById(bizReturnReceipt.getSupplierId());
        bizReturnReceipt.setSupplierCode(supplier.getCode());

        // 创建SimpleDateFormat对象，并设置日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        bizReturnReceipt.setStringDate(dateFormat.format(bizReturnReceipt.getFormDate()));

        List<List<BizReturnReceiptDetail> > list = new ArrayList<>();

        //打印数据时每页14条
        if(returnReceiptDetails.size() > 14){
            // 用于临时存储每组数据的列表
            List<BizReturnReceiptDetail> group = new ArrayList<>();
            // 遍历 outsourcedOrderDetails 列表
            for (BizReturnReceiptDetail detail : returnReceiptDetails) {
                group.add(detail);
                // 每添加 14 个元素后，将其添加到 list 中，并重置 group
                if (group.size() == 14) {
                    // 使用流过滤出 productNum 不为空的元素，并对其 productNum 值求和
                    Integer sum = group.stream()
                            .filter(item -> item.getProductNum() != null) // 过滤出 productNum 不为空的元素
                            .mapToInt(BizReturnReceiptDetail::getProductNum) // 映射到 productNum 属性
                            .sum(); // 计算总和
                    // 然后，给每个对象的 sum 属性赋值
                    for (BizReturnReceiptDetail item : group) {
                        item.setSum(sum);
                        item.setOriginalCarrierCount(item.getNewCarrierCount()==null?item.getOriginalCarrierCount():item.getNewCarrierCount());
                    }
                    list.add(new ArrayList<>(group));
                    group = new ArrayList<>();
                }
            }
            // 如果最后一组不足 14 个元素，也将其添加到 list 中
            if (!group.isEmpty()) {
                BizReturnReceiptDetail detail=new BizReturnReceiptDetail();
                while (group.size() < 14) {
                    group.add(detail); // 添加默认元素直到总数为14
                }
                list.add(group);
            }
        }else{
            BizReturnReceiptDetail detail=new BizReturnReceiptDetail();
            while (returnReceiptDetails.size() < 14) {
                returnReceiptDetails.add(detail); // 添加默认元素直到总数为14
            }
            // 使用流过滤出 productNum 不为空的元素，并对其 productNum 值求和
            Integer sum = returnReceiptDetails.stream()
                    .filter(item -> item.getReceiptNum() != null) // 过滤出 productNum 不为空的元素
                    .mapToInt(BizReturnReceiptDetail::getReceiptNum) // 映射到 productNum 属性
                    .sum(); // 计算总和
            // 然后，给每个对象的 sum 属性赋值
            for (BizReturnReceiptDetail receiptDetail : returnReceiptDetails) {
                receiptDetail.setSum(sum);
                receiptDetail.setOriginalCarrierCount(receiptDetail.getNewCarrierCount()==null?receiptDetail.getOriginalCarrierCount():receiptDetail.getNewCarrierCount());
            }

            list.add(returnReceiptDetails);
        }
        bizReturnReceipt.setDetailLists(list);


        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("returnReceipt" , bizReturnReceipt);
        Writer out = new StringWriter();
        //获取模板地址
        Template template = freeMarkerConfigurer.getConfiguration().getTemplate("returnReceiptPdf.html");
        template.process(paramMap, out);
        out.flush();
        out.close();
        String templateContent = out.toString();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/pdf");
        String fileName ="外协收回明细";
        response.setHeader("Content-Disposition", "filename=" + new String(fileName.getBytes()));
        byte[] resources = PdfUtil.html2Pdf(templateContent);
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(resources);
        outputStream.close();
    }
}
