package com.zhongshu.card.server.core.service.visitor;

import com.github.microservice.auth.client.model.UserFaceUploadModel;
import com.github.microservice.auth.client.service.UserFaceService;
import com.github.microservice.components.data.base.util.PageEntityUtil;
import com.github.microservice.core.util.bean.BeanUtil;
import com.github.microservice.models.gateDoor.use.DeviceUseParam;
import com.github.microservice.net.ResultContent;
import com.github.microservice.net.ResultMessage;
import com.github.microservice.types.user.DevicePermissFromType;
import com.github.microservice.types.user.UserFromType;
import com.zhongshu.card.client.model.devices.DeviceInfoSimpleModel;
import com.zhongshu.card.client.model.visitor.*;
import com.zhongshu.card.client.type.visitor.VisitorState;
import com.zhongshu.card.client.utils.DateUtils;
import com.zhongshu.card.server.core.dao.org.UserCountDao;
import com.zhongshu.card.server.core.dao.scene.SceneComponentDao;
import com.zhongshu.card.server.core.dao.visitor.VisitorMainDao;
import com.zhongshu.card.server.core.dao.visitor.VisitorSettingDao;
import com.zhongshu.card.server.core.domain.devices.DeviceInfo;
import com.zhongshu.card.server.core.domain.org.OrganizationUser;
import com.zhongshu.card.server.core.domain.org.UserAccount;
import com.zhongshu.card.server.core.domain.scene.SceneComponent;
import com.zhongshu.card.server.core.domain.visitor.VisitorMain;
import com.zhongshu.card.server.core.domain.visitor.VisitorSetting;
import com.zhongshu.card.server.core.service.base.CommonService;
import com.zhongshu.card.server.core.service.devices.DeviceInfoServiceImpl;
import com.zhongshu.card.server.core.service.dictionary.DictionaryService;
import com.zhongshu.card.server.core.service.org.OrganizationUserServiceImpl;
import com.zhongshu.card.server.core.service.permissVerify.Device2UseUsableService;
import com.zhongshu.card.server.core.service.permissVerify.SuperPermissService;
import com.zhongshu.card.server.core.service.projectAbout.OrgUserFaceService;
import com.zhongshu.card.server.core.service.user.UserAccountServiceImpl;
import com.zhongshu.card.server.core.util.CommonUtil;
import com.zhongshu.card.server.core.util.ExcelUtils;
import com.zhongshu.card.server.core.util.TempUserUtil;
import com.zhongshu.card.server.core.util.ValidateUtils;
import com.zhongshu.card.server.core.util.excel.CommonExeclParam;
import com.zhongshu.card.server.core.util.excel.CommonExeclTd;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author TRX
 * @date 2025/2/11
 */
@Slf4j
@Service
public class VisitorMainService extends SuperPermissService {

    @Autowired
    private VisitorMainDao visitorMainDao;

    @Autowired
    private DeviceInfoServiceImpl deviceInfoService;

    @Autowired
    private UserAccountServiceImpl userAccountService;

    @Autowired
    private SceneComponentDao sceneComponentDao;

    @Autowired
    private UserCountDao userCountDao;

    @Autowired
    private OrganizationUserServiceImpl organizationUserService;

    @Autowired
    private UserFaceService userFaceService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private Device2UseUsableService device2UseUsableService;

    @Autowired
    private VisitorSettingDao visitorSettingDao;

    @Autowired
    private OrgUserFaceService orgUserFaceService;

    @Autowired
    private DictionaryService dictionaryService;

    /**
     * 保存访客申请
     *
     * @param param
     * @return
     */
    public ResultContent<VisitorMain> saveInfo(VisitorMainParam param) {
        if (StringUtils.isEmpty(param.getVisitorUserId())) {
            return ResultContent.buildFail("visitorUserId 不能为空");
        }
        if (StringUtils.isEmpty(param.getFaceUrl())) {
            return ResultContent.buildFail("faceUrl 不能为空");
        }
        Long startTime = param.getStartTime();
        if (CommonUtil.longIsEmpty(startTime)) {
            return ResultContent.buildFail("到访时间不能为空");
        }
        Long minutes = param.getMinutes();
        if (CommonUtil.longIsEmpty(minutes)) {
            return ResultContent.buildFail("访问时长不能为空");
        }
        if (StringUtils.isNotEmpty(param.getPhone()) && !ValidateUtils.isPhoneNumber(param.getPhone())) {
            return ResultContent.buildFail("手机号码格式错误");
        }
        if (StringUtils.isNotEmpty(param.getCardNumber()) && !ValidateUtils.isIDCard(param.getCardNumber())) {
            return ResultContent.buildFail("身份证号码格式错误");
        }

        Long endTime = startTime + minutes * 60 * 1000l;
        if (param.getApplyType() == null) {
            return ResultContent.buildFail("applyType 不能为空");
        }
        if (endTime <= System.currentTimeMillis()) {
            return ResultContent.buildFail("访问结束时间不能小于当前时间");
        }
        String openid = param.getOpenId();
        if (StringUtils.isEmpty(openid)) {
            openid = getOpenId();
        }
        if (StringUtils.isEmpty(openid)) {
            return ResultContent.buildFail("openid不能为空");
        }
        param.setOpenId(openid);

        if (StringUtils.isEmpty(param.getSceneComponentId())) {
            return ResultContent.buildFail("sceneComponentId 不能为空");
        }
        // 所属组件信息
        String sceneComponentId = param.getSceneComponentId();
        SceneComponent sceneComponent = sceneComponentDao.findTopById(sceneComponentId);
        if (ObjectUtils.isEmpty(sceneComponent)) {
            return ResultContent.buildFail("组件不存在");
        }
        String projectOid = sceneComponent.getProjectOid();
        if (StringUtils.isEmpty(projectOid)) {
            projectOid = getCurrentProjectOid();
        }
        if (StringUtils.isEmpty(projectOid)) {
            projectOid = param.getProjectOid();
        }

        if (StringUtils.isEmpty(projectOid)) {
            return ResultContent.buildFail("projectOid 信息为空");
        }
        // 访客组件配置
        VisitorSetting visitorSetting = visitorSettingDao.findTopBySceneComponentIdAndProjectOid(sceneComponentId, projectOid);
        if (ObjectUtils.isEmpty(visitorSetting)) {
            return ResultContent.buildFail("访客组件参数未配置");
        }

        // 验证图片是否包含人脸（符合项目配置要求）
        ResultContent conformFaceContent = orgUserFaceService.conformFace(param.getFaceUrl(), projectOid);
        if (conformFaceContent.isFailed()) {
            return ResultContent.buildFail(conformFaceContent.getMsg());
        }

        // 判断访客是否存在
        UserAccount visitorUserAccount = userCountDao.findTopByUserId(param.getVisitorUserId());
        if (ObjectUtils.isEmpty(visitorUserAccount)) {
            return ResultContent.buildFail("被访人不存在");
        }
        OrganizationUser organizationUser = organizationUserService.getUserTopInProjectBindOrgUserInfo(projectOid, visitorUserAccount);

        VisitorMain entity = null;
        if (StringUtils.isNotEmpty(param.getId())) {
            entity = visitorMainDao.findTopById(param.getId());
            if (entity == null) {
                return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
            }
            initUpdateEntity(entity);
        } else {
            entity = new VisitorMain();
            initEntityNoCheckOid(entity);
            entity.setState(VisitorState.WaitReView);
            entity.setFinalState(VisitorState.WaitReView);
            entity.setIsReViewed(Boolean.FALSE);
        }
        BeanUtils.copyProperties(param, entity);

        entity.setVisitorUserAccount(visitorUserAccount);
        entity.setVisitorUserId(visitorUserAccount.getUserId());
        entity.setVisitorUserName(visitorUserAccount.getName());
        entity.setVisitorUserPhone(visitorUserAccount.getPhone());
        entity.setOrganizationUser(organizationUser);
        entity.setStartTime(startTime);
        entity.setEndTime(endTime);

        // 申请用户
        String applyUserId = getCurrentUserId();
        UserAccount applyUserAccount = null;
        if (StringUtils.isNotEmpty(applyUserId)) {
            applyUserAccount = userCountDao.findTopByUserId(applyUserId);
            OrganizationUser organizationUser1 = organizationUserService.getUserInProjectBindOrgUserInfo(projectOid, applyUserAccount);
            entity.setApplyOrganizationUser(organizationUser1);
        }
        entity.setApplyUserId(applyUserId);
        entity.setApplyUserAccount(applyUserAccount);
        entity.setProjectOid(projectOid);
        entity.setOid(projectOid);
        // 单位是小时
        Long preMinutes = visitorSetting.getMinutes();
        if (preMinutes == null) {
            preMinutes = 0L;
        }
        Long perStartTime = startTime - preMinutes * 60 * 60 * 1000l;
        Long perEndTime = DateUtils.getDayEndTime(endTime);
        entity.setPerStartTime(perStartTime);
        entity.setPerEndTime(perEndTime);

        // 如果访客申请，当前用户的userId为空，则标识他是 访客访问
        String tempUserId = applyUserId;
        UserFromType userFromType = UserFromType.SystemUser;
        if (StringUtils.isEmpty(tempUserId)) {
            if (StringUtils.isNotEmpty(param.getTempUserId())) {
                tempUserId = param.getTempUserId();
            } else {
                tempUserId = TempUserUtil.getVisitorTempUserId();
            }
            userFromType = UserFromType.VisitorUser;
        }
        // 访客 userId
        entity.setTempUserId(tempUserId);
        entity.setUserFromType(userFromType);
        visitorMainDao.save(entity);
        return ResultContent.buildSuccess(entity);
    }

    public ResultContent getInfo(String id) {
        VisitorMain entity = visitorMainDao.findTopById(id);
        if (entity == null) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        checkReViewInfo(entity);
        return ResultContent.buildSuccess(toModel(entity));
    }

    /**
     * 删除数据
     *
     * @param id
     * @return
     */
    public ResultContent deleteInfo(String id) {
        VisitorMain entity = visitorMainDao.findTopById(id);
        if (entity == null) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        visitorMainDao.delete(entity);
        return ResultContent.buildSuccess();
    }

    /**
     * 分页列表
     *
     * @param param
     * @param pageable
     * @return
     */
    public ResultContent<Page<VisitorMainModel>> page(VisitorMainSearch param, Pageable pageable) {
        if (param.getState() != null) {
            if (param.getState() == VisitorState.Leave) {
                param.setState(null);
                param.setIsLeave(Boolean.TRUE);
                param.setIsOverTimeLeave(null);
            } else if (param.getState() == VisitorState.LeaveOutTime) {
                param.setState(null);
                param.setIsLeave(null);
                param.setIsOverTimeLeave(Boolean.TRUE);
            }
        }
        Page<VisitorMain> page = visitorMainDao.page(pageable, param);
        if (param.getIsDesen() != null && param.getIsDesen()) {
            return ResultContent.buildSuccess(PageEntityUtil.concurrent2PageModel(page, this::toDesenModel));
        }
        return ResultContent.buildSuccess(PageEntityUtil.concurrent2PageModel(page, this::toModel));
    }

    /**
     * 拒绝
     *
     * @param param
     * @return
     */
    public ResultContent refuseVisitApply(VisitorReViewParam param) {
        VisitorMain visitorMain = visitorMainDao.findTopById(param.getId());
        if (visitorMain == null) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
        }
        ResultContent resultContent = checkReViewInfo(visitorMain);
        if (resultContent.isFailed()) {
            return resultContent;
        }
        // 已拒绝状态
        visitorMain.setState(VisitorState.Refuse);
        visitorMain.setFinalState(VisitorState.Refuse);
        visitorMain.setReviewRemark(param.getReviewRemark());
        visitorMain.setReViewSuccess(Boolean.FALSE);
        visitorMain.setIsReViewed(Boolean.TRUE);
        visitorMainDao.save(visitorMain);
        return ResultContent.buildSuccess();
    }

    /**
     * 取消申请 （申请审核通过后取消）
     *
     * @param id
     * @return
     */
    public ResultContent cancelVisitApply(String id) {
        VisitorMain visitorMain = visitorMainDao.findTopById(id);
        if (visitorMain == null) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        ResultContent resultContent = checkReViewInfo(visitorMain);
        if (resultContent.isFailed()) {
            return resultContent;
        }
        if (visitorMain.getState() != VisitorState.WaitVisit) {
            return ResultContent.buildFail(String.format("当前状态不能取消:%s", visitorMain.getState().getRemark()));
        }
        visitorMain.setIsCancel(Boolean.TRUE);
        visitorMain.setState(VisitorState.Cancel);
        visitorMain.setFinalState(VisitorState.Cancel);
        visitorMain.setCancelUserId(getCurrentUserId());
        visitorMain.setCancelTime(System.currentTimeMillis());
        visitorMainDao.save(visitorMain);
        return ResultContent.buildSuccess();
    }

    /**
     * 审核通过
     *
     * @param param
     * @return
     */
    public ResultContent passVisitApply(VisitorReViewParam param) {
        VisitorMain visitorMain = visitorMainDao.findTopById(param.getId());
        if (visitorMain == null) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
        }
        ResultContent resultContent = checkReViewInfo(visitorMain);
        if (resultContent.isFailed()) {
            return resultContent;
        }
        // 通过状态
        visitorMain.setState(VisitorState.WaitVisit);
        visitorMain.setFinalState(VisitorState.WaitVisit);
        visitorMain.setReviewRemark(param.getReviewRemark());
        visitorMain.setReViewSuccess(Boolean.TRUE);
        visitorMain.setIsReViewed(Boolean.TRUE);
        if (ObjectUtils.isNotEmpty(param.getDeviceIds())) {
            List<DeviceInfo> deviceInfos = deviceInfoService.getDevicesByDeviceIds(param.getDeviceIds());
            visitorMain.setDeviceInfos(deviceInfos);
        }
        visitorMain.setDeviceIds(param.getDeviceIds());

        String faceBase64 = commonService.getUrlFileBase64(visitorMain.getFaceUrl());
        String updateFaceFileId = "";
        // 维护管理权限中心用户的头像信息
        UserFaceUploadModel userFaceUploadModel = new UserFaceUploadModel();
        userFaceUploadModel.setUserId(visitorMain.getTempUserId());
        userFaceUploadModel.setFile(faceBase64);
        userFaceUploadModel.setUpdateFaceFileId(updateFaceFileId);
        com.github.microservice.auth.client.content.ResultContent<String> content = userFaceService.upload(userFaceUploadModel);
        if (content.isFailed()) {
            return ResultContent.buildFail(content.getMsg());
        }
        updateFaceFileId = content.getContent();
        visitorMain.setFaceFileId(updateFaceFileId);

        // 把用户头像对应的设备权限写入 临时权限表
        device2UseUsableService.addByVisitorData(visitorMain, false);

        visitorMainDao.save(visitorMain);
        return ResultContent.buildSuccess();
    }

    /**
     * 标记访客权限使用
     *
     * @param fromDataId
     */
    @Override
    public ResultContent markUse(String fromDataId, DeviceUseParam deviceUserParam) {
        if (StringUtils.isNotEmpty(fromDataId)) {
            VisitorMain visitorMain = visitorMainDao.findTopById(fromDataId);
            if (ObjectUtils.isEmpty(visitorMain)) {
                return null;
            }
            if (deviceUserParam != null) {
                // 封装使用记录参数
                deviceUserParam.setPermissFromType(DevicePermissFromType.Visitor);
                deviceUserParam.setUserName(visitorMain.getName());
                deviceUserParam.setUserFromType(visitorMain.getUserFromType());
                deviceUserParam.setAboutDataId(visitorMain.getId());
            }

            // 如果是 待来访 状态 则改为 已到访
            if (visitorMain.getState() == VisitorState.WaitVisit) {
                visitorMain.setState(VisitorState.Visit);
                visitorMain.setFinalState(VisitorState.Visit);
                visitorMain.setFirstVisitTime(System.currentTimeMillis());
                // 更新权限使用时间
                device2UseUsableService.addByVisitorData(visitorMain, true);
            }
            visitorMain.setLastVisitTime(System.currentTimeMillis());
            visitorMain.setUseNumber(visitorMain.getUseNumber() + 1);
            if (visitorMain.getUseNumber() >= 2) {
                // 访问次数大于2次，则判断已离开了
                visitorMain.setIsLeave(Boolean.TRUE);
                if (CommonUtil.longIsEmpty(visitorMain.getLeaveTime())) {
                    visitorMain.setLeaveTime(System.currentTimeMillis());
                }
                if (visitorMain.getLeaveTime() >= visitorMain.getEndTime()) {
                    visitorMain.setIsOverTimeLeave(Boolean.TRUE);
                    visitorMain.setFinalState(VisitorState.LeaveOutTime);
                } else {
                    visitorMain.setIsOverTimeLeave(Boolean.FALSE);
                    visitorMain.setFinalState(VisitorState.Leave);
                }
            }
            visitorMainDao.save(visitorMain);
            return ResultContent.buildSuccess(visitorMain);
        }
        return ResultContent.buildFail(ResultMessage.DATA_NOT_EXIST);
    }

    @Override
    public ResultContent detailInfo(String fromDataId) {
        return super.detailInfo(fromDataId);
    }

    /**
     * 统计当前用户访客数据 （被访人员）
     *
     * @return
     */
    public ResultContent staticCurrentUserTotal(VisitorStaticParam param) {
        if (StringUtils.isEmpty(param.getProjectOid())) {
            param.setProjectOid(getCurrentProjectOid());
        }
        if (StringUtils.isEmpty(param.getProjectOid())) {
            return ResultContent.buildFail("projectOid 信息为空");
        }
        VisitorStaticModel model = new VisitorStaticModel();
        String userId = getCurrentUserId();
        VisitorMainSearch search = new VisitorMainSearch();
        search.setProjectOid(param.getProjectOid());
        search.setVisitorUserId(userId);

        // 待审核 待申批
        search.setState(VisitorState.WaitReView);
        Long waitReViewNumber = visitorMainDao.count(search);

        // 待来访
        search.setState(VisitorState.WaitVisit);
        Long waitVisitNumber = visitorMainDao.count(search);

        // 当前访客 （已到访，没离开）
        search.setState(VisitorState.Visit);
        search.setIsLeave(Boolean.FALSE);
        Long visitNumber = visitorMainDao.count(search);

        model.setWaitReViewNumber(waitReViewNumber);
        model.setWaitVisitNumber(waitVisitNumber);
        model.setVisitNumber(visitNumber);
        return ResultContent.buildSuccess(model);
    }

    /**
     * 检查数据 审核是否是否已过期
     *
     * @param visitorMain
     * @return
     */
    public ResultContent checkReViewInfo(VisitorMain visitorMain) {
        if (ObjectUtils.isNotEmpty(visitorMain)) {
            if (visitorMain.getState() == VisitorState.WaitReView && visitorMain.getEndTime() <= System.currentTimeMillis()) {
                // 待审核 结束时间已过期
                visitorMain.setState(VisitorState.Cancel);
                visitorMain.setFinalState(VisitorState.Cancel);
                visitorMain.setReviewRemark("申请数据已失效");
                visitorMainDao.save(visitorMain);
                return ResultContent.buildFail("数据已失效");
            }
        }
        return ResultContent.buildSuccess();
    }

    /**
     * 每天检查数据，，如果访问时间已过期，则清除人脸数据
     */
    public void loopCheckVisitorData() {
        this.checkAllWaitReView();
        this.checkAllOverTimeData();
    }

    /**
     * 检查所有的 审核通过的是否过期（好清理人脸信息）
     */
    private void checkAllOverTimeData() {
        VisitorMainSearch param = new VisitorMainSearch();
        // 审核通过
        param.setReViewSuccess(Boolean.TRUE);
        // 没清除人脸
        param.setIsClearFace(Boolean.FALSE);

        Pageable pageable = PageRequest.of(0, 100);
        Page<VisitorMain> page = visitorMainDao.page(pageable, param);
        List<VisitorMain> list = page.getContent();
        log.info("checkAllOverTimeData size: " + list.size());
        if (ObjectUtils.isNotEmpty(list)) {
            list.forEach(visitorMain -> {
                checkExpireInfo(visitorMain);
            });
        }
    }

    /**
     * 检查数据是否过期
     *
     * @param visitorMain
     * @return
     */
    public ResultContent checkExpireInfo(VisitorMain visitorMain) {
        if (ObjectUtils.isNotEmpty(visitorMain)) {
            // 已审核  已过期
            if (visitorMain.getReViewSuccess() != null && visitorMain.getReViewSuccess() && visitorMain.getPerEndTime() < System.currentTimeMillis()) {
                // 取消人脸
                com.github.microservice.auth.client.content.ResultContent resultContent = userFaceService.delete(visitorMain.getTempUserId(), visitorMain.getFaceFileId());
                if (resultContent.isSuccess()) {
                    visitorMain.setIsOverTime(Boolean.TRUE);
                    visitorMain.setIsClearFace(Boolean.TRUE);
                    // 如果未使用，，则把状态改为 已失效
                    if (visitorMain.getState() == VisitorState.WaitVisit) {
                        visitorMain.setState(VisitorState.Cancel);
                        visitorMain.setFinalState(VisitorState.Cancel);
                    }
                    visitorMainDao.save(visitorMain);
                    return ResultContent.buildSuccess();
                } else {
                    return ResultContent.buildFail(resultContent.getMsg());
                }
            }
        }
        return ResultContent.buildFail("数据为空");
    }

    /**
     * 检查所有的待审核得数据是否过期
     */
    private void checkAllWaitReView() {
        // 待审核
        List<VisitorMain> list = visitorMainDao.findByState(VisitorState.WaitReView);
        if (ObjectUtils.isNotEmpty(list)) {
            list.stream().forEach(visitorMain -> {
                checkReViewInfo(visitorMain);
            });
        }
    }

    public void exportData(HttpServletRequest request, HttpServletResponse response, VisitorMainSearch param) throws IOException {
        Assert.hasText(param.getProjectOid(), "projectOid不能为空");
        Pageable pageable = PageRequest.of(0, Integer.MAX_VALUE);
        Page<VisitorMain> page = visitorMainDao.page(pageable, param);
        List<VisitorMain> list = page.getContent();
        List<Map<String, Object>> maps = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(list)) {
            maps = list.parallelStream().map(it -> {
                Map<String, Object> map = BeanUtil.bean2Map(it);
                String visitorTypeName = dictionaryService.queryItemName(it.getProjectOid(), "visitorType", it.getVisitorType());
                map.put("visitorTypeName", visitorTypeName);
                String finalStateStr = "";
                if (it.getFinalState() != null) {
                    finalStateStr = it.getFinalState().getRemark();
                }
                map.put("finalStateStr", finalStateStr);

                String firstVisitTimeStr = "";
                if (!CommonUtil.longIsEmpty(it.getFirstVisitTime())) {
                    firstVisitTimeStr = DateUtils.paresTime(it.getFirstVisitTime(), DateUtils.FORMAT_LONG);
                }
                map.put("firstVisitTimeStr", firstVisitTimeStr);

                String startTimeStr = "";
                if (!CommonUtil.longIsEmpty(it.getStartTime())) {
                    startTimeStr = DateUtils.paresTime(it.getStartTime(), DateUtils.FORMAT_LONG);
                }
                map.put("startTimeStr", startTimeStr);

                String endTimeStr = "";
                if (!CommonUtil.longIsEmpty(it.getEndTime())) {
                    endTimeStr = DateUtils.paresTime(it.getEndTime(), DateUtils.FORMAT_LONG);
                }
                map.put("endTimeStr", endTimeStr);

                UserAccount visitorUserAccount = it.getVisitorUserAccount();
                String visitorUserName = "";
                String visitorUserPhone = "";
                if (ObjectUtils.isNotEmpty(visitorUserAccount)) {
                    visitorUserName = visitorUserAccount.getName();
                    visitorUserPhone = visitorUserAccount.getPhone();
                }
                map.put("visitorUserName", visitorUserName);
                map.put("visitorUserPhone", visitorUserPhone);

                // 申请方式
                String applyTypeStr = "";
                if (it.getApplyType() != null) {
                    applyTypeStr = it.getApplyType().getRemark();
                }
                map.put("applyTypeStr", applyTypeStr);
                return map;
            }).collect(Collectors.toUnmodifiableList());
        }

        CommonExeclParam execlParam = new CommonExeclParam();
        execlParam.setTitle(String.format("访客列表"));
        execlParam.setStartRow(2);
        execlParam.setDatas(maps);

        List<CommonExeclTd> tds = new ArrayList<>();
        tds.add(CommonExeclTd.build("访客姓名", "name"));
        tds.add(CommonExeclTd.build("访客手机", "phone"));
        tds.add(CommonExeclTd.build("访客类型", "visitorTypeName"));
        tds.add(CommonExeclTd.build("审核状态", "finalStateStr"));
        tds.add(CommonExeclTd.build("实际到访时间", "firstVisitTime"));

        tds.add(CommonExeclTd.build("身份证号码", "cardNumber"));
        tds.add(CommonExeclTd.build("预约时间", "startTimeStr"));
        tds.add(CommonExeclTd.build("结束时间", "endTimeStr"));

        tds.add(CommonExeclTd.build("被访人", "visitorUserName"));
        tds.add(CommonExeclTd.build("被访人手机号", "visitorUserPhone"));
        tds.add(CommonExeclTd.build("预约类型", "applyTypeStr"));
        tds.add(CommonExeclTd.build("车牌号", "carNo"));

        execlParam.setTds(tds);
        ExcelUtils.commonExecuteExcel(request, response, execlParam);
    }

    public VisitorMainModel toDesenModel(VisitorMain entity) {
        VisitorMainModel model = null;
        if (ObjectUtils.isNotEmpty(entity)) {
            model = new VisitorMainModel();
            BeanUtils.copyProperties(entity, model);

            // 用户信息/被访人
            model.setVisitorUserAccount(userAccountService.toSimpleDesenModel(entity.getVisitorUserAccount()));
            // 申请用户
            model.setApplyUserAccount(userAccountService.toSimpleModel(entity.getApplyUserAccount()));

            // 设备信息
            List<DeviceInfoSimpleModel> deviceInfos = new ArrayList<>();
            if (ObjectUtils.isNotEmpty(entity.getDeviceInfos())) {
                deviceInfos = entity.getDeviceInfos().stream().map(deviceInfoService::toSimpleModel).collect(Collectors.toList());
            }
            model.setDeviceInfos(deviceInfos);
        }
        return model;
    }

    public VisitorMainModel toModel(VisitorMain entity) {
        VisitorMainModel model = null;
        if (ObjectUtils.isNotEmpty(entity)) {
            model = new VisitorMainModel();
            BeanUtils.copyProperties(entity, model);

            // 用户信息/被访人
            model.setVisitorUserAccount(userAccountService.toSimpleModel(entity.getVisitorUserAccount()));
            // 申请用户
            model.setApplyUserAccount(userAccountService.toSimpleModel(entity.getApplyUserAccount()));

            // 设备信息
            List<DeviceInfoSimpleModel> deviceInfos = new ArrayList<>();
            if (ObjectUtils.isNotEmpty(entity.getDeviceInfos())) {
                deviceInfos = entity.getDeviceInfos().stream().map(deviceInfoService::toSimpleModel).collect(Collectors.toList());
            }
            model.setDeviceInfos(deviceInfos);
        }
        return model;
    }

}
