package com.cool.store.service.close.impl;

import com.cool.store.constants.CommonConstants;
import com.cool.store.constants.RedisConstant;
import com.cool.store.dao.CloseStoreFileDetailDAO;
import com.cool.store.dao.CloseStoreFileInfoDAO;
import com.cool.store.dao.CloseStoreInfoDAO;
import com.cool.store.dao.CloseStoreStageInfoDAO;
import com.cool.store.entity.CloseStoreFileInfoDO;
import com.cool.store.entity.CloseStoreInfoDO;
import com.cool.store.entity.CloseStoreStageInfoDO;
import com.cool.store.enums.ErrorCodeEnum;
import com.cool.store.enums.close.*;
import com.cool.store.exception.ServiceException;
import com.cool.store.request.close.file.*;
import com.cool.store.entity.CloseStoreFileDetailDO;
import com.cool.store.service.close.CloseStoreFileService;
import com.cool.store.service.close.CloseStoreService;
import com.cool.store.utils.BeanUtil;
import com.cool.store.utils.RedisUtilPool;
import com.cool.store.vo.close.file.CloseStoreFileDetailMiniVO;
import com.cool.store.vo.close.file.CloseStoreFileDetailVO;
import com.cool.store.vo.close.file.CloseStoreFileInfoVO;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

import static com.cool.store.enums.close.CloseStoreSubStageStatusEnum.*;

/**
 * <p>
 * 闭店资料 服务实现类
 * </p>
 *
 * @author wangff
 * @since 2025/10/7
 */
@Service
@RequiredArgsConstructor
public class CloseStoreFileServiceImpl implements CloseStoreFileService {
    private final CloseStoreFileDetailDAO closeStoreFileDetailDAO;
    private final CloseStoreFileInfoDAO closeStoreFileInfoDAO;
    private final CloseStoreStageInfoDAO closeStoreStageInfoDAO;
    private final CloseStoreService closeStoreService;
    private final RedisUtilPool redisUtilPool;
    private final CloseStoreInfoDAO closeStoreInfoDAO;


    private static final CloseStoreStageEnum STAGE = CloseStoreStageEnum.CLOSE_STORE_STAGE_1;
    private static final CloseStoreSubStageEnum SUB_STAGE = CloseStoreSubStageEnum.CLOSE_STORE_SUB_STAGE_10;

    @Override
    @Transactional
    public Boolean updateMailAddress(CloseStoreMailAddressRequest request) {
        closeStoreStageInfoDAO.verifyStage(request.getCloseStoreId(), STAGE, SUB_STAGE, CLOSE_STORE_SUB_STAGE_STATUS_10);

        closeStoreFileDetailDAO.insertOrUpdateMailAddress(request);
        closeStoreService.closeStoreProcessFlow(request.getCloseStoreId(), SUB_STAGE);
        return true;
    }

    @Override
    @Transactional
    public Boolean submitFileApprove(CloseStoreFileApproveRequest request) {
        // 校验流程是否在材料待审批阶段
        closeStoreStageInfoDAO.verifyStage(request.getCloseStoreId(), STAGE, SUB_STAGE, CLOSE_STORE_SUB_STAGE_STATUS_18);
        // 修改材料详情
        boolean approveCompleted = ListUtils.emptyIfNull(request.getFileList()).stream().allMatch(v -> CommonConstants.INDEX_ONE.equals(v.getApproveStatus()));
        closeStoreFileDetailDAO.insertOrUpdateFileInfoSelective(request, approveCompleted);
        // 修改所有材料的审批状态
        if (CollectionUtils.isNotEmpty(request.getFileList())) {
            List<CloseStoreFileInfoDO> fileList = BeanUtil.toList(request.getFileList(), CloseStoreFileInfoDO.class);
            closeStoreFileInfoDAO.updateBatch(fileList);
        }
        // 全部材料合格，流程流转
        if (approveCompleted) {
            closeStoreService.closeStoreProcessFlow(request.getCloseStoreId(), SUB_STAGE);
        }
        return true;
    }

    @Override
    @Transactional
    public Boolean submitFileApproveSingle(CloseStoreFileInfoRequest request) {
        // 校验流程是否在材料待审批阶段
        closeStoreStageInfoDAO.verifyStage(request.getCloseStoreId(), STAGE, SUB_STAGE, CLOSE_STORE_SUB_STAGE_STATUS_18);
        // 更新其他字段
        updateFileField(request);
        // 更新材料审批信息
        CloseStoreFileInfoDO updateFileInfoDO = CloseStoreFileInfoDO.builder()
                .id(request.getId())
                .approveStatus(request.getApproveStatus())
                .mailStatus(request.getMailStatus())
                .approveOpinion(request.getApproveOpinion())
                .urls(request.getUrls())
                .build();
        closeStoreFileInfoDAO.updateSelective(updateFileInfoDO);
        // 校验所有材料是否审批完成，完成后流程流转
        verifyComplete(request);
        return true;
    }

    /**
     * 校验所有材料是否全部完成邮寄和审批完成
     */
    private void verifyComplete(CloseStoreFileInfoRequest request) {
        List<CloseStoreFileInfoDO> fileList = closeStoreFileInfoDAO.getByCloseStoreId(request.getCloseStoreId());
        // 除了授权书其他材料完成邮寄
        boolean completeApprove = fileList.stream()
                .filter(v -> !CloseStoreFileEnum.SQS.getCode().equals(v.getFileCode()))
                .allMatch(v -> Objects.nonNull(v.getApproveStatus()) && CommonConstants.INDEX_ONE.equals(v.getMailStatus()));
        if (completeApprove) {
            closeStoreFileDetailDAO.insertOrUpdateFileInfoSelective(CloseStoreFileApproveRequest.builder().closeStoreId(request.getCloseStoreId()).build(), true);
            boolean pass = fileList.stream().allMatch(v -> CommonConstants.INDEX_ONE.equals(v.getApproveStatus()));
            // 更新材料状态为审批状态
            closeStoreFileInfoDAO.updateFileStatusToApproveStatus(request.getCloseStoreId());
            if (pass) {
                closeStoreService.closeStoreProcessFlow(request.getCloseStoreId(), SUB_STAGE);
            } else {
                closeStoreStageInfoDAO.updateSubStageStatus(request.getCloseStoreId(), CLOSE_STORE_SUB_STAGE_STATUS_19);
            }
        }
    }

    /**
     * 更新其他字段
     */
    private void updateFileField(CloseStoreFileInfoRequest request) {
        CloseStoreFileInfoDO fileInfoDO = closeStoreFileInfoDAO.getById(request.getId());
        if (Objects.isNull(fileInfoDO)) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_FILE_NOT_EXIST);
        }
        if (CloseStoreFileEnum.TKD.getCode().equals(fileInfoDO.getFileCode())) {
            boolean f = Stream.of(request.getBankAccount(), request.getBankOpening(), request.getRefundAccount()).anyMatch(StringUtils::isNotBlank);
            if (f) {
                CloseStoreFileApproveRequest approveRequest = CloseStoreFileApproveRequest.builder()
                        .closeStoreId(request.getCloseStoreId())
                        .bankAccount(request.getBankAccount())
                        .bankOpening(request.getBankOpening())
                        .refundAccount(request.getRefundAccount())
                        .build();
                closeStoreFileDetailDAO.insertOrUpdateFileInfoSelective(approveRequest, false);
            }
        }
    }

    @Override
    public CloseStoreFileDetailVO getFileDetail(Long closeStoreId) {
        CloseStoreInfoDO closeStoreInfoDO = closeStoreInfoDAO.getById(closeStoreId);
        if (Objects.isNull(closeStoreInfoDO)) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_INFO_NOT_EXIST);
        }
        CloseStoreFileDetailDO fileDetailDO = closeStoreFileDetailDAO.getByCloseStoreId(closeStoreId);
        CloseStoreFileDetailVO detailVO = BeanUtil.toBean(fileDetailDO, CloseStoreFileDetailVO.class);
        detailVO.setCloseStoreNo(closeStoreInfoDO.getCloseStoreNo());

        List<CloseStoreFileInfoDO> fileList = closeStoreFileInfoDAO.getByCloseStoreId(closeStoreId);
        List<CloseStoreFileInfoVO> fileVOList = BeanUtil.toList(fileList, CloseStoreFileInfoVO.class);
        detailVO.setFileList(fileVOList);
        CloseStoreStageInfoDO stageInfo = closeStoreStageInfoDAO.getByStage(closeStoreId, STAGE.getCloseStoreStage(), SUB_STAGE.getCloseStoreSubStage());
        detailVO.setShopSubStageStatus(stageInfo.getShopSubStageStatus());
        if (CollectionUtils.isNotEmpty(detailVO.getFileList())) {
            detailVO.getFileList().forEach(v -> v.setTemplateUrl(redisUtilPool.hashGet(RedisConstant.CLOSE_STORE_FILE_TEMPLATE, v.getFileCode())));
        }
        return detailVO;
    }

    @Override
    public CloseStoreFileDetailMiniVO getMiniFileDetail(Long closeStoreId) {
        CloseStoreFileDetailVO fileDetail = getFileDetail(closeStoreId);
        return BeanUtil.toBean(fileDetail, CloseStoreFileDetailMiniVO.class);
    }

    @Override
    @Transactional
    public Boolean submitFile(CloseStoreMailInfoRequest request) {
        // 校验流程是否在材料待上传阶段
        CloseStoreSubStageStatusEnum[] conditions = {CLOSE_STORE_SUB_STAGE_STATUS_15, CLOSE_STORE_SUB_STAGE_STATUS_17, CLOSE_STORE_SUB_STAGE_STATUS_19};
        closeStoreStageInfoDAO.verifyStage(request.getCloseStoreId(), STAGE, SUB_STAGE, conditions);
        // 修改邮寄信息
        closeStoreFileDetailDAO.insertOrUpdateMailInfo(request, true);
        // 校验所有材料是否上传完成，完成后流程流转
        List<CloseStoreFileInfoDO> files = closeStoreFileInfoDAO.getByCloseStoreId(request.getCloseStoreId());
        List<Integer> verifyList = Arrays.asList(FileStatusEnum.UPLOADED.getStatus(), FileStatusEnum.MODIFIED.getStatus(), FileStatusEnum.QUALIFIED.getStatus());
        boolean verify = files.stream().allMatch(v -> verifyList.contains(v.getFileStatus()));
        if (verify) {
            closeStoreService.closeStoreProcessFlow(request.getCloseStoreId(), SUB_STAGE);
        }
        return true;
    }

    @Override
    public Boolean updateFile(CloseStoreFileSubmitRequest request) {
        CloseStoreSubStageStatusEnum[] conditions = {CLOSE_STORE_SUB_STAGE_STATUS_15, CLOSE_STORE_SUB_STAGE_STATUS_17, CLOSE_STORE_SUB_STAGE_STATUS_19};
        closeStoreStageInfoDAO.verifyStage(request.getCloseStoreId(), STAGE, SUB_STAGE, conditions);
        return closeStoreFileInfoDAO.updateFile(request.getId(), request.getUrls(), request.getReceivedFile());
    }

    @Override
    @Transactional
    public Boolean supervisionAudit(CloseStoreFileAuditRequest request) {
        closeStoreStageInfoDAO.verifyStage(request.getCloseStoreId(), STAGE, SUB_STAGE, CLOSE_STORE_SUB_STAGE_STATUS_16);
        if (CommonConstants.INDEX_ONE.equals(request.getStatus())) {
            // 所有资料状态改为审批中
            closeStoreFileInfoDAO.updateAllFileStatus(request.getCloseStoreId());
            // 流程流转
            closeStoreService.closeStoreProcessFlow(request.getCloseStoreId(), SUB_STAGE);
        } else {
            // 修改督导审批意见
            closeStoreFileDetailDAO.updateByCloseStoreIdSelective(CloseStoreFileDetailDO.builder().closeStoreId(request.getCloseStoreId()).remark(request.getRemark()).build());
            // 修改阶段状态
            closeStoreStageInfoDAO.updateSubStageStatus(request.getCloseStoreId(), CLOSE_STORE_SUB_STAGE_STATUS_17);
        }
        return true;
    }
}
