package com.dcsoft.system.visitor.controller;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.dcsoft.common.core.constant.CacheConstants;
import com.dcsoft.common.core.constant.Constants;
import com.dcsoft.common.core.domain.R;
import com.dcsoft.common.core.enums.ExamineEnum;
import com.dcsoft.common.core.exception.ServiceException;
import com.dcsoft.common.core.utils.CollUtil;
import com.dcsoft.common.core.utils.SmsUtils;
import com.dcsoft.common.core.utils.poi.ExcelUtil;
import com.dcsoft.common.core.web.controller.BaseController;
import com.dcsoft.common.core.web.domain.AjaxResult;
import com.dcsoft.common.core.web.page.TableDataInfo;
import com.dcsoft.common.log.annotation.Log;
import com.dcsoft.common.log.enums.BusinessType;
import com.dcsoft.common.redis.service.RedisService;
import com.dcsoft.common.security.annotation.RequiresPermissions;
import com.dcsoft.common.security.utils.SecurityUtils;
import com.dcsoft.common.sms.config.properties.SmsProperties;
import com.dcsoft.system.api.RemoteFileService;
import com.dcsoft.system.api.domain.SysFile;
import com.dcsoft.system.api.domain.SysUser;
import com.dcsoft.system.api.model.LoginUser;
import com.dcsoft.system.domain.SysPeople;
import com.dcsoft.system.domain.vo.IdNamelVo;
import com.dcsoft.system.service.ISysDictDataService;
import com.dcsoft.system.service.ISysPeopleService;
import com.dcsoft.system.service.ISysUserService;
import com.dcsoft.system.utils.ByteArrayMultipartFile;
import com.dcsoft.system.utils.PdfWatermark;
import com.dcsoft.system.utils.UuidUtil;
import com.dcsoft.system.visitor.domain.*;
import com.dcsoft.system.visitor.service.IVisCarryStuffService;
import com.dcsoft.system.visitor.service.IVisExitOutRecordService;
import com.dcsoft.system.visitor.service.IVisVisitorExamineService;
import com.dcsoft.system.visitor.service.IVisitorService;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/stuff")
public class VisCarryStuffController  extends BaseController {


    @Resource
    private IVisCarryStuffService visCarryStuffService;

    @Autowired
    private ISysDictDataService dictDataService;

    @Autowired
    private ISysPeopleService sysPeopleService;

    @Autowired
    private VisitorController visitorController;

    @Autowired
    private IVisitorService visitorService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private SmsProperties smsProperties;

    @Autowired
    private IVisVisitorExamineService visVisitorExamineService;

    @Resource
    private IVisExitOutRecordService visExitOutRecordService;

    private static final String APPROVE_KEY = "APPROVE_KEY:STUFF_APPROVE";

    @Autowired
    private ISysUserService sysUserService;

    @Value("${sms.parkName:'兴安智慧园区'}")
    private String parkName;

    @Value("${app.deptId:228}")
    private String appDeptId;

    @Value("${app.watermarkUrl:http://81.68.71.142:9000/others/gz/gz.png}")
    private String watermarkUrl;

    @Autowired
    private RemoteFileService remoteFileService;


    @GetMapping("/list")
    public TableDataInfo list(VisExitOutVo vo) {
        startPage();
        List<VisExitOutVo> list = visCarryStuffService.selectList(vo);
        if (CollUtil.isEmpty(list)) {
            return getDataTable(list);
        }

        //查询物品信息列表
        List<Long> collect = list.stream().map(VisExitOutVo::getId).collect(Collectors.toList());
        VisStuffInfoVo visStuffInfoVo = new VisStuffInfoVo();
        visStuffInfoVo.setExitIds(collect);
        List<VisStuffInfoVo> stuffList = visCarryStuffService.selectStuffList(visStuffInfoVo);
        if (CollUtil.isEmpty(stuffList)) {
            return getDataTable(list);
        }

        //处理字典值
        Map<String, String> map = dictDataService.queryDictData("vis_out_stuff_type");
        stuffList.forEach(stuff -> {
            if (StrUtil.isNotBlank(stuff.getType())) {
                stuff.setTypeName(map.get(stuff.getType()));
            }
            if (StrUtil.isNotBlank(stuff.getBackType())) {
                stuff.setBackTypeName(map.get(stuff.getBackType()));
            }
            if (StrUtil.isNotBlank(stuff.getImgUrls())) {
                stuff.setImgUrlList(Arrays.asList(stuff.getImgUrls().split(",")));
            }
            if (StrUtil.isNotBlank(stuff.getBackImgUrls())) {
                stuff.setBackImgUrlList(Arrays.asList(stuff.getBackImgUrls().split(",")));
            }
        });

        //查询放行保安名字
        VisExitOutRecordVo visExitOutRecordVo = new VisExitOutRecordVo();
        visExitOutRecordVo.setExitIds(collect);
        List<VisExitOutRecordVo> rList = visExitOutRecordService.selectList(visExitOutRecordVo);
        Map<Long, String> map1 = new HashMap<>();
        if (CollUtil.isNotEmpty(rList)) {
            map1 = rList.stream().collect(Collectors.toMap(VisExitOutRecordVo::getExitId, VisExitOutRecordVo::getUserName, (key1, key2) -> key1));
        }

        //构造数据
        Map<Long, List<VisStuffInfoVo>> collect1 = stuffList.stream().collect(Collectors.groupingBy(VisStuffInfoVo::getExitId));
        Map<Long, String> finalMap = map1;
        list.forEach(exit -> {
            exit.setVisStuffInfoList(collect1.get(exit.getId()));
            if (null != finalMap.get(exit.getId())) {
                exit.setReleaseName(finalMap.get(exit.getId()));
            }
        });

        return getDataTable(list);
    }


    @GetMapping("/appList")
    public TableDataInfo appList(VisExitOutVo vo) {
        startPage();
        if (!StringUtils.equals(appDeptId, vo.getAppDeptId())) {
            LoginUser user = SecurityUtils.getLoginUser();
            vo.setCreateBy(user.getUsername());
        }
        List<VisExitOutVo> list = visCarryStuffService.selectList(vo);
        if (CollUtil.isEmpty(list)) {
            return getDataTable(list);
        }

        //查询物品信息列表
        List<Long> collect = list.stream().map(VisExitOutVo::getId).collect(Collectors.toList());
        VisStuffInfoVo visStuffInfoVo = new VisStuffInfoVo();
        visStuffInfoVo.setExitIds(collect);
        List<VisStuffInfoVo> stuffList = visCarryStuffService.selectStuffList(visStuffInfoVo);
        if (CollUtil.isEmpty(stuffList)) {
            return getDataTable(list);
        }

        //处理字典值
        Map<String, String> map = dictDataService.queryDictData("vis_out_stuff_type");
        stuffList.forEach(stuff -> {
            if (StrUtil.isNotBlank(stuff.getType())) {
                stuff.setTypeName(map.get(stuff.getType()));
            }
            if (StrUtil.isNotBlank(stuff.getBackType())) {
                stuff.setBackTypeName(map.get(stuff.getBackType()));
            }
            if (StrUtil.isNotBlank(stuff.getImgUrls())) {
                stuff.setImgUrlList(Arrays.asList(stuff.getImgUrls().split(",")));
            }
            if (StrUtil.isNotBlank(stuff.getBackImgUrls())) {
                stuff.setBackImgUrlList(Arrays.asList(stuff.getBackImgUrls().split(",")));
            }
        });

        //构造数据
        Map<Long, List<VisStuffInfoVo>> collect1 = stuffList.stream().collect(Collectors.groupingBy(VisStuffInfoVo::getExitId));
        list.forEach(exit -> {
            exit.setVisStuffInfoList(collect1.get(exit.getId()));
        });

        return getDataTable(list);
    }

    /**
     * 获取携物信息详细信息（详情）
     */
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        VisExitOutVo stuffVo = visCarryStuffService.selectVisExitOutById(id);

        //查询物品信息列表
        VisStuffInfoVo visStuffInfoVo = new VisStuffInfoVo();
        visStuffInfoVo.setExitId(stuffVo.getId());
        List<VisStuffInfoVo> stuffList = visCarryStuffService.selectStuffList(visStuffInfoVo);
        if (CollUtil.isNotEmpty(stuffList)) {
            //处理字典
            Map<String, String> map = dictDataService.queryDictData("vis_out_stuff_type");
            stuffList.forEach(stuff -> {
                if (StrUtil.isNotBlank(stuff.getType())) {
                    stuff.setTypeName(map.get(stuff.getType()));
                }
                if (StrUtil.isNotBlank(stuff.getBackType())) {
                    stuff.setBackTypeName(map.get(stuff.getBackType()));
                }
                if (StrUtil.isNotBlank(stuff.getImgUrls())) {
                    stuff.setImgUrlList(Arrays.asList(stuff.getImgUrls().split(",")));
                }
                if (StrUtil.isNotBlank(stuff.getBackImgUrls())) {
                    stuff.setBackImgUrlList(Arrays.asList(stuff.getBackImgUrls().split(",")));
                }
            });
            stuffVo.setVisStuffInfoList(stuffList);
        }

        //查询二维码信息
        if (StringUtils.equals(ExamineEnum.PASSED.getCode(), stuffVo.getExamineState())) {
            CheckCodeVo codeVo = visCarryStuffService.selectStuffCheckCode(id);
            if (ObjectUtil.isNotNull(codeVo)) {
                stuffVo.setQrCode(codeVo.getCode());
            }
        }

        //查询审核信息
        List<VisitorReviewProcessVo> reviewProcess = visCarryStuffService.queryVisitorReviewProcessList(id);
        if (CollUtil.isNotEmpty(reviewProcess)) {
            boolean flag = true;
            for (VisitorReviewProcessVo process : reviewProcess) {
                if (!flag) {
                    process.setState(null);
                }
                if (Constants.ONE.equals(process.getState())) {
                    flag = false;
                }
            }
            stuffVo.setReviewProcessList(reviewProcess);
        }

        //查询放行记录，确认保安是否已放行
        VisExitOutRecordVo visExitOutRecordVo = new VisExitOutRecordVo();
        visExitOutRecordVo.setExitId(id);
        List<VisExitOutRecordVo> visExitOutRecordVos = visExitOutRecordService.selectList(visExitOutRecordVo);
        if (CollUtil.isNotEmpty(visExitOutRecordVos)) {
            stuffVo.setIsRelease(1);
        }
        return success(stuffVo);
    }


    /**
     * 新增访客信息
     */
    @Log(title = "出门证申请", businessType = BusinessType.INSERT)
    @PostMapping
    @Transactional
    public AjaxResult add(@Validated @RequestBody VisExitOutVo vo) {
        log.info("新增出门证申请信息：{}", vo);
        //校验是否存在返厂物资
        List<VisStuffInfoVo> visStuffInfoList = vo.getVisStuffInfoList();
        for (VisStuffInfoVo visStuffInfoVo : visStuffInfoList) {
            if (visStuffInfoVo.getIsBack() == 1) {
                vo.setIsExistBack(1);
                if (visStuffInfoVo.getBackNumber() > visStuffInfoVo.getNumber()) {
                    throw new ServiceException("返厂物资数量不能大于出厂物资数量！");
                }
            }
        }

        String url = "";
        // 查询一级审核人，企微发送消息（小程序来源）
        SysPeople people = sysPeopleService.selectSysPeopleById(vo.getReviewer1());
        try {
            //新增出门申请
            visCarryStuffService.insertVisExitOut(vo);

            //新增物资信息
            visStuffInfoList.forEach(stuff -> stuff.setExitId(vo.getId()));
            visCarryStuffService.insertVisStuffInfo(visStuffInfoList);

            url = getExamineUrl(String.valueOf(vo.getId()), people.getPhone());

            //新增审核环节信息
            List<VisExitOutVo> list = new ArrayList<>();
            VisExitOutVo visExitOutVo = new VisExitOutVo();
            visExitOutVo.setId(vo.getId());
            visExitOutVo.setReviewer(vo.getReviewer1());
            visExitOutVo.setState(ExamineEnum.IN_REVIEW.getCode());
            visExitOutVo.setApproveNode(1);
            visExitOutVo.setApproveData(url.substring(url.lastIndexOf("=") + 1));
            list.add(visExitOutVo);

            VisExitOutVo visExitOutVo2 = new VisExitOutVo();
            visExitOutVo2.setId(vo.getId());
            visExitOutVo2.setReviewer(vo.getReviewer2());
            visExitOutVo2.setState(ExamineEnum.IN_REVIEW.getCode());
            visExitOutVo2.setApproveNode(2);
            list.add(visExitOutVo2);

            VisExitOutVo visExitOutVo3 = new VisExitOutVo();
            visExitOutVo3.setId(vo.getId());
            visExitOutVo3.setReviewer(vo.getReviewer3());
            visExitOutVo3.setState(ExamineEnum.IN_REVIEW.getCode());
            visExitOutVo3.setApproveNode(3);
            list.add(visExitOutVo3);
            //保存审核环节表
            visCarryStuffService.saveVisitorReviewProcessList(list);

        } catch (Exception e) {
            log.error("出门证申请add异常：", e);
            throw new ServiceException("系统异常，请重新提交或联系管理员！");
        }
        //发送企微信息
        try {
            log.info("出门证申请add发送：{}审核链接：{}", people.getPhone(), url);
            visitorController.sendWeCom(people.getPhone(), url + " --访客姓名：" + vo.getName());
        } catch (Exception e) {
            log.error("出门证申请add-sendWeCom异常：", e);
            throw new ServiceException("系统异常，请重新提交或联系管理员！");
        }

        return AjaxResult.success();
    }

    /**
     * 获取审核链接
     *
     * @return
     */
    public String getExamineUrl(String id, String telephone) {
        //生成8位短参作为缓存key
        String code = UuidUtil.getShortUuid();
        try {
            while (redisService.hasKey(code)) {
                code = UuidUtil.getShortUuid();
            }
            redisService.setCacheObject(CacheConstants.VIS_CARRY_STUFF_CODE + code, id + "&" + telephone, 30L, TimeUnit.DAYS);
        } catch (Exception e) {
            throw new ServiceException("缓存数据异常：" + e.getMessage());
        }
        return "https://fk.xyxaks.cn/h5/?c=" + code + "2";
    }

    /**
     * 生成出门证编号
     * @return
     */
    @PostMapping("/getExitPermitNo")
    public AjaxResult getExitPermitNo() {
        return AjaxResult.success("操作成功", System.currentTimeMillis() + SmsUtils.generateSmsCode());
    }

    /**
     * 流程审核
     */
    @Log(title = "携物流程审核", businessType = BusinessType.UPDATE)
    @PostMapping("/approve")
    @Transactional
    public AjaxResult approve(@RequestBody VisExitOutVo vo) {
        log.info("携物流程审核入参 {}", JSON.toJSONString(vo));
        try {
            String telephone = StringUtils.isBlank(vo.getTelephone()) ? "1" : vo.getTelephone();
            Boolean lock = redisService.lock(APPROVE_KEY, telephone, 60 * 5, TimeUnit.SECONDS);
            if (!lock) {
                log.error("approve-审核人员正在审核中");
                return error("正在审核中");
            }
            //查询当前审核地址是否已审核
            VisitorReviewProcessVo visitorReviewProcessVo = new VisitorReviewProcessVo();
            visitorReviewProcessVo.setExitId(vo.getId());
            visitorReviewProcessVo.setApproveData(vo.getApproveData());
            VisitorReviewProcessVo visitorReviewProcess = visCarryStuffService.queryReviewProcess(visitorReviewProcessVo);
            if (ObjectUtil.isNotNull(visitorReviewProcess) && !StringUtils.equals(ExamineEnum.IN_REVIEW.getCode(), visitorReviewProcess.getState())) {
                log.error("stuff-approve-当前审核链接已审核");
                return error("当前链接已审核，请刷新页面！");
            }

            //查询当前审核人基本信息
            SysPeople sysPeople = sysPeopleService.queryPeopleName(telephone, null);

            //查询出门证申请详情信息
            VisExitOutVo stuffVo = visCarryStuffService.selectVisExitOutById(vo.getId());

            //保存审核环节表
            VisitorReviewProcessVo reviewProcess = new VisitorReviewProcessVo();
            reviewProcess.setState(vo.getExamineState());
            reviewProcess.setExitId(vo.getId());
            reviewProcess.setApproveNode(stuffVo.getCurrentNode());
            reviewProcess.setApproveData(vo.getApproveData());
            visCarryStuffService.updateVisitorReviewProcessById(reviewProcess);

            //保存审核历史表
            VisVisitorExamine examine = new VisVisitorExamine();
            examine.setExitId(vo.getId());
            examine.setCreateBy(sysPeople.getName());
            examine.setExamine(vo.getExamineState());

            //审核通过
            SysPeople people = new SysPeople();
            if(Constants.ZERO.equals(vo.getExamineState())) {
                //一级审核人审核
                if (stuffVo.getCurrentNode() == 1) {
                    vo.setExamineState("2");
                    vo.setCurrentNode(2);
                    //查询二级审核人信息，发送审核链接
                    people = sysPeopleService.selectSysPeopleById(stuffVo.getReviewer2());
                }
                //二级审核人审核
                else if (stuffVo.getCurrentNode() == 2) {
                    vo.setExamineState("2");
                    vo.setCurrentNode(3);
                    //查询三级审核人信息，发送审核链接
                    people = sysPeopleService.selectSysPeopleById(stuffVo.getReviewer3());
                }
                else {//三级审核，最后一级
                    //保存审核历史表
                    visVisitorExamineService.insertVisVisitorExamine(examine);

                    // 保存审核二维码地址信息
                    CheckCodeVo codeVo = new CheckCodeVo();
                    codeVo.setCode(String.valueOf(vo.getId()));
                    codeVo.setExitId(String.valueOf(vo.getId()));
                    codeVo.setId(UUID.randomUUID().toString().replace("-", ""));
                    visitorService.saveVisCheckCode(codeVo);

                    // 申请人发送短信（审核通过）
                    SysUser sysUser = sysUserService.selectUserById(stuffVo.getUserId());
                    try {
                        visitorController.sendMessage(sysUser.getPhonenumber(), "1", parkName, smsProperties.getTemplate2());
                    } catch (Exception e) {
                        log.error("短信发送异常：", e);
                    }
                }

                //向下级审核人发送审核信息
                if (stuffVo.getCurrentNode() != 3 ) {
                    String url = getExamineUrl(String.valueOf(vo.getId()), people.getPhone());
                    log.info("出门证申请approve发送：{}审核链接：{}", people.getPhone(), url);

                    //发送企微信息
                    try {
                    visitorController.sendWeCom(people.getPhone(), url + " --访客姓名：" + vo.getName());
                    } catch (Exception e) {
                        log.error("出门证申请approve-sendWeCom异常：", e);
                        throw new ServiceException("系统异常，请重新审核或联系管理员！");
                    }
                }
            }

            //审核拒绝
            if (Constants.ONE.equals(vo.getExamineState())) {
                //保存审核历史表
                visVisitorExamineService.insertVisVisitorExamine(examine);

                try {
                    visitorController.sendWeCom(telephone, vo.getName() + "的访客审核已驳回");
                } catch (Exception e) {
                    log.error("访客approve-sendWeCom驳回异常", e);
                    throw new ServiceException("系统异常，请重新审核或联系管理员！");
                }

                // 申请人发送短信（审核不通过）
                SysUser sysUser = sysUserService.selectUserById(stuffVo.getUserId());
                try {
                    visitorController.sendMessage(sysUser.getPhonenumber(), "1", parkName, smsProperties.getTemplate3());
                } catch (Exception e) {
                    log.error("短信发送异常：", e);
                }
            }

            visCarryStuffService.updateStaff(vo);
            return toAjax(true);
        } catch (Exception e) {
            log.error("审核异常:", e);
            throw new ServiceException("审核异常");
        }finally {
            redisService.deleteObject(APPROVE_KEY);
        }
    }

    /**
     * 查询审核人下拉数据
     * @return
     */
    @PostMapping("/getReviewerSelect")
    public AjaxResult getReviewerSelect(@RequestBody SysPeople people) {
        people.setBranchId("0");
        List<SysPeople> peopleList = sysPeopleService.selectSysPeopleLists(people);
        List<IdNamelVo> list = new ArrayList<>();
        peopleList.forEach(item -> {
            if (StrUtil.isNotBlank(item.getCarryStuffExamine())) {
                item.setCarryStuffExamineList(Arrays.asList(item.getCarryStuffExamine().split(",")));
            }

            IdNamelVo vo = new IdNamelVo();
            vo.setId(item.getId());
            vo.setName(item.getName());
            list.add(vo);
        });
        return AjaxResult.success(list);
    }

    /**
     * 导出出门证信息列表
     */
    @RequiresPermissions("visitor:stuff:export")
    @Log(title = "出门证申请", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, VisExitOutVo vo) {
        List<VisStuffInfoExportVo> list = visCarryStuffService.selectVisitorList(vo);

        List<Long> collect = list.stream().map(VisStuffInfoExportVo::getExitId).collect(Collectors.toList());

        //查询放行保安名字
        VisExitOutRecordVo visExitOutRecordVo = new VisExitOutRecordVo();
        visExitOutRecordVo.setExitIds(collect);
        List<VisExitOutRecordVo> rList = visExitOutRecordService.selectList(visExitOutRecordVo);
        Map<Long, String> map1 = new HashMap<>();
        if (CollUtil.isNotEmpty(rList)) {
            map1 = rList.stream().collect(Collectors.toMap(VisExitOutRecordVo::getExitId, VisExitOutRecordVo::getUserName, (key1, key2) -> key1));
        }

        Map<Long, String> finalMap = map1;
        Map<String, String> map = dictDataService.queryDictData("vis_out_stuff_type");
        list.forEach(stuff -> {
            if (StrUtil.isNotBlank(stuff.getType())) {
                stuff.setTypeName(map.get(stuff.getType()));
            }
            if (StrUtil.isNotBlank(stuff.getBackType())) {
                stuff.setBackTypeName(map.get(stuff.getBackType()));
            }
            if (StrUtil.isNotBlank(stuff.getImgUrls())) {
                String[] split = stuff.getImgUrls().split(",");
                for (int i = 0; i < split.length; i++) {
                    if (i == 0) {
                        stuff.setImgUrls1(split[i]);
                    }
                    if (i == 1) {
                        stuff.setImgUrls2(split[i]);
                    }
                    if (i == 2) {
                        stuff.setImgUrls3(split[i]);
                    }
                }
            }
            if (null != finalMap.get(stuff.getExitId())) {
                stuff.setReleaseName(finalMap.get(stuff.getExitId()));
            }
        });
        ExcelUtil<VisStuffInfoExportVo> util = new ExcelUtil<>(VisStuffInfoExportVo.class);
        util.exportExcel(response, list, "出厂物资明细数据");
    }

    /**
     * 取消出门证申请
     */
    @Log(title = "取消出门证申请", businessType = BusinessType.DELETE)
    @PostMapping("/cancel")
    @Transactional
    public AjaxResult cancel(@RequestBody VisExitOutVo vo) {
        log.info("取消出门证申请 {}", JSON.toJSONString(vo));
        //审核业务
        visCarryStuffService.cancel(vo);

        return toAjax(true);
    }


    /**
     * 根据ID查询出门记录并生成PDF
     */
    @GetMapping("/exportPdf/{id}")
    public AjaxResult exportPdf(@PathVariable("id") Long id) {
        try {
            //查询主数据
            VisExitOutVo visExitOutVo = visCarryStuffService.selectVisExitOutById(id);
            if (StringUtils.equals("5", visExitOutVo.getExamineState())) {
               return error("该申请已失效！");
            }
            //查询物品信息列表
            VisStuffInfoVo visStuffInfoVo = new VisStuffInfoVo();
            visStuffInfoVo.setExitId(id);
            List<VisStuffInfoVo> stuffList = visCarryStuffService.selectStuffList(visStuffInfoVo);
            if (CollUtil.isNotEmpty(stuffList)) {
                //处理字典
                Map<String, String> map = dictDataService.queryDictData("vis_out_stuff_type");
                stuffList.forEach(stuff -> {
                    if (StrUtil.isNotBlank(stuff.getType())) {
                        stuff.setTypeName(map.get(stuff.getType()));
                    }
                });
            }

            // 创建PDF文档
            Document document = new Document(new RectangleReadOnly(842F, 595F));
            document.setMargins(60, 60, 72, 72);
            
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PdfWriter writer = PdfWriter.getInstance(document, baos);
            
            // 添加水印事件处理器
//            PdfWatermark pdfWatermark = new PdfWatermark(watermarkUrl);
//            writer.setPageEvent(pdfWatermark);
            
            document.open();

            // 设置中文字体
            BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            Font contentFont = new Font(bfChinese, 10, Font.NORMAL);
            Font titleFont = new Font(bfChinese, 14, Font.BOLD);

            // 创建主表格（2列：左边表单，右边二维码）
//            PdfPTable mainTable = new PdfPTable(2);
//            mainTable.setWidthPercentage(100);
//            mainTable.setSpacingBefore(10f);

            // 添加标题
            Paragraph title = new Paragraph("兴安化工出门证", titleFont);
            title.setAlignment(Element.ALIGN_CENTER);
            document.add(title);

            // 添加表单内容
            PdfPTable formTable = new PdfPTable(2);
            formTable.setWidthPercentage(90);
            formTable.setHorizontalAlignment(Element.ALIGN_CENTER);

            // 创建数据表格
            float[] widths = {15f, 15f, 15f, 15f, 15f, 15f, 15f, 15f, 15f, 15f};
            PdfPTable dataForm = new PdfPTable(widths);
            dataForm.setWidthPercentage(100);
            dataForm.setSpacingBefore(10f);

            // 添加表头
            addFromHeader(dataForm, contentFont);

            // 添加表单的表格数据
            addFromRow(dataForm, visExitOutVo, contentFont);
            document.add(dataForm);

            // 下半部分：物资信息表格保持不变
//            Paragraph tableTitle = new Paragraph("物资信息", titleFont);
//            tableTitle.setAlignment(Element.ALIGN_CENTER);
//            document.add(tableTitle);

            // 创建数据表格
            PdfPTable dataTable = new PdfPTable(widths);
            dataTable.setWidthPercentage(100);
            dataTable.setSpacingBefore(10f);

            // 添加表头
            addTableHeader(dataTable, contentFont);
            
            // 添加表格数据
            if(CollUtil.isNotEmpty(stuffList)){
                int i = 1;
                for (VisStuffInfoVo vo : stuffList) {
                    addTableRow(dataTable, vo, contentFont, i);
                    i++;
                }
            }
            
            document.add(dataTable);
            document.add(new Paragraph("\n"));  // 增加空行间距

            // 创建底部表格（2列：左边二维码+文字，右边水印+文字）
            PdfPTable footerTable = new PdfPTable(2);
            footerTable.setWidthPercentage(80);  // 调整表格宽度为80%
            footerTable.setHorizontalAlignment(Element.ALIGN_CENTER);  // 表格整体居中
            footerTable.setSpacingBefore(20f);

            // 左边列：二维码和文字（水平排列）
            PdfPTable qrColumn = new PdfPTable(2);
            qrColumn.setWidths(new float[]{1, 2});
            qrColumn.setWidthPercentage(100);

            // 添加二维码文字（左）并设置垂直居中
            Paragraph qrText = new Paragraph("出门证二维码:", contentFont);
            PdfPCell qrTextCell = new PdfPCell(qrText);
            qrTextCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            qrTextCell.setHorizontalAlignment(Element.ALIGN_CENTER);  // 文字水平居中
            qrTextCell.setBorder(Rectangle.NO_BORDER);
            qrTextCell.setPaddingRight(-100);  // 减小右边距
            qrColumn.addCell(qrTextCell);

            // 生成二维码图片（右）
            CheckCodeVo checkCodeVo = visCarryStuffService.selectStuffCheckCode(id);
            if (ObjectUtil.isNotNull(checkCodeVo) && StrUtil.isNotBlank(checkCodeVo.getCode())) {
                BarcodeQRCode qrCode = new BarcodeQRCode(checkCodeVo.getCode(), 120, 120, null);
                Image qrCodeImage = qrCode.getImage();
                qrCodeImage.scaleAbsolute(100, 100);
                qrColumn.addCell(createCell(qrCodeImage, Element.ALIGN_CENTER));  // 图片居中
            }

            // 右边列：水印和文字（水平排列）
            PdfPTable watermarkColumn = new PdfPTable(2);
            watermarkColumn.setWidths(new float[]{1, 2});
            watermarkColumn.setWidthPercentage(100);

            // 添加水印文字（左）并设置垂直居中
            Paragraph watermarkText = new Paragraph("出厂许可授权章:", contentFont);
            PdfPCell watermarkTextCell = new PdfPCell(watermarkText);
            watermarkTextCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            watermarkTextCell.setHorizontalAlignment(Element.ALIGN_CENTER);  // 文字水平居中
            watermarkTextCell.setBorder(Rectangle.NO_BORDER);
            watermarkTextCell.setPaddingRight(-80);  // 减小右边距
            watermarkColumn.addCell(watermarkTextCell);
            
            // 添加水印图片（右）
            Image watermarkImage = Image.getInstance(watermarkUrl);
            watermarkImage.scaleAbsolute(90, 90);
            watermarkColumn.addCell(createCell(watermarkImage, Element.ALIGN_CENTER));  // 图片居中

            // 将左右列添加到底部表格
            footerTable.addCell(createCell(qrColumn, Element.ALIGN_CENTER));  // 左列居中
            footerTable.addCell(createCell(watermarkColumn, Element.ALIGN_CENTER));  // 右列居中
            
            document.add(footerTable);

            document.close();

            // 转换为MultipartFile并上传
            String fileName = "exit_record_" + id + ".pdf";
            MultipartFile multipartFile = new ByteArrayMultipartFile(baos.toByteArray(), fileName);
            R<SysFile> uploadResult = remoteFileService.uploadMinioPDF(multipartFile, fileName);

            return success(uploadResult.getData());
        } catch (Exception e) {
            log.error("生成PDF异常:", e);
            throw new ServiceException("生成PDF失败");
        }
    }

    // 创建带图片的单元格
    private PdfPCell createCell(Image image, int alignment) {
        PdfPCell cell = new PdfPCell(image);
        cell.setHorizontalAlignment(alignment);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setBorder(Rectangle.NO_BORDER);
        return cell;
    }

    // 创建带对齐方式的单元格
    private PdfPCell createCell(Phrase phrase, int alignment) {
        PdfPCell cell = new PdfPCell(phrase);
        cell.setBorder(Rectangle.NO_BORDER);
        cell.setHorizontalAlignment(alignment);
        return cell;
    }

    // 创建带对齐方式的表格单元格
    private PdfPCell createCell(PdfPTable table, int alignment) {
        PdfPCell cell = new PdfPCell(table);
        cell.setBorder(Rectangle.NO_BORDER);
        cell.setHorizontalAlignment(alignment);
        return cell;
    }


    // 添加表单行（两个字段）
    private void addFormRow(PdfPTable table, String label1, String value1, Font font) {
        // 第一个字段标签
        PdfPCell labelCell1 = new PdfPCell(new Paragraph(label1, font));
        labelCell1.setBorder(Rectangle.NO_BORDER);
        labelCell1.setHorizontalAlignment(Element.ALIGN_RIGHT);
        labelCell1.setVerticalAlignment(Element.ALIGN_MIDDLE);
        labelCell1.setPaddingRight(5);
        table.addCell(labelCell1);

        // 第一个字段值
        PdfPCell valueCell1 = new PdfPCell(new Paragraph(value1 != null ? value1 : "", font));
        valueCell1.setBorder(Rectangle.NO_BORDER);
        valueCell1.setHorizontalAlignment(Element.ALIGN_LEFT);
        table.addCell(valueCell1);
    }

    // 添加表格表头
    private void addFromHeader(PdfPTable table, Font font) {
        String[] headers = {"出门证编号", "申请人姓名", "申请单位", "申请日期", "事由", "工具", "车牌号", "部门审核", "生产或设备审核人", "人力综合部审核人"};
        for (String header : headers) {
            PdfPCell cell = new PdfPCell(new Paragraph(header, font));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            cell.setFixedHeight(25);
            table.addCell(cell);
        }
    }

    // 添加表格行数据
    private void addFromRow(PdfPTable table, VisExitOutVo vo, Font font) {
        table.addCell(createCell(vo.getExitPermitNo(), font));
        table.addCell(createCell(vo.getName(), font));
        table.addCell(createCell(vo.getVisitingUnit(), font));
        table.addCell(createCell(DateUtil.format(vo.getVisTime(), DatePattern.NORM_DATE_PATTERN), font));
        table.addCell(createCell(vo.getReason(), font));
        table.addCell(createCell(StrUtil.isBlank(vo.getVehicle()) ? "" : vo.getVehicle(), font));
        table.addCell(createCell(StrUtil.isBlank(vo.getCarNo()) ? "" : vo.getCarNo(), font));
        table.addCell(createCell(vo.getReviewerName1(), font));
        table.addCell(createCell(vo.getReviewerName2(), font));
        table.addCell(createCell(vo.getReviewerName3(), font));
    }

    // 添加表格表头
    private void addTableHeader(PdfPTable table, Font font) {
        String[] headers = {"序号", "物资名称", "规格型号", "物资类型", "物资用途", "数量","计量单位", "是否返厂", "返厂时间", "返厂数量"};
        for (String header : headers) {
            PdfPCell cell = new PdfPCell(new Paragraph(header, font));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            cell.setFixedHeight(25);
            table.addCell(cell);
        }
    }

    // 添加表格行数据
    private void addTableRow(PdfPTable table, VisStuffInfoVo vo, Font font, int i) {
        String backTime = vo.getBackTime() != null ?
                DateUtil.format(vo.getBackTime(), DatePattern.NORM_DATE_PATTERN) : "";
        String isBack = vo.getIsBack() == 1 ? "是" : "否";

        table.addCell(createCell(String.valueOf(i), font));
        table.addCell(createCell(vo.getName(), font));
        table.addCell(createCell(vo.getModel(), font));
        table.addCell(createCell(vo.getTypeName(), font));
        table.addCell(createCell(vo.getPurpose(), font));
        table.addCell(createCell(vo.getNumber() == null ? "" : String.valueOf(vo.getNumber()), font));
        table.addCell(createCell(vo.getUnit(), font));
        table.addCell(createCell(isBack, font));
        table.addCell(createCell(backTime, font));
        table.addCell(createCell(vo.getBackNumber() == null ? "" : String.valueOf(vo.getBackNumber()), font));
    }

    // 创建表格单元格
    private PdfPCell createCell(String text, Font font) {
        PdfPCell cell = new PdfPCell(new Paragraph(text != null ? text : "", font));
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setFixedHeight(20);
        return cell;
    }

    // 创建表格单元格
    @PostMapping("/expireVisCarryStuff")
    public void expireVisCarryStuff() {
        Date dateTime = DateUtil.beginOfDay(new Date());
        List<Long> list = visCarryStuffService.selectexpireVisCarryStuff(dateTime);
        if (CollUtil.isEmpty(list)) {
            return;
        }

        VisExitOutVo visExitOutVo = new VisExitOutVo();
        visExitOutVo.setIds(list);
        visExitOutVo.setExamineState("5");
        visCarryStuffService.updateStaffState(visExitOutVo);
    }

}


