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.components.data.base.util.PageEntityUtil;
import com.github.microservice.core.util.bean.BeanUtil;
import com.google.common.collect.Lists;
import com.zhongshu.card.client.model.base.IDsParam;
import com.zhongshu.card.client.model.base.OidModel;
import com.zhongshu.card.client.model.org.OidAboutInfo;
import com.zhongshu.card.client.model.school.*;
import com.github.microservice.net.ResultContent;
import com.github.microservice.net.ResultMessage;
import com.zhongshu.card.client.type.CardCancelState;
import com.zhongshu.card.client.type.school.CardType;
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.school.CardInfoPoolDao;
import com.zhongshu.card.server.core.domain.org.Organization;
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.org.OrganizationServiceImpl;
import com.zhongshu.card.server.core.service.orgManager.OrganizationManagerServiceImpl;
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.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 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;

/**
 * @author TRX
 * @date 2024/7/30
 */
@Slf4j
@Service
public class CardInfoPoolService extends SuperService {

    @Autowired
    CardInfoPoolDao cardInfoPoolDao;

    @Autowired
    OrganizationServiceImpl organizationService;

    @Autowired
    OrganizationDao organizationDao;

    @Autowired
    OrganizationManagerServiceImpl organizationManagerService;

    @Autowired
    OrganizationUserDao organizationUserDao;

    /**
     * 保存卡片信息
     *
     * @param param
     * @return
     */
    public ResultContent saveCardInfoPool(CardInfoPoolParam param) {
        checkParamOid(param);

        CardInfoPool entity = null;
        // 这是oid
        String oid = param.getOid();
        Organization organization = organizationDao.findTopByOid(oid);
        if (ObjectUtils.isEmpty(organization)) {
            return ResultContent.buildFail(String.format("机构不存在：%s", param.getOid()));
        }
        param.setCode(param.getCode().toUpperCase());

        OidAboutInfo oidAboutInfo = organizationManagerService.getOidAboutInfo(oid);
        String projectOid = oidAboutInfo.getProjectOid();
        // 项目唯一
//        CardInfoPool temp = cardInfoPoolDao.findTopByCodeAndProjectOid(param.getCode(), projectOid);
        CardInfoPool temp = cardInfoPoolDao.findTopByCode(param.getCode());
        if (StringUtils.isNotEmpty(param.getId())) {
            entity = cardInfoPoolDao.findTopById(param.getId());
            if (ObjectUtils.isEmpty(entity)) {
                return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
            }
            if (ObjectUtils.isNotEmpty(temp) && !temp.getId().equals(entity.getId())) {
                return ResultContent.buildFail(String.format("卡号已存在：%s", param.getCode()));
            }
            initUpdateEntity(entity);
        } else {
            entity = new CardInfoPool();
            if (ObjectUtils.isNotEmpty(temp)) {
                return ResultContent.buildFail(String.format("卡号已存在：%s", param.getCode()));
            }
            entity.setIsUsed(Boolean.FALSE);
            initEntityNoCheckOid(entity);
        }
        BeanUtils.copyProperties(param, entity, "isUsed");
        entity.setOid(oid);
        entity.setProjectOid(projectOid);
        entity.setAboutAuthType(oidAboutInfo.getAuthType());
        entity.setAboutOid(oidAboutInfo.getOid());
        cardInfoPoolDao.save(entity);
        return ResultContent.buildSuccess();
    }

    /**
     * 分页列表，给web端用
     *
     * @param param
     * @param pageable
     * @return
     */
    public ResultContent<Page<CardInfoPoolModel>> page(CardInfoPoolSearch param, Pageable pageable) {
        checkParamOid(param);
        initOidSearchParamNoCheckOid(param);
        Page<CardInfoPool> page = cardInfoPoolDao.page(pageable, param);
        return ResultContent.buildSuccess(PageEntityUtil.concurrent2PageModel(page, this::toModel));
    }

    /**
     * 查询卡片详情
     *
     * @param id
     * @return
     */
    public ResultContent<CardInfoPoolModel> getCardInfoPoolDetail(String id) {
        CardInfoPool entity = cardInfoPoolDao.findTopById(id);
        if (ObjectUtils.isEmpty(entity)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        return ResultContent.buildSuccess(toModel(entity));
    }

    /**
     * 恢复卡片 （把卡片变成未使用）
     *
     * @param param
     * @return
     */
    public ResultContent<CardInfoPoolModel> restoreCardInfoPool(CardInfoPoolRestoreParam param) {
        CardInfoPool entity = cardInfoPoolDao.findTopById(param.getId());
        if (ObjectUtils.isEmpty(entity)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
        }
        // 判断是否可以恢复

        entity.setIsUsed(Boolean.FALSE);
        entity.setCardCancelState(CardCancelState.Common);
        entity.setUseTime(0L);
        entity.setUseUserId("");
        cardInfoPoolDao.save(entity);
        return ResultContent.buildSuccess(toModel(entity));
    }

    public ResultContent<CardInfoPoolModel> cancelStateChange(CardInfoPoolChangeParam param) {
        CardInfoPool entity = cardInfoPoolDao.findTopById(param.getId());
        if (ObjectUtils.isEmpty(entity)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
        }
        entity.setCardCancelState(param.getCancelState());
        cardInfoPoolDao.save(entity);
        return ResultContent.buildSuccess(toModel(entity));
    }

    /**
     * 删除卡片
     *
     * @param id
     * @return
     */
    public ResultContent deleteCardInfoPool(String id) {
        CardInfoPool entity = cardInfoPoolDao.findTopById(id);
        if (ObjectUtils.isEmpty(entity)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        cardInfoPoolDao.delete(entity);
        return ResultContent.buildSuccess();
    }

    /**
     * 批量删除
     *
     * @param param
     * @return
     */
    public ResultContent deleteByIds(IDsParam param) {
        cardInfoPoolDao.deleteAllById(param.getIds());
        return ResultContent.buildSuccess();
    }

    /**
     * 导入 学校卡片excel
     *
     * @param request
     * @param response
     * @param file
     * @return
     */
    public ResultContent<ImportResultModel> importCardPool(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 {
            ImportParams params = new ImportParams();
            params.setHeadRows(1);
            params.setTitleRows(1);
            List<CardInfoPoolImportParam> list = ExcelImportUtil.importExcel(file.getInputStream(), CardInfoPoolImportParam.class, params);
            model.setTotal(list.size());

            int startRow = 2;
            List<String> failDetails = new ArrayList<>();
            List<CardInfoPool> cardInfoPools = new ArrayList<>();
            HashMap<String, String> codeMap = new HashMap<>();
            if (ObjectUtils.isNotEmpty(list)) {
                for (CardInfoPoolImportParam param1 : list) {
                    startRow++;

                    // 验证数据合法性
                    String code = param1.getCode();
                    if (StringUtils.isEmpty(code)) {
                        failDetails.add(String.format("第%d行卡号不能为空", startRow));
                        continue;
                    }
                    code = code.trim().toUpperCase();
                    if (codeMap.containsKey(code)) {
                        failDetails.add(String.format("第%d行卡号%s已存在", startRow, code));
                        continue;
                    }

                    if (StringUtils.isEmpty(param1.getCardType())) {
                        failDetails.add(String.format("第%d行卡片类型不能为空", startRow));
                        continue;
                    }

                    if (StringUtils.isNotEmpty(param1.getCardType())) {
                        CardType cardType = CommonUtil.getCardTypeByStr(param1.getCardType());
                        if (cardType == null) {
                            failDetails.add(String.format("第%d行卡片类型不正确", startRow));
                            continue;
                        }
                    }

                    // 检查是否已存在 code
                    boolean exit = cardInfoPoolDao.existsByCode(code);
                    if (exit) {
                        failDetails.add(String.format("第%d行卡号%s已存在", startRow, code));
                        continue;
                    }

                    // 组装数据
                    codeMap.put(code, code);
                    // 验证通过
                    CardInfoPool pool = new CardInfoPool();
                    initEntity(pool);
                    param1.setCode(code);
                    BeanUtils.copyProperties(param1, pool, "cardType");
                    pool.setSchoolOid("");
                    pool.setProjectOid(projectOid);
                    pool.setOid(oid);
                    pool.setAboutOid(oidAboutInfo.getOid());
                    pool.setAboutAuthType(oidAboutInfo.getAuthType());

                    // 初始状态为  未使用
                    pool.setIsUsed(Boolean.FALSE);
                    // 对比出卡片类型
                    CardType cardType = CommonUtil.getCardTypeByStr(param1.getCardType());
                    pool.setCardType(cardType);
                    cardInfoPools.add(pool);
                }
                cardInfoPoolDao.saveAll(cardInfoPools);
                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, CardInfoPoolSearch param) {
        Assert.hasText(param.getProjectOid(), "projectOid不能为空");

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

        List<Map<String, Object>> maps = new ArrayList<>();
        if (page.getContent() != null) {
            List<CardInfoPool> list = page.getContent();
            maps = list.stream().map(it -> {
                Map<String, Object> map = BeanUtil.bean2Map(it);
                String cardStr = it.getCardType().getRemark();
                map.put("cardStr", cardStr);
                String useStr = "未使用";
                if (it.getIsUsed() != null && it.getIsUsed()) {
                    useStr = "已使用";
                }
                map.put("useStr", useStr);
                // 作废状态
                String cancelStr = "";
                if (it.getCardCancelState() != null) {
                    cancelStr = it.getCardCancelState().getRemark();
                }
                map.put("cancelStr", cancelStr);
                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("卡号", "code"));
        tds.add(CommonExeclTd.build("卡片类型", "cardStr"));
        tds.add(CommonExeclTd.build("使用状态", "useStr"));
        tds.add(CommonExeclTd.build("作废状态", "cancelStr"));
        tds.add(CommonExeclTd.build("备注", "remark"));
        execlParam.setTds(tds);
        ExcelUtils.commonExecuteExcel(request, response, execlParam);
    }

    public CardInfoPool getProjectCard(String projectOid, String code) {
        CardInfoPool cardInfoPool = null;
        if (StringUtils.isNotEmpty(projectOid) && StringUtils.isNotEmpty(code)) {
            cardInfoPool = cardInfoPoolDao.findTopByProjectOidAndCodeAndIsUsedAndCardCancelState(projectOid, code, Boolean.FALSE, CardCancelState.Common);
        }
        return cardInfoPool;
    }

    /**
     * 搜索卡片
     *
     * @param param
     * @return
     */
    public ResultContent<List<CardInfoPoolSimpleModel>> queryPoolCard(CardInfoPoolQueryParam param) {
        if (StringUtils.isEmpty(param.getCode())) {
            return ResultContent.buildSuccess(Lists.newArrayList());
        }
        String projectOid = param.getProjectOid();
        if (StringUtils.isEmpty(projectOid)) {
            projectOid = getCurrentProjectOid();
        }
        // 查询前十的卡片数据
        List<CardInfoPool> list = cardInfoPoolDao.findTop10ByProjectOidAndCodeLikeAndIsUsedAndCardCancelState(projectOid, param.getCode(), Boolean.FALSE, CardCancelState.Common);
        List<CardInfoPoolSimpleModel> models = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(list)) {
            models = list.stream().map(this::toSimpleModel).collect(Collectors.toList());
        }
        return ResultContent.buildSuccess(models);
    }

    public CardInfoPoolModel toModel(CardInfoPool entity) {
        CardInfoPoolModel model = null;
        if (ObjectUtils.isNotEmpty(entity)) {
            model = new CardInfoPoolModel();
            BeanUtils.copyProperties(entity, model);
        }
        return model;
    }

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

}
