package com.bonus.material.lease.controller;

import cn.hutool.core.convert.Convert;
import com.bonus.common.biz.config.ListPagingUtil;
import com.bonus.common.biz.domain.LeaseRecordInfo;
import com.bonus.common.biz.domain.lease.LeaseApplyInfo;
import com.bonus.common.biz.domain.lease.LeasePublishInfo;
import com.bonus.common.core.utils.ServletUtils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.utils.poi.ExcelUtil;
import com.bonus.common.core.web.controller.BaseController;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.log.annotation.SysLog;
import com.bonus.common.log.enums.OperaType;
import com.bonus.material.archives.service.ArchivesService;
import com.bonus.material.common.annotation.PreventRepeatSubmit;
import com.bonus.material.lease.domain.LeaseApplyDetails;
import com.bonus.material.lease.domain.LeasePublishDetails;
import com.bonus.material.lease.domain.vo.LeaseApplyRequestVo;
import com.bonus.material.lease.service.ILeaseTaskService;
import com.bonus.material.ma.domain.Type;
import com.bonus.material.ma.domain.vo.MaTypeVoLevelTwo;
import com.bonus.system.api.RemoteFileService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.mock.web.MockMultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.List;

/**
 * @author hay
 * @description 业务办理--领用任务
 * @date 2025/2/17 13:13
 */
@Api(tags = "领用任务接口")
@RestController
@RequestMapping("/leaseTask")
public class LeaseTaskController extends BaseController {

    @Resource
    private ILeaseTaskService service;

    @Resource
    private RemoteFileService sysFileService;

    @Resource
    private ArchivesService archivesService;

    /**
     * 新增领用任务
     */
    @ApiOperation(value = "新增领用任务")
    @PreventRepeatSubmit
    @SysLog(title = "领用任务", businessType = OperaType.INSERT, logType = 1, module = "领用申请->新增领用任务")
    @PostMapping
    public AjaxResult add(@NotNull(message = "领用任务不能为空") @RequestBody LeaseApplyRequestVo leaseApplyRequestVo) {
        try {
            return service.insertLeaseApplyInfo(leaseApplyRequestVo);
        } catch (Exception e) {
            return error("系统错误, " + e.getMessage());
        }
    }

    /**
     * 领用记录查询
     */
    @ApiOperation(value = "领用记录列表查询")
    @GetMapping("/list")
    public AjaxResult list(LeaseApplyInfo leaseApplyInfo) {
        Integer pageIndex = Convert.toInt(ServletUtils.getParameter("pageNum"), 1);
        Integer pageSize = Convert.toInt(ServletUtils.getParameter("pageSize"), 10);
        try {
            List<LeaseApplyInfo> list = service.selectLeaseApplyInfoList(leaseApplyInfo);
            if (leaseApplyInfo.getIsApp()==null){
                return AjaxResult.success(ListPagingUtil.paging(pageIndex, pageSize, list));
            }else {
                return AjaxResult.success(list);
            }
        } catch (Exception e) {
            if (leaseApplyInfo.getIsApp()==null){
                return AjaxResult.success(ListPagingUtil.paging(pageIndex, pageSize, new ArrayList<>()));
            }else {
                return AjaxResult.success(new ArrayList<>());
            }
        }
    }

    /**
     * 上传业务联系单PDF文件
     */
    @PostMapping("/uploadPdf")
    @SysLog(title = "上传业务联系单PDF", businessType = OperaType.INSERT, module = "仓储管理->上传业务联系单PDF")
    public AjaxResult uploadPdf(@RequestParam("file") MultipartFile file, @RequestParam("id") Long id) {
        try {
            AjaxResult result = sysFileService.upload(file);
            if (!result.isSuccess()) {
                return AjaxResult.error("SysFile文件服务上传失败：" + result.get("msg"));
            }

            @SuppressWarnings("unchecked")
            Map<String, Object> jsonObject = (Map<String, Object>) result.get("data");
            String fileName = file.getOriginalFilename();
            String filePath = jsonObject.get("url").toString();

            return archivesService.uploadArchivesProjectPdf("业务联系单", fileName, filePath, Math.toIntExact(id));
        } catch (Exception e) {
            logger.error("上传业务联系单PDF文件失败", e);
            return AjaxResult.error("上传业务联系单PDF文件失败：" + e.getMessage());
        }
    }

    /**
     * 导出领料记录查询
     * @param response
     * @param leaseApplyInfo
     */
    @ApiOperation(value = "导出领料记录查询")
    @PostMapping("/exportLeaseRecord")
    public void exportLeaseRecord(HttpServletResponse response, LeaseApplyInfo leaseApplyInfo) {
        // 查询全部数据
        List<LeaseRecordInfo> list = service.getLeaseRecordList(leaseApplyInfo);
        // 导出分页后的数据
        ExcelUtil<LeaseRecordInfo> util = new ExcelUtil<>(LeaseRecordInfo.class);
        try {
            // 获取分页参数
            Integer pageNum = Convert.toInt(ServletUtils.getParameter("pageNum"), 1);
            Integer pageSize = Convert.toInt(ServletUtils.getParameter("pageSize"), 10);

            // 分页处理
            ListPagingUtil pagingUtil = ListPagingUtil.paging(pageNum, pageSize, list);
            @SuppressWarnings("unchecked")
            List<LeaseRecordInfo> pagedList = (List<LeaseRecordInfo>) pagingUtil.getRows();
            util.exportExcel(response, pagedList, "领料记录查询数据");
        } catch (Exception e) {
            util.exportExcel(response, list, "领料记录查询数据");
            logger.error("导出领料记录查询数据失败", e);
        }
    }

    /**
     * 领用发布查询
     * @param leaseApplyInfo
     * @return
     */
    @ApiOperation(value = "领用发布查询")
    @GetMapping("/getPublishList")
    public AjaxResult getPublishList(LeaseApplyInfo leaseApplyInfo) {
        Integer pageIndex = Convert.toInt(ServletUtils.getParameter("pageNum"), 1);
        Integer pageSize = Convert.toInt(ServletUtils.getParameter("pageSize"), 10);
        try {
            List<LeasePublishInfo> list = service.getPublishList(leaseApplyInfo);
            if (leaseApplyInfo.getIsApp()==null){
                return AjaxResult.success(ListPagingUtil.paging(pageIndex, pageSize, list));
            }else {
                return AjaxResult.success(list);
            }
        } catch (Exception e) {
            if (leaseApplyInfo.getIsApp()==null){
                return AjaxResult.success(ListPagingUtil.paging(pageIndex, pageSize, new ArrayList<>()));
            }else {
                return AjaxResult.success(new ArrayList<>());
            }
        }
    }

    /**
     * 领用发布详情
     * @param leaseApplyInfo
     * @return
     */
    @ApiOperation(value = "领用发布详情")
    @GetMapping("/getDetailsById")
    public AjaxResult getDetailsById(LeaseApplyInfo leaseApplyInfo) {
        return success(service.getDetailsById(leaseApplyInfo));
    }

    /**
     * 根据typeId查询待出库数量
     * @param typeId
     * @return
     */
    @ApiOperation(value = "根据typeId查询待出库数量")
    @GetMapping(value ="/getPendingOutNumByTypeId/{typeId}")
    public AjaxResult getPendingOutNumByTypeId(@PathVariable("typeId") Long typeId) {
        return service.getPendingOutNumByTypeId(typeId);
    }

    /**
     * 导出领料发布详情
     * @param response
     * @param leaseApplyInfo
     */
    @ApiOperation(value = "导出领料发布详情")
    @PostMapping("/exportPublishDetails")
    public void exportPublishDetails(HttpServletResponse response, LeaseApplyInfo leaseApplyInfo) {
        List<LeasePublishDetails> list = service.getPublishDetails(leaseApplyInfo);
        ExcelUtil<LeasePublishDetails> util = new ExcelUtil<>(LeasePublishDetails.class);
        util.exportExcel(response, list, "领料发布详情数据");

    }

    /**
     * 发布数据保存
     * @param leaseApplyRequestVo
     * @return
     */
    @ApiOperation(value = "发布数据保存")
    @PostMapping("/addPublish")
    public AjaxResult addPublish(@RequestBody LeaseApplyRequestVo leaseApplyRequestVo) {
        return service.addPublish(leaseApplyRequestVo);
    }

    /**
     * 领用发布驳回
     */
    @ApiOperation(value = "领用发布驳回")
    @PostMapping("/leasePublishReject")
    public AjaxResult leasePublishReject(@RequestBody LeaseApplyDetails leaseApplyDetails) {
        return service.leasePublishReject(leaseApplyDetails);
    }

    /**
     * 领料详情删除
     */
    @ApiOperation(value = "领料详情删除")
    @PostMapping("/delLeaseDetails")
    public AjaxResult delLeaseDetails(@RequestBody LeaseApplyDetails leaseApplyDetails) {
        return service.delLeaseDetails(leaseApplyDetails);
    }

    /**
     * 领用/领料---退回
     */
    @ApiOperation(value = "领料出库退回")
    @PostMapping("/leaseOutReject")
    public AjaxResult leaseOutReject(@RequestBody LeaseApplyDetails leaseApplyDetails) {
        return service.leaseOutReject(leaseApplyDetails);
    }

    /**
     * 领用发布终结
     * @param leaseApplyInfo
     * @return
     */
    @ApiOperation(value = "领用发布终结")
    @PostMapping("/endPublish")
    public AjaxResult endPublish(@RequestBody LeaseApplyInfo leaseApplyInfo) {
        return service.endPublish(leaseApplyInfo);
    }

    /**
     * 导出领料发布列表
     * @param response
     * @param leaseApplyInfo
     */
    @ApiOperation(value = "导出领料发布列表")
    @PostMapping("/exportPublish")
    public void exportPublish(HttpServletResponse response, LeaseApplyInfo leaseApplyInfo) {
        List<LeasePublishInfo> list = service.getPublishList(leaseApplyInfo);
        ExcelUtil<LeasePublishInfo> util = new ExcelUtil<>(LeasePublishInfo.class);
        util.exportExcel(response, list, "领料发布列表数据");

    }

    /**
     * 领用记录详情查看
     */
    @ApiOperation(value = "领用记录详情查看")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@NotNull(message = "领用任务ID不能为空") @PathVariable("id")  Long id,
                              @RequestParam(value = "keyWord", required = false) String keyWord) {
        return success(service.selectLeaseApplyInfoById(id, keyWord));
    }

    /**
     * 修改领用任务
     */
    @ApiOperation(value = "修改领用任务")
    @PreventRepeatSubmit
    @SysLog(title = "领用任务", businessType = OperaType.UPDATE, logType = 1,module = "仓储管理->修改领用任务")
    @PutMapping
    public AjaxResult edit(@RequestBody @NotNull LeaseApplyRequestVo leaseApplyRequestVo) {
        try {
            return toAjax(service.updateLeaseApplyInfo(leaseApplyRequestVo));
        } catch (Exception e) {
            return error("系统错误, " + e.getMessage());
        }
    }

    /**
     * 删除领用任务
     */
    @ApiOperation(value = "删除领用任务")
    @PreventRepeatSubmit
    @SysLog(title = "领用任务", businessType = OperaType.DELETE, logType = 1,module = "仓储管理->删除领用任务")
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(service.deleteLeaseApplyInfoByIds(ids));
    }


    /**
     * 查询规格型号对应数据
     */
    @ApiOperation(value = "查询规格型号对应数据")
    @GetMapping("/getTypeDataList")
    public AjaxResult getTypeDataList(Type bean) {
        try {
            List<Type> listByMaType = service.getTypeDataList(bean);
            return success(listByMaType);
        } catch (Exception e) {
            return success(new ArrayList<>());
        }

    }

    /**
     * 审核人员领用记录查询
     */
    @ApiOperation(value = "审核人员领用记录查询")
    @GetMapping("/auditList")
    public AjaxResult auditList(LeaseApplyInfo leaseApplyInfo) {
        Integer pageIndex = Convert.toInt(ServletUtils.getParameter("pageNum"), 1);
        Integer pageSize = Convert.toInt(ServletUtils.getParameter("pageSize"), 10);
        try {
            List<LeaseApplyInfo> list = service.selectAuditLeaseApplyInfoList(leaseApplyInfo);
            if (leaseApplyInfo.getIsApp()==null){
                return AjaxResult.success(ListPagingUtil.paging(pageIndex, pageSize, list));
            }else {
                return AjaxResult.success(list);
            }
        } catch (Exception e) {
            if (leaseApplyInfo.getIsApp()==null){
                return AjaxResult.success(ListPagingUtil.paging(pageIndex, pageSize, new ArrayList<>()));
            }else {
                return AjaxResult.success(new ArrayList<>());
            }
        }
    }

    /**
     * 生成采购单号
     */
    @ApiOperation(value = "生成采购单号")
    @GetMapping(value = "/getCode")
    public AjaxResult getCode() {
        return AjaxResult.success(service.getCode());
    }


    /**
     * 导出物资类型管理列表
     */
    @ApiOperation(value = "导出物资类型列表")
    @PreventRepeatSubmit
    @SysLog(title = "工器具物资类型", businessType = OperaType.EXPORT, module = "->导出物资类型")
    @PostMapping("/export")
    public void export(HttpServletResponse response) {
        List<MaTypeVoLevelTwo> maTypeVos = service.selectParentId();
        ExcelUtil<MaTypeVoLevelTwo> util = new ExcelUtil<>(MaTypeVoLevelTwo.class);
        util.exportExcel(response, maTypeVos, "工器具数据");

    }

    /**
     * 查询物资类型3级--前端联动式下拉框
     * 没有4级规格型号
     */
    @ApiOperation(value = "获取物资类型连动式下拉框")
    @GetMapping("/equipmentThreeType")
    public AjaxResult equipmentThreeType() {
        List<Type> listByMaType = service.getEquipmentThreeTypes();
        return success(listByMaType);
    }


    /**
     * 业务联系单pdf
     */
    @ApiOperation(value = "业务联系单pdf")
    @GetMapping("/getCodePDF/{taskId}")
    public AjaxResult getCodePDF(@PathVariable("taskId") Long taskId, Map<String, String> replacements) throws IOException, ParseException {
        InputStream in = getClass().getClassLoader().getResourceAsStream("template/yewu.docx");
        XWPFDocument document = new XWPFDocument(in);

        LeaseApplyInfo info = service.getApplyInfo(taskId);

        //订单日期
        replacements.put("${createTime}", String.valueOf(info.getCreateTime()));

        //合同编号
        replacements.put("${createBy}", String.valueOf(info.getCreateBy()));

        replacements.put("${unitName}", String.valueOf(info.getUnitName()));

        replacements.put("${leasePerson}", String.valueOf(info.getLeasePerson()));

        replacements.put("${companyName}", String.valueOf(info.getCompanyName()));

        replacements.put("${projectName}", String.valueOf(info.getProjectName()));

        replacements.put("${phone}", String.valueOf(info.getPhone()));

        replacements.put("${code}", String.valueOf(info.getCode()));

        // 假设 info.getCreateTime() 返回的是 String 类型的日期时间
        SimpleDateFormat inputFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH);
        SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date1 = inputFormat.parse(String.valueOf(info.getCreateTime()));
        String startTime = outputFormat.format(date1);
        // 将 startTime 字符串转换为 LocalDate 对象
        LocalDate localDate = LocalDate.parse(startTime);
        // 提取年、月、日
        int year = localDate.getYear();
        int month = localDate.getMonthValue();
        int day = localDate.getDayOfMonth();

        replacements.put("${year}", String.valueOf(year));

        replacements.put("${month}", String.valueOf(month));

        replacements.put("${day}", String.valueOf(day));

         //填充订单详情到表格
        fillOrderTable(document, info);

        //获取附件详情
        List<LeaseApplyDetails> details = service.getApplyDetails(taskId);


        //填充订单详情到表格
        fillOrderTableTwo(document, details);

        // 将拼接的字符串放入替换的map中
//        replacements.put("${orderTable}", orderDetail.toString());

        for (IBodyElement element : document.getBodyElements()) {
            if (element instanceof XWPFParagraph) {
                XWPFParagraph paragraph = (XWPFParagraph) element;
                for (XWPFRun run : paragraph.getRuns()) {
                    String text = run.getText(0);
                    if (text != null) {
                        for (Map.Entry<String, String> entry : replacements.entrySet()) {
                            String entryValue = entry.getValue();
                            if (entryValue == null) {continue;}
                            text = text.replace(entry.getKey(), entryValue);
                        }
                        run.setText(text, 0);
                    }
                }
            }
        }

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        document.write(outputStream);
        byte[] wordBytes = outputStream.toByteArray();
//        // 将 DOCX 转换为 PDF
//        ByteArrayOutputStream pdfOutputStream = new ByteArrayOutputStream();
//        try (XWPFDocument docxDocument = new XWPFDocument(new java.io.ByteArrayInputStream(wordBytes))) {
//            PdfOptions options = PdfOptions.create();
//            PdfConverter.getInstance().convert(docxDocument, pdfOutputStream, options);
//        } catch (IOException e) {
//            e.printStackTrace();
//            // 处理异常
//        }
//        byte[] pdfBytes = pdfOutputStream.toByteArray();

        MultipartFile file = new MockMultipartFile("contract", "contract.docx", MediaType.APPLICATION_OCTET_STREAM_VALUE, wordBytes);
//        MultipartFile file = new MockMultipartFile("contract", "contract.pdf", MediaType.APPLICATION_PDF_VALUE, pdfBytes);


        return sysFileService.upload(file);
    }

    private static void fillOrderTable(XWPFDocument document, LeaseApplyInfo info) {
        XWPFTable table = null;
        int headerRowIndex = 0; // 表头行索引
        int footerRowIndex = 0; // 合计行索引
        int cellCount = 0;
        try {
            // 获取第一个表格（假设模板中只有一个表格）
            table = document.getTables().get(0);
            Map<String, String> replacements = new HashMap<>();
            // 假设 info.getCreateTime() 返回的是 String 类型的日期时间
            SimpleDateFormat inputFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH);
            SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date date1 = inputFormat.parse(String.valueOf(info.getCreateTime()));
            String startTime = outputFormat.format(date1);
            // 将 startTime 字符串转换为 LocalDate 对象
            LocalDate localDate = LocalDate.parse(startTime);
            // 提取年、月、日
            int year = localDate.getYear();
            int month = localDate.getMonthValue();
            int day = localDate.getDayOfMonth();

            replacements.put("${year}", String.valueOf(year));

            replacements.put("${month}", String.valueOf(month));

            replacements.put("${day}", String.valueOf(day));
            replacements.put("${companyName}", info.getCompanyName());
            replacements.put("TTTleas", info.getLeasePerson());
            replacements.put("${unitName}", info.getUnitName());
            replacements.put("${projectName}", info.getProjectName());
            replacements.put("${phone}", info.getPhone());
            replacements.put("${code}", info.getCode());
            replacements.put("${createTime}", String.valueOf(info.getCreateTime()));
            replacements.put("${createBy}", String.valueOf(info.getCreateBy()));

            // 遍历表格的每一行
            for (int i = 0; i < table.getNumberOfRows(); i++) {
                XWPFTableRow row = table.getRow(i);
                // 遍历行中的每个单元格
                for (int j = 0; j < row.getTableCells().size(); j++) {
                    XWPFTableCell cell = row.getCell(j);
                    // 遍历单元格中的每个段落
                    for (XWPFParagraph paragraph : cell.getParagraphs()) {
                        // 遍历段落中的每个运行对象
                        for (XWPFRun run : paragraph.getRuns()) {
                            String text = run.getText(0);
                            if (text != null) {
                                // 遍历替换映射
                                for (Map.Entry<String, String> entry : replacements.entrySet()) {
                                    String placeholder = entry.getKey();
                                    String value = entry.getValue();
                                    if (StringUtils.isNotBlank(placeholder) && StringUtils.isNotBlank(value)) {
                                        if (text.contains(placeholder)) {
                                            // 替换占位符为实际值
                                            text = text.replace(placeholder, value);
                                            run.setText(text, 0);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

        } catch (IndexOutOfBoundsException e) {
            throw new RuntimeException("模板表处理异常，请检查合同信息");
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }


    private static void fillOrderTableTwo(XWPFDocument document, List<LeaseApplyDetails> orderDetails) {
        XWPFTable table = null;
        int headerRowIndex = 0; // 表头行索引
        int footerRowIndex = 0; // 合计行索引
        int cellCount = 0;
        try {
            // 获取第一个表格（假设模板中只有一个表格）
            table = document.getTables().get(1);

            // 保留第一行（表头）和最后一行（合计行），仅在中间插入数据行
            headerRowIndex = 0;
            footerRowIndex = table.getRows().size();

            // 删除中间的所有行（如果有的话）
            for (int i = table.getRows().size() - 2; i > headerRowIndex; i--) {
                table.removeRow(i);
            }
            // 获取表头行的单元格数量
            cellCount = table.getRow(headerRowIndex).getTableCells().size();

            // 遍历订单详情并动态插入数据行
            SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        } catch (IndexOutOfBoundsException e) {
            throw new RuntimeException("模板表处理异常，请检查合同信息");
        }
        int num = orderDetails.size();
        for (LeaseApplyDetails detail : orderDetails) {
            XWPFTableRow newRow = table.insertNewTableRow(headerRowIndex + 1);

            // 确保新行有足够数量的单元格
            while (newRow.getTableCells().size() < cellCount) {
                newRow.createCell();
            }
            int cellIndex = 0;
            // 序号
            newRow.getCell(cellIndex++).setText(String.valueOf(num));
            num--;

            // 机具名称
            newRow.getCell(cellIndex++).setText(detail.getMaTypeName());
            String typeName = detail.getTypeName();
            // 规格型号
            newRow.getCell(cellIndex++).setText(typeName);
            // 单位
            newRow.getCell(cellIndex++).setText(detail.getUnitName());
            // 数量
            newRow.getCell(cellIndex++).setText(String.valueOf(detail.getPreNum()));
            // 备注
            newRow.getCell(cellIndex++).setText(detail.getRemark() );


        }
    }
}
