package com.cool.store.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.cool.store.constants.CommonConstants;
import com.cool.store.context.LoginUserInfo;
import com.cool.store.dao.HyPartnerUserChannelDAO;
import com.cool.store.dao.LineInfoDAO;
import com.cool.store.dao.QualificationsInfoDAO;
import com.cool.store.entity.*;
import com.cool.store.enums.*;
import com.cool.store.exception.ApiException;
import com.cool.store.exception.ServiceException;
import com.cool.store.mapper.*;
import com.cool.store.mq.util.HttpRestTemplateService;
import com.cool.store.request.*;
import com.cool.store.response.InitiatingResponse;
import com.cool.store.response.ResponseResult;
import com.cool.store.response.SigningBaseInfoResponse;
import com.cool.store.service.*;
import com.cool.store.utils.RedisUtilPool;
import com.cool.store.utils.SecureUtil;
import com.cool.store.utils.StringUtil;
import com.cool.store.utils.poi.DateUtils;
import com.cool.store.utils.poi.constant.Constants;
import com.cool.store.vo.BusinessLicenseInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;


@Service
@Slf4j
public class IntentAgreementServiceImpl extends LineFlowService implements IntentAgreementService, AuditResultService {


    @Resource
    IntentAgreementMapper intentAgreementMapper;

    @Resource
    LineInfoMapper lineInfoMapper;

    @Resource
    JoinIntentionMapper joinIntentionMapper;

    @Resource
    LineInfoDAO lineInfoDAO;

    @Resource
    private HttpRestTemplateService httpRestTemplateService;

    @Value("${xfsg.url}")
    private String xfsgUrl;

    @Resource
    LineAuditInfoMapper lineAuditInfoMapper;

    @Resource
    LinePayMapper linePayMapper;

    @Resource
    HyOpenAreaInfoMapper openAreaInfoMapper;

    @Resource
    RedisUtilPool redisUtilPool;

    @Resource
    private CommonService commonService;

    @Resource
    AliyunService aliyunService;
    @Resource
    private UserAuthMappingService userAuthMappingService;
    @Resource
    private ShopService shopService;
    @Resource
    QualificationsInfoDAO qualificationsInfoDAO;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submit(IntentAgreementSubmitRequest request) {
        SigningBaseInfoDO signingBaseInfoDO = request.toSigningBaseInfoDO();
        boolean submitStatus = intentAgreementMapper.insert(signingBaseInfoDO);
        if (submitStatus) {
            LineInfoDO lineInfoDO = lineInfoMapper.getByPartnerId(request.getPartnerId());
            if (Objects.isNull(lineInfoDO)) {
                throw new ServiceException(ErrorCodeEnum.INTERVIEW_PARTNER_NOT_EXIST);
            }
            lineInfoDO.setWorkflowSubStageStatus(WorkflowSubStageStatusEnum.SIGN_INTENT_AGREEMENT_125.getCode());
            lineInfoMapper.updateByPrimaryKeySelective(lineInfoDO);
            AuditPassRequest auditPassRequest = new AuditPassRequest();
            auditPassRequest.setLineId(lineInfoDO.getId());
            auditPassRequest.setWorkflowSubStage(lineInfoDO.getWorkflowSubStage());
            commonService.getLineFlowService(lineInfoDO.getWorkflowSubStage()).auditPass(auditPassRequest, null);
            // TODO: 2024/6/18 企微工作通知
//            Map<String, String> requestMap = new HashMap<>();
//            requestMap.put("partnerUsername", lineInfoDO.getUsername());
//            requestMap.put("partnerMobile", lineInfoDO.getMobile());
//            requestMap.put("lineId", String.valueOf(lineInfoDO.getId()));
//            requestMap.put("submitTime", DateUtils.dateTimeNow(DateUtils.SPECIAL_DATE_START));
//            commonService.sendMessage(Collections.singletonList(lineInfoDO.getInvestmentManager()),
//                    MessageEnum.MESSAGE_30,
//                    requestMap);
            return Boolean.TRUE;

        }
        return false;
    }

    @Override
    public SigningBaseInfoResponse getMiniIntentAgreement(String partnerId, Long lineId) {
        if (StringUtil.isBlank(partnerId) && lineId == null) {
            throw new ServiceException(ErrorCodeEnum.PARAMS_VALIDATE_ERROR);
        }
        SigningBaseInfoDO signingBaseInfoDO = intentAgreementMapper.selectByPartnerIdOrLineId(partnerId, lineId);
        if (Objects.isNull(signingBaseInfoDO)) {
            log.info("getMiniIntentAgreement signingBaseInfoDO IS NULL......");
            return null;
        }
        SigningBaseInfoResponse response = SigningBaseInfoResponse.from(signingBaseInfoDO);
        QualificationsInfoDO byLineId = qualificationsInfoDAO.getByLineId(lineId);
        response.setType(byLineId.getJoinType());
        if (Objects.nonNull(signingBaseInfoDO.getAuditId())) {
            LineAuditInfoDO lineAuditInfoDO = lineAuditInfoMapper.selectByPrimaryKey(signingBaseInfoDO.getAuditId());
            if (Objects.isNull(lineAuditInfoDO)) {
                response.setRejectPublicReason(null);
            }
            response.setRejectPublicReason(lineAuditInfoDO.getRejectPublicReason());
        }
        return response;
    }

    @Override
    protected Boolean auditPass(Long auditId, LineInfoDO lineInfo, String userId) {
        LineInfoDO updateLine = new LineInfoDO();
        updateLine.setId(lineInfo.getId());
        updateLine.setWorkflowStage(WorkflowStageEnum.STORE.getCode());
        updateLine.setWorkflowSubStageStatus(WorkflowSubStageStatusEnum.SIGN_INTENT_AGREEMENT_125.getCode());
        updateLine.setDevelopmentManager(lineInfo.getInvestmentManager());
        updateLine.setUpdateUserId(userId);
        lineInfoDAO.updateLineInfo(updateLine);
        //初始化店铺
        shopService.initShop(lineInfo);
        return Boolean.TRUE;
    }

    @Override
    protected Boolean auditReject(Long auditId, LineInfoDO lineInfo, String userId) {
        return null;
    }


    @Override
    public Boolean initiating(IntentAgreementSubmitRequest request, LoginUserInfo user) {
        log.info("initiating request:{}",JSONObject.toJSONString(request));
        SigningBaseInfoDO signingBaseInfoDO = request.toSigningBaseInfoDO();
        boolean submitStatus = intentAgreementMapper.insert(signingBaseInfoDO);
        if (submitStatus) {
            LineInfoDO lineInfoDO = lineInfoMapper.getByPartnerId(request.getPartnerId());
            if (Objects.isNull(lineInfoDO)) {
                throw new ServiceException(ErrorCodeEnum.INTERVIEW_PARTNER_NOT_EXIST);
            }
            lineInfoDO.setWorkflowSubStageStatus(WorkflowSubStageStatusEnum.SIGN_INTENT_AGREEMENT_125.getCode());
            lineInfoMapper.updateByPrimaryKeySelective(lineInfoDO);
            AuditPassRequest auditPassRequest = new AuditPassRequest();
            auditPassRequest.setLineId(lineInfoDO.getId());
            auditPassRequest.setWorkflowSubStage(lineInfoDO.getWorkflowSubStage());
            commonService.getLineFlowService(lineInfoDO.getWorkflowSubStage()).auditPass(auditPassRequest, null);
            String redisKey = "OA:" + request.getMobile() + request.getIdCardNo();
            log.info("initiating redisKey:{},request:{}", redisKey, JSONObject.toJSONString(request));
            redisUtilPool.setString(redisKey, JSONObject.toJSONString(request));
            // TODO: 2024/6/18 企微工作通知
//            Map<String, String> requestMap = new HashMap<>();
//            requestMap.put("partnerUsername", lineInfoDO.getUsername());
//            requestMap.put("partnerMobile", lineInfoDO.getMobile());
//            requestMap.put("lineId", String.valueOf(lineInfoDO.getId()));
//            requestMap.put("submitTime", DateUtils.dateTimeNow(DateUtils.SPECIAL_DATE_START));
//            commonService.sendMessage(Collections.singletonList(lineInfoDO.getInvestmentManager()),
//                    MessageEnum.MESSAGE_30,
//                    requestMap);
            return Boolean.TRUE;

        }
        return false;
    }

    @Override
    public Boolean skipIntentAgreement(Long lineId,LoginUserInfo user) {
        log.info("skipIntentAgreement lineId:{},操作人:{}",lineId,user.getName());
        LineInfoDO lineInfo = lineInfoDAO.getLineInfo(lineId);
        if (lineInfo == null){
            throw new ServiceException(ErrorCodeEnum.LINE_ID_IS_NOT_EXIST);
        }
        if ( !WorkflowSubStageStatusEnum.SIGN_INTENT_AGREEMENT_70.getCode().equals(lineInfo.getWorkflowSubStageStatus())) {
            throw  new ServiceException(ErrorCodeEnum.LINE_STATUS_NOT_ALLOW_OPERATE);
        }
        LineInfoDO updateLine = new LineInfoDO();
        updateLine.setId(lineInfo.getId());
        updateLine.setWorkflowStage(WorkflowStageEnum.STORE.getCode());
        updateLine.setWorkflowSubStageStatus(WorkflowSubStageStatusEnum.SIGN_INTENT_AGREEMENT_125.getCode());
        updateLine.setDevelopmentManager(lineInfo.getInvestmentManager());
        updateLine.setUpdateUserId(user.getUserId());
        lineInfoDAO.updateLineInfo(updateLine);
        //初始化店铺
        shopService.initShop(lineInfo);
        return Boolean.TRUE;
    }

    private void verifyDate(InitiatingRequest request) {
        if (request.getSignStartTime() == null || request.getSignEndTime() == null) {
            throw new ServiceException(ErrorCodeEnum.TIME_NULL_FALSE);
        }
        if (request.getSignStartTime().after(request.getSignEndTime())) {
            throw new ServiceException(ErrorCodeEnum.TIME_FALSE);
        }
    }

    @Override
    public InitiatingRequest getOaDetail(String mobile, String idCardNo) {
        SigningBaseInfoDO signingBaseInfoDO = intentAgreementMapper.selectByMobile(mobile, idCardNo);
        if (signingBaseInfoDO==null){
            return null;
        }
        String redisKey = "OA:" + mobile + idCardNo;
        String responseString = redisUtilPool.getString(redisKey);
        if (StringUtils.isNotBlank(responseString)) {
            return JSONObject.parseObject(responseString, InitiatingRequest.class);
        }
        return null;
    }

    @Override
    public ResponseResult save(FranchiseeSaveRequest request, LoginUserInfo user) throws ApiException {
        log.info("save request:{}", JSONObject.toJSONString(request));
        if (Objects.isNull(request)) {
            throw new ServiceException(ErrorCodeEnum.PARAMS_VALIDATE_ERROR);
        }

        String lockKey = "saveFranchise:" + request.getLineId();
        String lockValue = UUID.randomUUID().toString();
        boolean acquired = false;
        try {
            acquired = redisUtilPool.setNxExpire(lockKey, lockValue, CommonConstants.TEN_SECONDS);
            if (Boolean.TRUE.equals(acquired)) {
                Map<String, Object> requestMap = new HashMap<>();
                fillSignatureInfo(requestMap);
                String url = xfsgUrl + Constants.FRANCHISEE_STORE_NUM + "?timestamp=" + requestMap.get("timestamp") + "&signature=" + requestMap.get("signature");
                FranchiseeDO franchiseeDO = request.toFranchiseeDO();
                //查银行信息
                LinePayDO linePayDO = linePayMapper.getLinePayByLineId(request.getLineId());
                if (Objects.isNull(linePayDO)) {
                    throw new ServiceException(ErrorCodeEnum.LINE_PAY_FALSE);
                }
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String dateString = sdf.format(linePayDO.getPayTime());
                franchiseeDO.setPayDateStr(dateString);
                franchiseeDO.setRetAccount(ReceivingBankEnum.XFSG_RECEIVING_BANK.getAccountNum());
                franchiseeDO.setBank(linePayDO.getBankCode());
                franchiseeDO.setBankSub(linePayDO.getBranchBankCode());
                //查城市信息
                LineInfoDO lineInfoDO = lineInfoMapper.getByLineId(request.getLineId());
                if (Objects.isNull(lineInfoDO)) {
                    throw new ServiceException(ErrorCodeEnum.LINE_ID_IS_NOT_EXIST);
                }
                if (StringUtil.isNotBlank(lineInfoDO.getPartnerNum())) {
                    throw new ServiceException(ErrorCodeEnum.DUPLICATE_SUBMISSION);
                }
                if (lineInfoDO.getPartnerNum() != null) {
                    return new ResponseResult(200000, null, null);
                }
                if ("1".equals(lineInfoDO.getSex())) {
                    franchiseeDO.setSex(1);
                } else if ("2".equals(lineInfoDO.getSex())) {
                    franchiseeDO.setSex(0);
                }
                HyOpenAreaInfoDO openAreaInfoDO = openAreaInfoMapper.selectById(lineInfoDO.getWantShopAreaId());
                franchiseeDO.setProvinceCode(String.valueOf(openAreaInfoDO.getParentId()));
                franchiseeDO.setCityCode(String.valueOf(openAreaInfoDO.getId()));
                franchiseeDO.setOperator(user.getJobNumber());
                QualificationsInfoDO qualificationsInfoDO = qualificationsInfoDAO.getByLineId(lineInfoDO.getId());
                //如果是企业加盟，需要传有效期和法人
                if (Objects.nonNull(qualificationsInfoDO) && Constants.TWO_INTEGER.equals(qualificationsInfoDO.getJoinType())) {
                    SigningBaseInfoDO signingBaseInfoDO = intentAgreementMapper.selectByPartnerIdOrLineId(null, lineInfoDO.getId());
                    BusinessLicenseInfoVO businessLicenseInfo = aliyunService.getBusinessLicenseInfo(signingBaseInfoDO.getBusinessLicense());
                    franchiseeDO.setBusinessTerm(businessLicenseInfo.getValidPeriod());
                    franchiseeDO.setLegalPerson(businessLicenseInfo.getLegalPerson());
                }
                InitiatingResponse initiatingResponse = httpRestTemplateService.postForObject(url, franchiseeDO, InitiatingResponse.class);
                //更新线索(进入蓄水池并回填加盟商编码)
                if (initiatingResponse.getCode() == 0) {
                    LineInfoDO lineInfoParam = new LineInfoDO();
                    lineInfoParam.setId(request.getLineId());
                    //蓄水池
                    lineInfoParam.setJoinStatus(1);
                    lineInfoParam.setPartnerNum(initiatingResponse.getData());
                    lineInfoMapper.updateByPrimaryKeySelective(lineInfoParam);
                }
                if (initiatingResponse.getCode() != 0) {
                    lineInfoMapper.updateByPrimaryKeySelective(lineInfoDO);
                    return new ResponseResult(500, initiatingResponse.getMessage(), initiatingResponse.getData());
                } else {
                    return new ResponseResult(200000, initiatingResponse.getMessage(), initiatingResponse.getData());
                }
            } else {
                throw new ServiceException(ErrorCodeEnum.DUPLICATE_SUBMISSION);
            }
        } finally {
            if (Boolean.TRUE.equals(acquired)) {
                String currentValue = redisUtilPool.getString(lockKey);
                if (lockValue.equals(currentValue)) {
                    redisUtilPool.delKey(lockKey);
                }
            }
        }
    }

    @Override
    public Boolean auditResult(AuditResultRequest request) {
        String kdzBusinessId = request.getKdzBusinessId();
        String lineId = getLineId(kdzBusinessId);
        String redisKey = "kdzBusinessId:" + kdzBusinessId;
        if (StringUtil.isBlank(lineId)) {
            throw new ServiceException(ErrorCodeEnum.BUSINESS_ID_NOT_EXIST);
        }
        LineInfoDO lineInfoDO = lineInfoMapper.getByLineId(Long.valueOf(lineId));
        if (Objects.isNull(lineInfoDO)) {
            throw new ServiceException(ErrorCodeEnum.LINE_ID_IS_NOT_EXIST);
        }
        String auditResult = redisUtilPool.getString(redisKey);
//        if (WorkflowSubStageStatusEnum.SIGN_INTENT_AGREEMENT_70.getCode().equals(lineInfoDO.getWorkflowSubStageStatus())) {
//            //鲜丰系统不稳定，会出现调用成功但内部状态未更改的情况，这时直接返回true即可
//            return true;
//        }
        if (request.getAuditResult() == 1) {
            AuditPassRequest auditPassRequest = new AuditPassRequest();
            auditPassRequest.setLineId(lineInfoDO.getId());
            auditPassRequest.setPassReason(request.getCause());
            auditPassRequest.setWorkflowSubStage(lineInfoDO.getWorkflowSubStage());
            commonService.getLineFlowService(auditPassRequest.getWorkflowSubStage()).auditPass(auditPassRequest, null);
        } else if (request.getAuditResult() == 0) {
            AuditRejectRequest auditRejectRequest = new AuditRejectRequest();
            auditRejectRequest.setLineId(lineInfoDO.getId());
            auditRejectRequest.setWorkflowSubStage(lineInfoDO.getWorkflowSubStage());
            auditRejectRequest.setRejectPublicReason(request.getCause());
            auditRejectRequest.setRejectRealReason(request.getFailureCause());
            commonService.getLineFlowService(auditRejectRequest.getWorkflowSubStage()).auditReject(auditRejectRequest, null);
        }
        redisUtilPool.setString(redisKey, JSONObject.toJSONString(request.getAuditResult()));
        return true;
    }

    private String getLineId(String kdzBusinessId) {
        return kdzBusinessId.substring(kdzBusinessId.indexOf("_") + 1, kdzBusinessId.lastIndexOf("_"));
    }

    private void fillSignatureInfo(Map<String, Object> requestMap) {
        long timestamp = System.currentTimeMillis();
        String signature = SecureUtil.getSignature(timestamp);
        requestMap.put("timestamp", timestamp);
        requestMap.put("signature", signature);
    }
}
