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

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.github.microservice.auth.client.content.ResultState;
import com.github.microservice.auth.client.service.UserService;
import com.github.microservice.components.data.base.util.PageEntityUtil;
import com.github.microservice.core.util.bean.BeanUtil;
import com.github.microservice.net.ResultContent;
import com.github.microservice.net.ResultMessage;
import com.google.common.collect.Lists;
import com.zhongshu.card.client.model.base.OidModel;
import com.zhongshu.card.client.model.org.OidAboutInfo;
import com.zhongshu.card.client.model.org.OrganizationUserModel;
import com.zhongshu.card.client.model.school.*;
import com.zhongshu.card.client.service.school.CardInfoService;
import com.zhongshu.card.client.type.CardCancelState;
import com.zhongshu.card.client.type.CardOperationType;
import com.zhongshu.card.client.type.school.CardState;
import com.zhongshu.card.client.utils.DateUtils;
import com.zhongshu.card.server.core.dao.org.OrganizationDao;
import com.zhongshu.card.server.core.dao.org.OrganizationUserDao;
import com.zhongshu.card.server.core.dao.org.UserCountDao;
import com.zhongshu.card.server.core.dao.school.CardInfoDao;
import com.zhongshu.card.server.core.dao.school.CardInfoPoolDao;
import com.zhongshu.card.server.core.dao.user.CardInfoLossRecordDao;
import com.zhongshu.card.server.core.domain.org.Organization;
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.school.CardInfo;
import com.zhongshu.card.server.core.domain.school.CardInfoLossRecord;
import com.zhongshu.card.server.core.domain.school.CardInfoPool;
import com.zhongshu.card.server.core.service.base.SuperService;
import com.zhongshu.card.server.core.service.devices.permiss.DevicePermissEventService;
import com.zhongshu.card.server.core.service.org.OrganizationServiceImpl;
import com.zhongshu.card.server.core.service.org.OrganizationUserServiceImpl;
import com.zhongshu.card.server.core.service.orgManager.OrganizationManagerServiceImpl;
import com.zhongshu.card.server.core.service.user.UserAccountServiceImpl;
import com.zhongshu.card.server.core.util.BeanUtils;
import com.zhongshu.card.server.core.util.CommonUtil;
import com.zhongshu.card.server.core.util.ExcelUtils;
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.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
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.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 卡片管理Service
 *
 * @author TRX
 * @date 2024/6/13
 */
@Slf4j
@Service
public class CardInfoServiceImpl extends SuperService implements CardInfoService {

    @Autowired
    private CardInfoDao cardInfoDao;

    @Autowired
    private OrganizationDao organizationDao;

    @Autowired
    private UserCountDao userCountDao;

    @Autowired
    private UserService userService;

    @Autowired
    private CardInfoLossRecordDao cardInfoLossRecordDao;

    @Autowired
    private CardInfoPoolDao cardInfoPoolDao;

    @Autowired
    private OrganizationServiceImpl organizationService;

    @Autowired
    private UserAccountServiceImpl userAccountService;

    @Autowired
    private OrganizationManagerServiceImpl organizationManagerService;

    @Autowired
    private OrganizationUserDao organizationUserDao;

    @Autowired
    private OrganizationUserServiceImpl organizationUserService;

    @Autowired
    CardInfoPoolService cardInfoPoolService;

    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    private DevicePermissEventService devicePermissEventService;

    /**
     * 添加或修改卡片信息
     *
     * @param param
     * @return
     */
    @Override
    public ResultContent addCardInfo(CardInfoParam param) {
//        checkParamOid(param);
        initDefaultUserParam(param);
        if (StringUtils.isEmpty(param.getCode())) {
            return ResultContent.buildFail("code不能为空");
        }
        String oid = param.getOid();

        String code = param.getCode();
        code = code.trim();
        param.setCode(code);
        CardInfo cardInfo = new CardInfo();

        CardInfo temp = cardInfoDao.findByCode(code);
        if (StringUtils.isNotEmpty(param.getId())) {
            cardInfo = cardInfoDao.findTopById(param.getId());
            if (ObjectUtils.isEmpty(cardInfo)) {
                return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
            }
            if (ObjectUtils.isNotEmpty(temp) && !ObjectUtils.equals(temp.getId(), cardInfo.getId())) {
                return ResultContent.buildFail(String.format("卡号已存在：%s", code));
            }
        } else {
            if (ObjectUtils.isNotEmpty(temp)) {
                return ResultContent.buildFail(String.format("卡号已存在：%s", code));
            }
        }
        BeanUtils.copyProperties(param, cardInfo, "cardState", "isCanceled");

        if (cardInfo.getCardState() == null) {
            cardInfo.setCardState(CardState.Enable);
        }
        if (StringUtils.isNotEmpty(oid)) {
            Organization organization = organizationDao.findTopByOid(oid);
            cardInfo.setOrganization(organization);
        }
        OidAboutInfo oidAboutInfo = organizationManagerService.getOidAboutInfo(oid);
        UserAccount account = userCountDao.findTopByUserId(param.getUserId());
        cardInfo.setUserAccount(account);
        cardInfo.setUserId(account.getUserId());
        cardInfo.setUserName(account.getName());
        cardInfo.setPhone(account.getPhone());

        cardInfo.setProjectOid(oidAboutInfo.getProjectOid());
        cardInfo.setAboutOid(oidAboutInfo.getOid());
        cardInfo.setAboutAuthType(oidAboutInfo.getAuthType());
        cardInfoDao.save(cardInfo);

        return ResultContent.buildSuccess();
    }

    /**
     * 从卡池选择卡片绑定到个人
     *
     * @param poolId
     * @return
     */
    public ResultContent bindCardFromPool(String poolId, String userId) {
        if (StringUtils.isEmpty(userId)) {
            return ResultContent.buildFail("userId不能为空");
        }
        if (StringUtils.isEmpty(poolId)) {
            return ResultContent.buildFail("poolId不能为空");
        }
        // 卡池数据
        CardInfoPool cardInfoPool = cardInfoPoolDao.findTopById(poolId);
        if (ObjectUtils.isEmpty(cardInfoPool)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, poolId));
        }
        List<OrganizationUser> list = organizationUserService.getUserOrgList(cardInfoPool.getProjectOid(), userId);
        if (ObjectUtils.isEmpty(list)) {
            return ResultContent.buildFail("用户未加入结构，不能绑定卡片");
        }
        return bindCardFromPoolByOrgId(poolId, list.get(0).getId(), "");
    }

    /**
     * @param poolId 卡池数据的id
     * @param id     OrganizationUser id
     * @return
     */
    @Transactional
    @Override
    public ResultContent bindCardFromPoolByOrgId(String poolId, String id, String remark) {
        if (StringUtils.isEmpty(id)) {
            return ResultContent.buildFail("id不能为空");
        }
        if (StringUtils.isEmpty(poolId)) {
            return ResultContent.buildFail("poolId不能为空");
        }
        // 卡池数据
        CardInfoPool cardInfoPool = cardInfoPoolDao.findTopById(poolId);
        if (ObjectUtils.isEmpty(cardInfoPool)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, poolId));
        }
        if (cardInfoPool.getIsUsed() != null && cardInfoPool.getIsUsed()) {
            return ResultContent.buildFail(String.format("卡片已使用：%s", cardInfoPool.getCode()));
        }
        if (cardInfoPool.getCardCancelState() != null && cardInfoPool.getCardCancelState() != CardCancelState.Common) {
            return ResultContent.buildFail(String.format("卡片：%s", cardInfoPool.getCardCancelState().getRemark()));
        }

        OrganizationUser organizationUser = organizationUserDao.findTopById(id);
        if (ObjectUtils.isEmpty(organizationUser)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }

        if (!cardInfoPool.getProjectOid().equals(organizationUser.getProjectOid())) {
            return ResultContent.buildFail(String.format("卡片和用户不在同一个项目下，不能绑定"));
        }

        // 用户信息
        UserAccount account = organizationUser.getUser();
        if (ObjectUtils.isEmpty(account)) {
            return ResultContent.buildFail("机构用户信息为空");
        }

        String userId = account.getUserId();
        String code = cardInfoPool.getCode();
        CardInfo cardInfo = cardInfoDao.findByCode(code);
        if (ObjectUtils.isNotEmpty(cardInfo)) {
            return ResultContent.buildFail(String.format("卡号已存在：%s", code));
        }
        cardInfo = new CardInfo();
        initEntity(cardInfo);

        cardInfo.setName(cardInfoPool.getName());
        cardInfo.setCode(cardInfoPool.getCode());
        cardInfo.setCardType(cardInfoPool.getCardType());

        cardInfo.setProjectOid(cardInfoPool.getProjectOid());
        cardInfo.setSchoolOid(cardInfoPool.getSchoolOid());
        cardInfo.setAboutAuthType(cardInfoPool.getAboutAuthType());
        cardInfo.setAboutOid(cardInfoPool.getAboutOid());
        cardInfo.setOid(cardInfoPool.getOid());
        cardInfo.setOrganization(organizationUser.getOrganization());
        cardInfo.setOrganizationUser(organizationUser);

        cardInfo.setCardState(CardState.Enable);
        cardInfo.setUserAccount(account);
        cardInfo.setUserId(userId);
        cardInfo.setUserName(account.getName());
        cardInfo.setPhone(account.getPhone());
        cardInfo.setRemark(remark);
        cardInfoDao.save(cardInfo);

        // 标记卡池这张卡已使用
        cardInfoPool.setIsUsed(Boolean.TRUE);
        cardInfoPool.setUseUserId(userId);
        cardInfoPool.setUseTime(System.currentTimeMillis());
        cardInfoPoolDao.save(cardInfoPool);

        // 用户卡片增多
        devicePermissEventService.sendUserInfoChangeEvent(cardInfo.getUserId(), cardInfo.getProjectOid(), "bindCardFromPoolByOrgId");
        return ResultContent.buildSuccess();
    }

    @Transactional
    @Override
    public ResultContent bindByCode(String code) {
        if (StringUtils.isEmpty(code)) {
            return ResultContent.buildFail("code不能为空");
        }
        code = code.trim().toUpperCase();
        log.info("code: {}", code);
        // 卡池数据
        CardInfoPool cardInfoPool = cardInfoPoolDao.findTopByCode(code);
        if (ObjectUtils.isEmpty(cardInfoPool)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, code));
        }
        if (cardInfoPool.getIsUsed() != null && cardInfoPool.getIsUsed()) {
            return ResultContent.buildFail(String.format("卡片已使用：%s", cardInfoPool.getCode()));
        }
        if (cardInfoPool.getCardCancelState() != null && cardInfoPool.getCardCancelState() != CardCancelState.Common) {
            return ResultContent.buildFail(String.format("卡片：%s", cardInfoPool.getCardCancelState().getRemark()));
        }
        String userId = getCurrentUserId();
        String projectOid = getCurrentProjectOid();

        List<OrganizationUser> organizationUsers = organizationUserService.getUserOrgList(userId, projectOid);
        if (ObjectUtils.isEmpty(organizationUsers)) {
            return ResultContent.buildFail("用户未加入机构");
        }
        OrganizationUser organizationUser = organizationUsers.get(0);

        // 用户信息
        UserAccount account = userCountDao.findTopByUserId(userId);
        if (ObjectUtils.isEmpty(account)) {
            return ResultContent.buildFail("机构用户信息为空");
        }
        CardInfo cardInfo = cardInfoDao.findByCode(code);
        if (ObjectUtils.isNotEmpty(cardInfo)) {
            return ResultContent.buildFail(String.format("卡号已存在：%s", code));
        }
        cardInfo = new CardInfo();
        initEntityNoCheckOid(cardInfo);

        cardInfo.setName(cardInfoPool.getName());
        cardInfo.setCode(cardInfoPool.getCode());
        cardInfo.setCardType(cardInfoPool.getCardType());

        cardInfo.setProjectOid(cardInfoPool.getProjectOid());
        cardInfo.setSchoolOid(cardInfoPool.getSchoolOid());
        cardInfo.setAboutAuthType(cardInfoPool.getAboutAuthType());
        cardInfo.setAboutOid(cardInfoPool.getAboutOid());
        cardInfo.setOid(cardInfoPool.getOid());
        cardInfo.setOrganization(organizationUser.getOrganization());
        cardInfo.setOrganizationUser(organizationUser);

        cardInfo.setCardState(CardState.Enable);
        cardInfo.setUserAccount(account);
        cardInfo.setUserId(userId);
        cardInfo.setUserName(account.getName());
        cardInfo.setPhone(account.getPhone());
        cardInfo.setRemark("用户搜索绑定");
        cardInfoDao.save(cardInfo);

        // 标记卡池这张卡已使用
        cardInfoPool.setIsUsed(Boolean.TRUE);
        cardInfoPool.setUseUserId(userId);
        cardInfoPool.setUseTime(System.currentTimeMillis());
        cardInfoPoolDao.save(cardInfoPool);

        // 用户卡片增多
        devicePermissEventService.sendUserInfoChangeEvent(cardInfo.getUserId(), cardInfo.getProjectOid(), "bindByCode");
        return ResultContent.buildSuccess();
    }

    /**
     * 解绑卡片
     *
     * @param id
     * @return
     */
    @Transactional
    public ResultContent unBindCard(String id) {
        CardInfo cardInfo = cardInfoDao.findTopById(id);
        if (ObjectUtils.isEmpty(cardInfo)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        // 删除用户的卡片
        cardInfoDao.delete(cardInfo);

        // 恢复卡池的数据
        CardInfoPool cardInfoPool = cardInfoPoolDao.findTopByCode(cardInfo.getCode());
        if (ObjectUtils.isNotEmpty(cardInfoPool)) {
            cardInfoPool.setIsUsed(Boolean.FALSE);
            cardInfoPool.setUseUserId(null);
            cardInfoPool.setUseTime(null);
            cardInfoPoolDao.save(cardInfoPool);
        }

        // 用户可用卡片减少
        devicePermissEventService.sendUserInfoChangeEvent(cardInfo.getUserId(), cardInfo.getProjectOid(), "unBindCard");
        return ResultContent.buildSuccess();
    }

    /**
     * 得到当前用户所在 学校的所有卡片
     *
     * @return
     */
    @Override
    public ResultContent<List<CardInfoModel>> getCurrentUserOrgAll(String oid) {
        String userId = getCurrentUserId();
        return ResultContent.buildSuccess(getUserOrgAllCard(userId, oid));
    }

    /**
     * 查询结构用户的卡片信息
     *
     * @param id
     * @return
     */
    public ResultContent<List<CardInfoModel>> getOrgCardList(String id) {
        List<CardInfoModel> models = new ArrayList<>();
        OrganizationUser organizationUser = organizationUserDao.findTopById(id);
        if (ObjectUtils.isEmpty(organizationUser)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        List<CardInfo> list = cardInfoDao.findByUserIdAndProjectOid(organizationUser.getUserId(), organizationUser.getProjectOid());
        if (ObjectUtils.isNotEmpty(list)) {
            models = list.stream().map(this::toModel).collect(Collectors.toList());
        }
        return ResultContent.buildSuccess(models);
    }

    @Override
    public List<CardInfoModel> getUserOrgAllCard(String userId, String oid) {
        List<CardInfoModel> models = new ArrayList<>();
        List<CardInfo> list = new ArrayList<>();
        if (StringUtils.isNotEmpty(oid)) {
            list = cardInfoDao.findByUserIdAndOid(userId, oid);
        } else {
            list = cardInfoDao.findByUserId(userId);
        }
        if (ObjectUtils.isNotEmpty(list)) {
            models = list.parallelStream().map(this::toModel).collect(Collectors.toList());
        }
        return models;
    }

    /**
     * 删除卡片
     *
     * @param id
     * @return
     */
    public ResultContent deleteCardInfo(String id) {
        Assert.hasText(id, "id不能为空");
        CardInfo cardInfo = cardInfoDao.findTopById(id);
        if (ObjectUtils.isEmpty(cardInfo)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        cardInfoDao.delete(cardInfo);

        // 查看卡池是否有这张卡
        CardInfoPool cardInfoPool = cardInfoPoolDao.findTopByCode(cardInfo.getCode());
        if (ObjectUtils.isNotEmpty(cardInfoPool)) {
            // 把状态设置为未使用
            cardInfoPool.setIsUsed(Boolean.FALSE);
            cardInfoPoolDao.save(cardInfoPool);
        }

        return ResultContent.buildSuccess();
    }

    /**
     * 通过卡片ID挂失 (当前用户挂失自己的卡片)
     *
     * @param param
     * @return
     */
    @Transactional
    @Override
    public ResultContent cardLossById(CardLossParam param) {
        Assert.hasText(param.getPassWord(), "密码不能为空");
        Assert.hasText(param.getId(), "id不能为空");
        String userId = getCurrentUserId();
        com.github.microservice.auth.client.content.ResultContent<Void> resultContent = userService.checkLoginPassword(userId, param.getPassWord());
        if (resultContent.getState() != ResultState.Success) {
            return ResultContent.buildFail("密码错误");
        }
        UserAccount userAccount = userCountDao.findTopByUserId(userId);
        CardInfo cardInfo = cardInfoDao.findTopById(param.getId());
        if (ObjectUtils.isEmpty(cardInfo)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
        }
        cardInfo.setCardState(CardState.Loss);
        cardInfoDao.save(cardInfo);

        CardInfoLossRecord cardInfoLossRecord = new CardInfoLossRecord();
        cardInfoLossRecord.setCardInfo(cardInfo);
        cardInfoLossRecord.setOperUserAccount(userAccount);
        cardInfoLossRecord.setOperUserId(userId);
        cardInfoLossRecord.setCardUserId(userId);
        cardInfoLossRecord.setCardUserAccount(userAccount);
        cardInfoLossRecord.setOperationType(CardOperationType.Loss);
        cardInfoLossRecordDao.save(cardInfoLossRecord);

        return ResultContent.buildSuccess();
    }

    /**
     * 通过卡片的iccid挂失 （帮别人挂失）
     *
     * @param param
     * @return
     */
    @Override
    public ResultContent cardLossByIccId(CardLossParam param) {
        Assert.hasText(param.getCode(), "code不能为空");
        String userId = getCurrentUserId();
        UserAccount userAccount = userCountDao.findTopByUserId(userId);

        boolean isVerify = false;
        // 是否验证密码
        if (param.getVerifyPassword() != null && param.getVerifyPassword()) {
            isVerify = true;
        }

        if (isVerify) {
            Assert.hasText(param.getPhone(), "phone不能为空");
            Assert.hasText(param.getPassWord(), "密码不能为空");
            com.github.microservice.auth.client.content.ResultContent<Void> resultContent = userService.checkLoginPassword(userId, param.getPassWord());
            if (resultContent.getState() != ResultState.Success) {
                return ResultContent.buildFail("密码错误");
            }
        }

        CardInfo cardInfo = cardInfoDao.findByCode(param.getCode());
        if (ObjectUtils.isEmpty(cardInfo)) {
            return ResultContent.buildFail(String.format("卡片不存在：%s", param.getCode()));
        }
        // 判断卡片人的信息
        String cardUserId = cardInfo.getUserId();
        UserAccount cardUserAccount = userCountDao.findTopByUserId(cardUserId);
        if (isVerify) {
            if (!cardUserAccount.getPhone().equals(param.getPhone())) {
                return ResultContent.buildFail("持卡人信息和卡号不一致");
            }
        }

        if (cardInfo.getCardState() == CardState.Loss) {
            return ResultContent.buildFail(String.format("卡片已挂失：%s", param.getCode()));
        }

        cardInfo.setCardState(CardState.Loss);
        cardInfoDao.save(cardInfo);

        CardInfoLossRecord cardInfoLossRecord = new CardInfoLossRecord();
        cardInfoLossRecord.setCardInfo(cardInfo);
        cardInfoLossRecord.setOperUserAccount(userAccount);
        cardInfoLossRecord.setOperUserId(userId);

        cardInfoLossRecord.setCardUserId(cardUserAccount.getUserId());
        cardInfoLossRecord.setCardUserAccount(cardUserAccount);
        cardInfoLossRecord.setOperationType(CardOperationType.Loss);
        cardInfoLossRecordDao.save(cardInfoLossRecord);

        String groupId = CommonUtil.UUID();
        Map<String, Object> map = new HashMap<>();
        map.put("groupId", groupId);
        // 卡片信息发送变化
        devicePermissEventService.sendUserInfoChangeEvent(cardInfo.getUserId(), cardInfo.getProjectOid(), map);
        return ResultContent.buildSuccess();
    }

    /**
     * 卡片启用
     *
     * @param param
     * @return
     */
    @Override
    public ResultContent cardEnableById(CardLossParam param) {
        Assert.hasText(param.getPassWord(), "密码不能为空");
        Assert.hasText(param.getId(), "id不能为空");
        String userId = getCurrentUserId();
        UserAccount userAccount = userCountDao.findTopByUserId(userId);
        com.github.microservice.auth.client.content.ResultContent<Void> resultContent = userService.checkLoginPassword(userId, param.getPassWord());
        if (resultContent.getState() != ResultState.Success) {
            return ResultContent.buildFail("密码错误");
        }
        CardInfo cardInfo = cardInfoDao.findTopById(param.getId());
        if (ObjectUtils.isEmpty(cardInfo)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
        }
        cardInfo.setCardState(CardState.Enable);
        cardInfoDao.save(cardInfo);

        CardInfoLossRecord cardInfoLossRecord = new CardInfoLossRecord();
        cardInfoLossRecord.setCardInfo(cardInfo);
        cardInfoLossRecord.setOperUserAccount(userAccount);
        cardInfoLossRecord.setOperUserId(userId);
        cardInfoLossRecord.setCardUserId(userId);
        cardInfoLossRecord.setCardUserAccount(userAccount);
        cardInfoLossRecord.setOperationType(CardOperationType.Enable);
        cardInfoLossRecordDao.save(cardInfoLossRecord);
        // 卡片信息发送变化
        devicePermissEventService.sendUserInfoChangeEvent(cardInfo.getUserId(), cardInfo.getProjectOid(), "cardEnableById");
        return ResultContent.buildSuccess();
    }

    /**
     * 通过卡片的iccid启用 （帮别人启用）
     *
     * @param param
     * @return
     */
    @Override
    public ResultContent cardEnableByIccId(CardLossParam param) {
        Assert.hasText(param.getCode(), "code不能为空");
        String userId = getCurrentUserId();
        UserAccount userAccount = userCountDao.findTopByUserId(userId);

        boolean isVerify = false;
        if (param.getVerifyPassword() != null && param.getVerifyPassword()) {
            isVerify = true;
        }

        if (isVerify) {
            Assert.hasText(param.getPhone(), "phone不能为空");
            Assert.hasText(param.getPassWord(), "密码不能为空");
            com.github.microservice.auth.client.content.ResultContent<Void> resultContent = userService.checkLoginPassword(userId, param.getPassWord());
            if (resultContent.getState() != ResultState.Success) {
                return ResultContent.buildFail("密码错误");
            }
        }

        CardInfo cardInfo = cardInfoDao.findByCode(param.getCode());
        if (ObjectUtils.isEmpty(cardInfo)) {
            return ResultContent.buildFail(String.format("code不存在：%s", param.getCode()));
        }

        // 判断卡片人的信息
        String cardUserId = cardInfo.getUserId();
        UserAccount cardUserAccount = userCountDao.findTopByUserId(cardUserId);

        if (isVerify) {
            if (!cardUserAccount.getPhone().equals(param.getPhone())) {
                return ResultContent.buildFail("持卡人信息和卡号不一致");
            }
        }

        if (cardInfo.getCardState() == CardState.Enable) {
            return ResultContent.buildFail(String.format("卡片已接挂：%s", param.getCode()));
        }

        cardInfo.setCardState(CardState.Enable);
        cardInfoDao.save(cardInfo);

        CardInfoLossRecord cardInfoLossRecord = new CardInfoLossRecord();
        cardInfoLossRecord.setCardInfo(cardInfo);
        cardInfoLossRecord.setOperUserAccount(userAccount);
        cardInfoLossRecord.setOperUserId(userId);

        cardInfoLossRecord.setCardUserId(cardUserAccount.getCreateUserId());
        cardInfoLossRecord.setCardUserAccount(cardUserAccount);
        cardInfoLossRecord.setOperationType(CardOperationType.Enable);
        cardInfoLossRecordDao.save(cardInfoLossRecord);

        String groupId = CommonUtil.UUID();
        Map<String, Object> map = new HashMap<>();
        map.put("groupId", groupId);
        // 用户可用卡片发生变化
        devicePermissEventService.sendUserInfoChangeEvent(cardInfo.getUserId(), cardInfo.getProjectOid(), map);
        return ResultContent.buildSuccess();
    }

    /**
     * 通过ID查询卡片详情
     *
     * @param id
     * @return
     */
    @Override
    public ResultContent<CardInfoModel> getCardDetail(String id) {
        Assert.hasText(id, "id不能为空");
        CardInfo cardInfo = cardInfoDao.findTopById(id);
        if (ObjectUtils.isEmpty(cardInfo)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        CardInfoModel model = toOrgModel(cardInfo);
        return ResultContent.buildSuccess(model);
    }

    @Override
    public ResultContent<CardInfoSimpleModel> getCardDetailByCode(String code) {
        Assert.hasText(code, "code不能为空");
        CardInfo cardInfo = cardInfoDao.findByCode(code);
        if (ObjectUtils.isEmpty(cardInfo)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, code));
        }
        CardInfoSimpleModel model = toSimpleModel(cardInfo);
        return ResultContent.buildSuccess(model);
    }

    //----------------------------园区卡片操作 start ------------------------

    public ResultContent<Page<CardInfoModel>> page(CardInfoSearch param, Pageable pageable) {
        if (StringUtils.isEmpty(param.getProjectOid())) {
            return ResultContent.buildFail("projectOid不能为空");
        }
        Page<CardInfo> page = cardInfoDao.page(pageable, param);
        return ResultContent.buildSuccess(PageEntityUtil.concurrent2PageModel(page, this::toOrgModel));
    }

    /**
     * 卡片ID挂失 (园区管理员操作)
     *
     * @param id
     * @return
     */
    public ResultContent lossById(String id) {
        Assert.hasText(id, "id不能为空");
        String userId = getCurrentUserId();
        UserAccount userAccount = userCountDao.findTopByUserId(userId);

        CardInfo cardInfo = cardInfoDao.findTopById(id);
        if (ObjectUtils.isEmpty(cardInfo)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        if (cardInfo.getCardState() == CardState.Loss) {
            return ResultContent.buildFail(String.format("卡片已是锁定状态：%s", cardInfo.getCode()));
        }
        cardInfo.setCardState(CardState.Loss);
        initUpdateEntity(cardInfo);
        cardInfoDao.save(cardInfo);

        CardInfoLossRecord cardInfoLossRecord = new CardInfoLossRecord();
        cardInfoLossRecord.setCardInfo(cardInfo);
        // 挂失操作人
        cardInfoLossRecord.setOperUserAccount(userAccount);
        cardInfoLossRecord.setOperUserId(userId);
        // 卡片所属人
        cardInfoLossRecord.setCardUserId(cardInfo.getUserId());
        cardInfoLossRecord.setCardUserAccount(cardInfo.getUserAccount());
        cardInfoLossRecord.setOperationType(CardOperationType.Loss);
        cardInfoLossRecordDao.save(cardInfoLossRecord);
        return ResultContent.buildSuccess();
    }

    /**
     * 卡片启用 园区操作
     *
     * @param id
     * @return
     */
    public ResultContent enableById(String id) {
        Assert.hasText(id, "id不能为空");
        String userId = getCurrentUserId();
        UserAccount userAccount = userCountDao.findTopByUserId(userId);

        CardInfo cardInfo = cardInfoDao.findTopById(id);
        if (ObjectUtils.isEmpty(cardInfo)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        if (cardInfo.getCardState() == CardState.Enable) {
            return ResultContent.buildFail(String.format("卡片已是启用状态：%s", cardInfo.getCode()));
        }
        cardInfo.setCardState(CardState.Enable);
        initUpdateEntity(cardInfo);
        cardInfoDao.save(cardInfo);

        CardInfoLossRecord cardInfoLossRecord = new CardInfoLossRecord();
        cardInfoLossRecord.setCardInfo(cardInfo);

        cardInfoLossRecord.setOperUserAccount(userAccount);
        cardInfoLossRecord.setOperUserId(userId);

        cardInfoLossRecord.setCardUserId(cardInfo.getUserId());
        cardInfoLossRecord.setCardUserAccount(cardInfo.getUserAccount());
        cardInfoLossRecord.setOperationType(CardOperationType.Enable);
        cardInfoLossRecordDao.save(cardInfoLossRecord);

        devicePermissEventService.sendUserInfoChangeEvent(cardInfo.getUserId(), cardInfo.getProjectOid(), "enableById");
        return ResultContent.buildSuccess();
    }

    /**
     * 作废卡片(园区操作)
     *
     * @param id
     * @return
     */
    public ResultContent cardCancel(String id) {
        Assert.hasText(id, "id不能为空");
        String userId = getCurrentUserId();
        CardInfo cardInfo = cardInfoDao.findTopById(id);
        if (ObjectUtils.isEmpty(cardInfo)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        if (cardInfo.getIsCanceled() != null && cardInfo.getIsCanceled()) {
            return ResultContent.buildFail(String.format("卡片已是作废状态：%s", cardInfo.getCode()));
        }
        initUpdateEntity(cardInfo);
        cardInfo.setIsCanceled(Boolean.TRUE);
        cardInfo.setCancelUserId(userId);
        cardInfo.setCancelTime(System.currentTimeMillis());
        cardInfoDao.save(cardInfo);
        return ResultContent.buildSuccess();
    }

    /**
     * 恢复作废
     *
     * @param id
     * @return
     */
    @Override
    public ResultContent restoreCardCancel(String id) {
        Assert.hasText(id, "id不能为空");
        String userId = getCurrentUserId();
        CardInfo cardInfo = cardInfoDao.findTopById(id);
        if (ObjectUtils.isEmpty(cardInfo)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        initUpdateEntity(cardInfo);

        // 设置是否作废：否
        cardInfo.setIsCanceled(Boolean.FALSE);
        cardInfo.setCancelUserId(userId);
        cardInfo.setCancelTime(System.currentTimeMillis());
        cardInfoDao.save(cardInfo);
        return ResultContent.buildSuccess();
    }

    public ResultContent getUserProjectAllCard(String userId, String projectOid) {
        List<CardInfo> list = cardInfoDao.findByUserIdAndProjectOid(userId, projectOid);
        List<CardInfoModel> models = new ArrayList<>(list.size());
        if (ObjectUtils.isNotEmpty(list)) {
            models = list.stream().map(this::toModel).collect(Collectors.toUnmodifiableList());
        }
        return ResultContent.buildSuccess(models);
    }

    public List<CardInfo> getProjectCards(String projectOid, List<String> userIds) {
        if (StringUtils.isNotEmpty(projectOid) && ObjectUtils.isNotEmpty(userIds)) {
            return cardInfoDao.findByProjectOidAndUserIdInAndCardStateOrderByUpdateTimeDesc(projectOid, userIds, CardState.Enable);
        }
        return Lists.newArrayList();
    }

    /**
     * 导入 学校卡片excel
     *
     * @param request
     * @param response
     * @param file
     * @return
     */
    public ResultContent<ImportResultModel> importCard(HttpServletRequest request, HttpServletResponse response, MultipartFile file, OidModel param) {
        String oid = param.getOid();
        Assert.hasText(oid, "oid不能为空");
        OidAboutInfo oidAboutInfo = organizationManagerService.getOidAboutInfo(oid);
        String projectOid = oidAboutInfo.getProjectOid();

        ImportResultModel model = new ImportResultModel();
        try {
            int startRow = 2;
            ImportParams params = new ImportParams();
            params.setHeadRows(1);
            params.setTitleRows(1);
            List<CardInfoBindImportParam> list = ExcelImportUtil.importExcel(file.getInputStream(), CardInfoBindImportParam.class, params);
            model.setTotal(list.size());

            HashMap<String, String> codeMap = new HashMap<>();
            HashMap<String, OrganizationUser> phone2OrgId = new HashMap<>();

            List<String> failDetails = new ArrayList<>();
            List<CardInfoPoolBind2OrgUserParam> cardInfoPools = new ArrayList<>();
            if (ObjectUtils.isNotEmpty(list)) {
                List<String> userIds = new ArrayList<>();
                for (CardInfoBindImportParam bindImportParam : list) {
                    startRow++;
                    CardInfoPoolBind2OrgUserParam bind2OrgUserParam = new CardInfoPoolBind2OrgUserParam();
                    // 验证数据合法性
                    String code = bindImportParam.getCode();
                    if (StringUtils.isEmpty(code)) {
                        failDetails.add(String.format("第%d行卡号不能为空", startRow));
                        continue;
                    }
                    code = code.trim();
                    String phone = bindImportParam.getPhone();
                    if (StringUtils.isEmpty(phone)) {
                        failDetails.add(String.format("第%d行手机号码不能为空", startRow));
                        continue;
                    }
                    if (codeMap.containsKey(code)) {
                        failDetails.add(String.format("第%d行卡号已存在", startRow));
                        continue;
                    }
                    CardInfo cardInfo = cardInfoDao.findTopByProjectOidAndCode(projectOid, code);
                    if (ObjectUtils.isNotEmpty(cardInfo)) {
                        failDetails.add(String.format("第%d行卡号%s已绑定", startRow, code));
                        continue;
                    }

                    CardInfoPool cardInfoPool = cardInfoPoolService.getProjectCard(projectOid, code);
                    if (ObjectUtils.isEmpty(cardInfoPool)) {
                        failDetails.add(String.format("第%d行卡号 %s不存在或已使用", startRow, code));
                        continue;
                    }
                    bind2OrgUserParam.setPoolId(cardInfoPool.getId());

                    // 查询用户
                    UserAccount userAccount = userCountDao.findTopByLoginName(phone);
                    if (ObjectUtils.isEmpty(userAccount)) {
                        failDetails.add(String.format("第%d行用户%s不存在", startRow, phone));
                        continue;
                    }
                    OrganizationUser organizationUser = null;
                    if (phone2OrgId.containsKey(phone)) {
                        organizationUser = phone2OrgId.get(phone);
                    } else {
                        List<OrganizationUser> organizationUsers = organizationUserService.getUserOrgList(userAccount.getUserId(), projectOid);
                        if (ObjectUtils.isNotEmpty(organizationUsers)) {
                            organizationUser = organizationUsers.get(0);
                        }
                        if (ObjectUtils.isEmpty(organizationUser)) {
                            failDetails.add(String.format("第%d行用户%s未加入当前项目", startRow, phone));
                            continue;
                        }
                        phone2OrgId.put(phone, organizationUser);
                    }
                    codeMap.put(code, phone);
                    bind2OrgUserParam.setId(organizationUser.getId());
                    cardInfoPools.add(bind2OrgUserParam);
                    userIds.add(userAccount.getUserId());
                }
                if (ObjectUtils.isNotEmpty(cardInfoPools)) {
                    for (CardInfoPoolBind2OrgUserParam bind2OrgUserParam : cardInfoPools) {
                        bindCardFromPoolByOrgId(bind2OrgUserParam.getPoolId(), bind2OrgUserParam.getId(), bind2OrgUserParam.getRemark());
                    }

                    devicePermissEventService.sendUserInfoChangeEvent(userIds, projectOid, "importCard");
                }
                model.setSuccess(cardInfoPools.size());
                model.setFailDetails(failDetails);
            }
        } catch (Exception e) {
            return ResultContent.buildFail(String.format("导入出错：%s", e.getMessage()));
        }
        return ResultContent.buildSuccess(model);
    }

    /**
     * 导出项目用户
     *
     * @param request
     * @param response
     * @param param
     */
    public void exportProjectCard(HttpServletRequest request, HttpServletResponse response, CardInfoSearch param) {
        Assert.hasText(param.getProjectOid(), "projectOid不能为空");

        Organization organization = organizationDao.findTopByOid(param.getProjectOid());
        Pageable pageable = PageRequest.of(0, Integer.MAX_VALUE);
        Page<CardInfo> page = cardInfoDao.page(pageable, param);

        List<Map<String, Object>> maps = new ArrayList<>();
        if (page.getContent() != null) {
            List<CardInfo> list = page.getContent();
            maps = list.stream().map(it -> {
                Map<String, Object> map = BeanUtil.bean2Map(it);
                String cardStr = it.getCardType().getRemark();
                map.put("cardStr", cardStr);

                OrganizationUser orgUser = it.getOrganizationUser();
                if (ObjectUtils.isEmpty(orgUser)) {
                    // 人员编号
                    List<OrganizationUser> tempList = organizationUserService.getUserOrgList(it.getUserId(), it.getProjectOid());
                    if (ObjectUtils.isNotEmpty(tempList)) {
                        orgUser = tempList.get(0);
                    }
                }

                if (ObjectUtils.isNotEmpty(orgUser)) {
                    String userCode = "";
                    String userName = "";
                    String userSex = "";
                    userCode = orgUser.getCode();
                    UserAccount userAccount = orgUser.getUser();
                    if (userAccount != null) {
                        map.put("phone", userAccount.getPhone());
                        if (userAccount.getSex() != null) {
                            userSex = userAccount.getSex().getRemark();
                        }
                        userName = userAccount.getName();
                    }
                    map.put("userCode", userCode);
                    map.put("userName", userName);
                    map.put("userSex", userSex);

                    String orgName = "";
                    Organization organization1 = it.getOrganization();
                    if (ObjectUtils.isNotEmpty(organization1)) {
                        orgName = organization1.getName();
                    }
                    map.put("orgName", orgName);
                    String departmentName = "";
                    if (orgUser.getDepartment() != null) {
                        departmentName = orgUser.getDepartment().getName();
                    }
                    map.put("departmentName", departmentName);
                    String roleNames = "";
                    if (ObjectUtils.isNotEmpty(orgUser.getRoles())) {
                        roleNames = orgUser.getRoles().stream().map(it1 -> it1.getName()).collect(Collectors.joining("、"));
                    }
                    map.put("roleNames", roleNames);
                }
                String cancelStr = "未作废";
                if (it.getIsCanceled() != null && it.getIsCanceled()) {
                    cancelStr = "已作废";
                }
                map.put("cancelStr", cancelStr);
                String cardState = it.getCardState().getRemark();
                map.put("cardState", cardState);

                map.put("createTime", DateUtils.paresTime(it.getCreateTime(), DateUtils.FORMAT_LONG));
                map.put("updateTime", DateUtils.paresTime(it.getUpdateTime(), DateUtils.FORMAT_LONG));
                return map;
            }).collect(Collectors.toList());
        }

        CommonExeclParam execlParam = new CommonExeclParam();
        execlParam.setTitle(String.format("%s卡片数据", organization.getName()));
        execlParam.setStartRow(2);
        execlParam.setDatas(maps);

        List<CommonExeclTd> tds = new ArrayList<>();
        tds.add(CommonExeclTd.build("卡片ID", "code"));
        tds.add(CommonExeclTd.build("卡片类型", "cardStr"));
        tds.add(CommonExeclTd.build("人员编号", "userCode"));
        tds.add(CommonExeclTd.build("姓名", "userName"));
        tds.add(CommonExeclTd.build("性别", "userSex"));
        tds.add(CommonExeclTd.build("机构", "orgName"));
        tds.add(CommonExeclTd.build("部门", "departmentName"));
        tds.add(CommonExeclTd.build("人员类型", "roleNames"));
        tds.add(CommonExeclTd.build("手机号", "phone"));
        tds.add(CommonExeclTd.build("作废状态", "cancelStr"));
        tds.add(CommonExeclTd.build("挂失状态", "cardState"));
        tds.add(CommonExeclTd.build("创建人员", "createUserName"));
        tds.add(CommonExeclTd.build("创建时间", "createTime"));
        tds.add(CommonExeclTd.build("更新人员", "updateUserName"));
        tds.add(CommonExeclTd.build("更新时间", "updateTime"));

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

    //----------------------------园区卡片操作 end --------------------------

    // 简单的信息
    public CardInfoModel toModel(CardInfo entity) {
        CardInfoModel model = null;
        if (ObjectUtils.isNotEmpty(entity)) {
            model = new CardInfoModel();
            BeanUtils.copyProperties(entity, model);
        }
        return model;
    }

    public CardInfoModel toOrgModel(CardInfo entity) {
        CardInfoModel model = null;
        if (ObjectUtils.isNotEmpty(entity)) {
            model = new CardInfoModel();
            BeanUtils.copyProperties(entity, model);

            OrganizationUserModel orgUserInfo = null;
            OrganizationUser organizationUser = entity.getOrganizationUser();
            if (ObjectUtils.isEmpty(organizationUser)) {
                // 机构用户信息
                List<OrganizationUser> list = organizationUserService.getUserOrgList(entity.getUserId(), entity.getProjectOid());
                if (ObjectUtils.isNotEmpty(list)) {
                    organizationUser = list.get(0);
                }
            }
            if (ObjectUtils.isNotEmpty(organizationUser)) {
                orgUserInfo = userAccountService.toOrgUserModel(organizationUser);
            }
            model.setOrganizationUser(orgUserInfo);
        }
        return model;
    }

    public CardInfoSimpleModel toSimpleModel(CardInfo entity) {
        CardInfoSimpleModel model = null;
        if (ObjectUtils.isNotEmpty(entity)) {
            model = new CardInfoSimpleModel();
            BeanUtils.copyProperties(entity, model);
        }
        return model;
    }

    public CardInfoStoreModel toStoreModel(CardInfo entity) {
        CardInfoStoreModel model = null;
        if (ObjectUtils.isNotEmpty(entity)) {
            model = new CardInfoStoreModel();
            BeanUtils.copyProperties(entity, model);
        }
        return model;
    }

}
