package com.ningdatech.pmapi.expert.manage;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.file.entity.vo.result.AttachFileVo;
import com.ningdatech.file.service.FileService;
import com.ningdatech.pmapi.common.model.FileBasicInfo;
import com.ningdatech.pmapi.expert.assembler.ExpertInfoCmdAssembler;
import com.ningdatech.pmapi.expert.assembler.ExpertUserInfoAssembler;
import com.ningdatech.pmapi.expert.constant.ExpertAccountStatusEnum;
import com.ningdatech.pmapi.expert.constant.ExpertUserInfoStepEnum;
import com.ningdatech.pmapi.expert.entity.ExpertUserFullInfo;
import com.ningdatech.pmapi.expert.helper.ExpertInfoCommonHelper;
import com.ningdatech.pmapi.expert.helper.ExpertManageHelper;
import com.ningdatech.pmapi.expert.model.*;
import com.ningdatech.pmapi.expert.model.cmd.ExpertFullInfoSaveCmd;
import com.ningdatech.pmapi.expert.model.cmd.ExpertRecommendProofSaveCmd;
import com.ningdatech.pmapi.expert.model.dto.ExpertDictionaryDTO;
import com.ningdatech.pmapi.expert.model.dto.ExpertFullInfoAllDTO;
import com.ningdatech.pmapi.expert.model.req.ExpertRegistrationRequest;
import com.ningdatech.pmapi.expert.model.req.ExpertUserBasicInfoSubmitRequest;
import com.ningdatech.pmapi.expert.model.vo.ExpertFullInfoVO;
import com.ningdatech.pmapi.expert.service.ExpertInfoService;
import com.ningdatech.pmapi.expert.service.IExpertUserFullInfoService;
import com.ningdatech.pmapi.meta.constant.DictExpertInfoTypeEnum;
import com.ningdatech.pmapi.meta.model.ExpertRegionInfo;
import com.ningdatech.pmapi.sms.constant.VerificationCodeType;
import com.ningdatech.pmapi.sms.helper.VerifyCodeCheckHelper;
import com.ningdatech.pmapi.sys.model.entity.Role;
import com.ningdatech.pmapi.sys.model.entity.UserRole;
import com.ningdatech.pmapi.sys.service.IRoleService;
import com.ningdatech.pmapi.sys.service.IUserRoleService;
import com.ningdatech.pmapi.user.constant.UserAvailableEnum;
import com.ningdatech.pmapi.user.entity.UserInfo;
import com.ningdatech.pmapi.user.entity.enumeration.RoleEnum;
import com.ningdatech.pmapi.user.service.IUserInfoService;
import com.ningdatech.pmapi.user.util.LoginUserUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author liuxinxin
 * @date 2023/2/23 上午8:55
 */

@Component
@RequiredArgsConstructor
public class ExpertManage {

    private final ExpertManageHelper expertManageHelper;
    private final IExpertUserFullInfoService iExpertUserFullInfoService;
    private final ExpertInfoService expertInfoService;
    private final ExpertInfoCommonHelper expertInfoCommonHelper;
    private final FileService fileService;
    private final ExpertUserInfoAssembler expertUserInfoAssembler;
    private final IUserInfoService iUserInfoService;
    private final ExpertMetaApplyManage expertMetaApplyManage;
    private final IUserRoleService iUserRoleService;
    private final IRoleService iRoleService;
    private final VerifyCodeCheckHelper verifyCodeCheckHelper;


    /**
     * 专家管理员新增专家
     *
     * @param req /
     */
    @Transactional(rollbackFor = Exception.class)
    public void expertBasicInfoSubmit(ExpertUserBasicInfoSubmitRequest req) {
        Long operatorId = LoginUserUtil.getUserId();
        // 用户id
        Long userId = assemblerAndGenerateExpert(req, operatorId);
        // 批量通过专家入库审核/专家履职意向审核
        expertMetaApplyManage.autoPassExpertApply(userId);

        // 增加用户专家角色
        Role role = iRoleService.getOne(Wrappers.lambdaQuery(Role.class).eq(Role::getCode, RoleEnum.EXPERT.name()));
        UserRole expertRole = iUserRoleService.getOne(userId, role.getId());
        if (Objects.isNull(expertRole)) {
            expertRole = new UserRole();
            expertRole.setUserId(userId);
            expertRole.setRoleId(role.getId());
            iUserRoleService.save(expertRole);
        }
    }


    @Transactional(rollbackFor = Exception.class)
    public Long expertRecommendProofSubmit(List<DictionaryFieldInfo> recommendedWay, List<FileBasicInfo> recommendProofFile, Long expertUserId) {
        // 用户id
        ExpertUserFullInfo expertUserFullInfo = iExpertUserFullInfoService.getByUserId(expertUserId);
        // 判断专家状态，是否可以进行证明材料提交
        if (Objects.isNull(expertUserFullInfo)
                || !ExpertAccountStatusEnum.APPLYING.getKey().equals(expertUserFullInfo.getExpertAccountStatus())
                || ExpertUserInfoStepEnum.EVIDENCE_HAS_BEEN_SUBMITTED.getKey().equals(expertUserFullInfo.getUserInfoStep())) {
            throw new BizException("当前状态无法提交证明材料");
        }

        // 证明材料提交
        ExpertRecommendProofSaveCmd expertRecommendProofSaveCmd = new ExpertRecommendProofSaveCmd();
        if (CollectionUtils.isNotEmpty(recommendProofFile)) {
            expertRecommendProofSaveCmd.setRecommendationProofFileIdList(recommendProofFile.stream().map(FileBasicInfo::getFileId).collect(Collectors.toList()));
        }
        List<ExpertDictionaryDTO> recommendedWayDictionaryDTOList = new ArrayList<>();
        if (CollUtil.isNotEmpty(recommendedWay)) {
            recommendedWay.forEach(r -> {
                ExpertDictionaryDTO expertDictionaryDTO = new ExpertDictionaryDTO();
                expertDictionaryDTO.setDictionaryCode(r.getDictionaryCode());
                expertDictionaryDTO.setExpertInfoField(DictExpertInfoTypeEnum.RECOMMENDED_WAY.getKey());
                recommendedWayDictionaryDTOList.add(expertDictionaryDTO);
            });
        }
        expertRecommendProofSaveCmd.setRecommendedWay(recommendedWayDictionaryDTOList);
        expertRecommendProofSaveCmd.setUserId(expertUserId);
        return expertInfoService.expertRecommendProofSave(expertRecommendProofSaveCmd);
    }

    public ExpertFullInfoVO getExpertFullInfoDetail(Long expertUserId) {
        Long currentUserId = LoginUserUtil.getUserId();
        if (Objects.isNull(expertUserId)) {
            expertUserId = currentUserId;
        }
        ExpertFullInfoAllDTO expertUserFullInfoAll = expertInfoService.getExpertUserFullInfoAll(expertUserId);
        if (Objects.isNull(expertUserFullInfoAll)) {
            return null;
        }
        List<Long> fileIdList = expertInfoCommonHelper.getExpertFileIdList(expertUserFullInfoAll);
        List<AttachFileVo> attachFiles = fileService.getByIds(fileIdList);
        return expertUserInfoAssembler.buildExpertFullInfoVO(attachFiles, expertUserFullInfoAll);
    }

    @Transactional(rollbackFor = Exception.class)
    public Long generateOrGetUserId(ExpertBasicInfo basicInfo, Long operatorId) {
        String phoneNo = basicInfo.getPhoneNo();
        UserInfo userInfo = iUserInfoService.getUserInfoByPhoneNo(phoneNo);
        if (Objects.isNull(userInfo)) {
            userInfo = UserInfo.builder()
                    //.accountId(dingEmployeeInfo.getAccountId())
                    .username(basicInfo.getName())
                    .realName(basicInfo.getName())
                    //.employeeCode(dingEmployeeInfo.getEmployeeCode())
                    .available(UserAvailableEnum.DISABLE.name())
                    .mobile(phoneNo)
                    .createBy(operatorId)
                    .updateBy(operatorId)
                    .createOn(LocalDateTime.now())
                    .updateOn(LocalDateTime.now())
                    .build();
            iUserInfoService.save(userInfo);
        }
        ExpertUserFullInfo one = iExpertUserFullInfoService.getOne(Wrappers.lambdaQuery(ExpertUserFullInfo.class)
                .eq(ExpertUserFullInfo::getPhoneNo, phoneNo));
        if (Objects.nonNull(one)) {
            throw new BizException("该手机号已被专家注册，请确认后再填写");
        }
        return userInfo.getId();
    }

    /**
     * 社会专家报名 需要校验手机号
     *
     * @param request
     */
    @Transactional(rollbackFor = Exception.class)
    public void expertRegistration(ExpertRegistrationRequest request) {
        String verificationCode = request.getVerificationCode();
        String phoneNo = request.getBasicInfo().getPhoneNo();
        //校验 专家验证码
        if (false) {
            verifyCodeCheckHelper.verification(VerificationCodeType.EXPERT_REGISTER, phoneNo, verificationCode);
        }
        assemblerAndGenerateExpert(request, null);
    }


    @Transactional(rollbackFor = Exception.class)
    public Long assemblerAndGenerateExpert(ExpertUserBasicInfoSubmitRequest req, Long operatorId) {
        if (Objects.isNull(operatorId)) {
            operatorId = -1L;
        }
        ExpertBasicInfo basicInfo = req.getBasicInfo();
        Long userId = generateOrGetUserId(basicInfo, operatorId);

        // 校验区域编码合法性 校验履职意向编码合法性
        ExpertRegionInfo expertRegionInfo = basicInfo.getExpertRegionInfo();
        expertManageHelper.expertRegionInfoCheck(expertRegionInfo);
        List<ExpertRegionInfo> expertIntentionWorkRegions = basicInfo.getExpertIntentionWorkRegions();
        for (ExpertRegionInfo expertIntentionWorkRegion : expertIntentionWorkRegions) {
            expertManageHelper.expertRegionInfoCheck(expertIntentionWorkRegion);
        }
        ExpertEduInfo eduInfo = req.getEduInfo();
        ExpertJobInfo jobInfo = req.getJobInfo();
        ExpertProfessionalInfo professionalInfo = req.getProfessionalInfo();
        // 校验标签字段
        expertManageHelper.tagFieldCheck(professionalInfo, basicInfo);
        // 校验字典字段
        expertManageHelper.dictionaryFieldCheck(basicInfo, eduInfo, jobInfo);
        // 判断专家提交状态，判断是否可以进行此操作
        ExpertUserFullInfo expertUserFullInfo = iExpertUserFullInfoService.getByUserId(userId);

        boolean submitBasicInfoStatusEnable = Objects.isNull(expertUserFullInfo)
                || (ExpertAccountStatusEnum.APPLYING.getKey().equals(expertUserFullInfo.getExpertAccountStatus())
                && !ExpertUserInfoStepEnum.EVIDENCE_HAS_BEEN_SUBMITTED.getKey().equals(expertUserFullInfo.getUserInfoStep()));
        if (submitBasicInfoStatusEnable) {
            // 新建 保存
            ExpertFullInfoSaveCmd expertFullInfoSaveCmd = ExpertInfoCmdAssembler
                    .buildExpertFullInfoSaveCmd(userId, basicInfo, eduInfo, jobInfo, professionalInfo);
            expertInfoService.saveExpertInfo(expertFullInfoSaveCmd);
        }

        ExpertRecommendInfo recommendInfo = req.getRecommendInfo();
        // 推荐证明材料
        List<DictionaryFieldInfo> recommendedWay = recommendInfo.getRecommendedWay();
        // 推荐方式
        List<FileBasicInfo> recommendProofFile = recommendInfo.getRecommendationProofFile();
        expertRecommendProofSubmit(recommendedWay, recommendProofFile, userId);
        return userId;
    }

}
