package com.cool.store.service.impl;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import com.cool.store.constants.CommonConstants;
import com.cool.store.context.LoginUserInfo;
import com.cool.store.dao.QualificationsInfoDAO;
import com.cool.store.dao.ShopStageInfoDAO;
import com.cool.store.entity.*;
import com.cool.store.enums.*;
import com.cool.store.enums.point.ShopSubStageEnum;
import com.cool.store.enums.point.ShopSubStageStatusEnum;
import com.cool.store.exception.ServiceException;
import com.cool.store.mapper.*;
import com.cool.store.request.AddSignFranchiseRequest;
import com.cool.store.request.AuditResultRequest;
import com.cool.store.request.FranchiseAgreementRequest;
import com.cool.store.response.AddSignFranchiseResponse;
import com.cool.store.response.ResponseResult;
import com.cool.store.service.CoolStoreStartFlowService;
import com.cool.store.service.PreparationService;
import com.cool.store.service.SignFranchiseService;
import com.cool.store.utils.GeoMapUtil;
import com.cool.store.utils.RedisUtilPool;
import com.cool.store.utils.poi.DateUtils;
import com.cool.store.utils.poi.StringUtils;
import com.cool.store.utils.poi.constant.Constants;
import lombok.extern.slf4j.Slf4j;
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 SignFranchiseServiceImpl implements SignFranchiseService, AuditResultService {
    @Resource
    SignFranchiseMapper signFranchiseMapper;

    @Resource
    CoolStoreStartFlowService coolStoreStartFlowService;

    @Resource
    FranchiseFeeMapper franchiseFeeMapper;

    @Resource
    ShopInfoMapper shopInfoMapper;

    @Resource
    IntentAgreementMapper intentAgreementMapper;

    @Resource
    LinePayMapper linePayMapper;

    @Resource
    PointInfoMapper pointInfoMapper;

    @Resource
    LineInfoMapper lineInfoMapper;

    @Resource
    SystemBuildingShopMapper systemBuildingShopMapper;

    @Resource
    ApplyLicenseMapper applyLicenseMapper;

    @Resource
    ThirdDepartmentMapper thirdDepartmentMapper;

    @Resource
    JoinIntentionMapper joinIntentionMapper;

    @Resource
    ShopStageInfoDAO shopStageInfoDAO;

    @Resource
    ShopAuditInfoMapper shopAuditInfoMapper;

    @Resource
    PreparationService preparationService;

    @Resource
    CommonService commonService;

    @Resource
    RedisUtilPool redisUtilPool;
    @Resource
    QualificationsInfoDAO qualificationsInfoDAO;

    @Resource
    RegionMapper regionMapper;


    @Override
    public Boolean auditResult(AuditResultRequest request) {
        log.info("SignFranchiseServiceImpl auditResult request：{}", JSONObject.toJSONString(request));
        Long shopId = getShopId(request.getKdzBusinessId());
        ShopSubStageStatusEnum shopSubStageStatusEnum = null;
        if (request.getAuditResult() == 1) {
            shopSubStageStatusEnum = ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_84;
        } else if (request.getAuditResult() == 0) {
            shopSubStageStatusEnum = ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_85;
        }
        ShopAuditInfoDO shopAuditInfoDO = new ShopAuditInfoDO();
        shopAuditInfoDO.setShopId(shopId);
        shopAuditInfoDO.setAuditType(AuditTypeEnum.SIGN_FRANCHISE.getCode());
        shopAuditInfoDO.setSubmittedUserId("");
        shopAuditInfoDO.setSubmittedUserName("");
        if (Constants.ZERO_INTEGER.equals(request.getAuditResult())) {
            shopAuditInfoDO.setResultType(Constants.ONE_INTEGER);
            shopAuditInfoDO.setRejectReason(request.getCause());
            Map<String, String> requestMap = new HashMap<>();
            ShopInfoDO shopInfoDO = shopInfoMapper.selectByPrimaryKey(shopId);
            LineInfoDO lineInfo = lineInfoMapper.getByLineId(shopInfoDO.getLineId());
            requestMap.put("storeName", shopInfoDO.getShopName());
            requestMap.put("partnerName", lineInfo.getUsername());
            requestMap.put("partnerMobile", lineInfo.getMobile());
            requestMap.put("lineId", String.valueOf(lineInfo.getId()));
            requestMap.put("shopId", String.valueOf(shopInfoDO.getId()));
            commonService.sendMessage(Collections.singletonList(lineInfo.getInvestmentManager()), MessageEnum.MESSAGE_20, requestMap);
        } else if (Constants.ONE_INTEGER.equals(request.getAuditResult())) {
            shopAuditInfoDO.setResultType(Constants.ZERO_INTEGER);
            shopAuditInfoDO.setPassReason(request.getCause());
            //校验建店与加盟签约合同是否完成 并初始化后续流程数据
            //preparationService.contractAndBuildStoreCompletion(shopId);
        }
        shopAuditInfoMapper.insertSelective(shopAuditInfoDO);
        Long auditId = shopAuditInfoDO.getId();
        shopStageInfoDAO.updateShopStageAndAuditInfo(shopId, shopSubStageStatusEnum, auditId);
        signFranchiseMapper.updateAuditByShopId(auditId, shopId);
        return true;
    }

    private Long getShopId(String kdzBusinessId) {
        String shopId = kdzBusinessId.substring(kdzBusinessId.indexOf("_") + 1, kdzBusinessId.lastIndexOf("_"));
        return Long.valueOf(shopId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult submitSignFranchise(AddSignFranchiseRequest request, LoginUserInfo user) {
        log.info("submitSignFranchise request:{}", JSONObject.toJSONString(request));
        if (Objects.isNull(request)) {
            throw new ServiceException(ErrorCodeEnum.PARAMS_VALIDATE_ERROR);
        }
        if (Objects.isNull(request.getShopId())) {
            throw new ServiceException(ErrorCodeEnum.SHOP_ID_NOT_EXIST);
        }
        SignFranchiseDO isExist = signFranchiseMapper.selectByShopId(request.getShopId());
        if (Objects.nonNull(isExist) && Objects.isNull(request.getId())){
            throw new ServiceException(ErrorCodeEnum.DUPLICATE_SUBMISSION);
        }
        String lockKey = "submitSignFranchise:" + request.getShopId();
        //流水
        String lockValue = UUID.randomUUID().toString();
        boolean acquired = false;
        try {
            //10s过期
            acquired = redisUtilPool.setNxExpire(lockKey, lockValue, CommonConstants.TEN_SECONDS);
            if (Boolean.TRUE.equals(acquired)) {
                SignFranchiseDO signFranchiseDO = request.toSignFranchiseDO();
                if (Objects.isNull(request.getId())) {
                    signFranchiseMapper.insertSelective(signFranchiseDO);
                } else {
                    signFranchiseMapper.updateByPrimaryKeySelective(signFranchiseDO);
                }
                //店铺信息
                ShopInfoDO shopInfoDO = shopInfoMapper.selectByPrimaryKey(request.getShopId());
                shopInfoDO.setRegionId(request.getRegionId());
                shopInfoDO.setShopName(request.getShopName());
                shopInfoDO.setDetailAddress(request.getDetailAddress());
                shopInfoMapper.updateByPrimaryKeySelective(shopInfoDO);
                //更新状态为加盟商
                LineInfoDO lineInfoDO = lineInfoMapper.getByLineId(shopInfoDO.getLineId());
                //暂时去掉
                lineInfoDO.setJoinStatus(CommonConstants.TWO);
                lineInfoMapper.insertOrUpdate(lineInfoDO);
                //todo 提交之后先直接到已签约 正常是待审核
                shopStageInfoDAO.updateShopStageInfo(request.getShopId(), ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_84);
                //如果加盟合同完成 开始设计阶段与验收阶段
                preparationService.contractAndBuildStoreCompletion(request.getShopId());
                commonService.sendSms(lineInfoDO.getMobile(),SMSMsgEnum.SIGN_CONTRACT);
                return new ResponseResult(200000,"提交成功");
            } 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 AddSignFranchiseResponse getSignFranchise(Long shopId) {
        SignFranchiseDO signFranchiseDO = signFranchiseMapper.selectByShopId(shopId);
        AddSignFranchiseResponse response = from(signFranchiseDO, shopId);
        ShopAuditInfoDO shopAuditInfoDO = null;
        if (Objects.nonNull(signFranchiseDO)) {
            shopAuditInfoDO = shopAuditInfoMapper.selectByPrimaryKey(signFranchiseDO.getAuditId());
        }
        if (Objects.nonNull(shopAuditInfoDO)) {
            response.setStatus(shopAuditInfoDO.getResultType());
            if (shopAuditInfoDO.getResultType() == 0) {
                response.setResult(shopAuditInfoDO.getPassReason());
            } else {
                response.setResult(shopAuditInfoDO.getRejectReason());
            }
        }
        if (signFranchiseDO!=null){
            response.setResultTime(signFranchiseDO.getCreateTime());
        }
        return response;
    }

    public AddSignFranchiseResponse from(SignFranchiseDO signFranchiseDO,
                                         Long shopId) {
        AddSignFranchiseResponse addSignFranchiseResponse = new AddSignFranchiseResponse();
        //店铺信息
        ShopInfoDO shopInfoDO = shopInfoMapper.selectByPrimaryKey(shopId);
        //线索信息
        LineInfoDO lineInfoDO = lineInfoMapper.getByLineId(shopInfoDO.getLineId());
        //加盟问卷信息
        QualificationsInfoDO qualificationsInfoDO = qualificationsInfoDAO.getByLineId(shopInfoDO.getLineId());
        //缴费信息
        FranchiseFeeDO franchiseFeeDO = franchiseFeeMapper.selectOne(FranchiseFeeDO.builder().shopId(shopId).build());
        //线索id
        Long lineId = shopInfoDO.getLineId();
        //缴款信息
        LinePayDO linePayDO = linePayMapper.getByLineIdAndPayTypeAndShopId(lineId, 1, shopId);
        //铺位信息
        PointInfoDO pointInfoDO = pointInfoMapper.getDataByShopIdAndLineId(lineId, shopId);
        //证照办理
        LicenseTransactDO licenseTransactDO = applyLicenseMapper.selectByShopId(shopId);

        RegionDO regionInfo = regionMapper.getByRegionId(shopInfoDO.getRegionId());


        addSignFranchiseResponse.setDetailAddress(shopInfoDO.getDetailAddress());
        if (Objects.nonNull(signFranchiseDO)) {
            addSignFranchiseResponse.setId(signFranchiseDO.getId());
            addSignFranchiseResponse.setShopId(signFranchiseDO.getShopId());
            addSignFranchiseResponse.setSignType(signFranchiseDO.getSignType());
            addSignFranchiseResponse.setBrandFee(signFranchiseDO.getBrandFee());
            addSignFranchiseResponse.setIsBusinessLicense(signFranchiseDO.getIsBusinessLicense());
            addSignFranchiseResponse.setIsFoodLicense(signFranchiseDO.getIsFoodLicense());
            addSignFranchiseResponse.setContractStartTime(signFranchiseDO.getContractStartTime());
            addSignFranchiseResponse.setContractStartEndTime(signFranchiseDO.getContractEndTime());
            addSignFranchiseResponse.setImpressionNum(signFranchiseDO.getImpressionNum());
            addSignFranchiseResponse.setBusinessStartHours(signFranchiseDO.getBusinessStartHours());
            addSignFranchiseResponse.setBusinessEndHours(signFranchiseDO.getBusinessEndHours());
            addSignFranchiseResponse.setIrregularReason(signFranchiseDO.getIrregularReason());
            addSignFranchiseResponse.setRemark(signFranchiseDO.getRemark());
            addSignFranchiseResponse.setResign(signFranchiseDO.getResign());
            addSignFranchiseResponse.setMobile(signFranchiseDO.getMobile());
        } else {
            addSignFranchiseResponse.setMobile(lineInfoDO.getMobile());
        }
        addSignFranchiseResponse.setStoreName(shopInfoDO.getShopName());

        if (Objects.nonNull(regionInfo)){
            addSignFranchiseResponse.setRegionId(shopInfoDO.getRegionId());
            addSignFranchiseResponse.setRegionName(regionInfo.getName());
        }

        if (Objects.nonNull(pointInfoDO)) {
            addSignFranchiseResponse.setStoreAddress(pointInfoDO.getAddress());
            if (StringUtils.isNoneBlank(pointInfoDO.getLatitude(), pointInfoDO.getLongitude())){
                GeoMapUtil.AddressInfo addressInfo = GeoMapUtil.reverseGeoCoding(pointInfoDO.getLatitude(), pointInfoDO.getLongitude());
                addSignFranchiseResponse.setStoreProvinceCity(String.format("%s%s%s", addressInfo.getProvince(), addressInfo.getCity(), addressInfo.getDistrict()));
            }
        }
        if (Objects.nonNull(linePayDO)) {
            addSignFranchiseResponse.setPayName(linePayDO.getPayUserName());
            addSignFranchiseResponse.setBankCardNo(linePayDO.getPayAccount());
            addSignFranchiseResponse.setBank(linePayDO.getBankName());
            addSignFranchiseResponse.setSubBank(linePayDO.getBranchBankName());
            addSignFranchiseResponse.setPayDate(linePayDO.getPayTime());
        }
        if (Objects.nonNull(licenseTransactDO)) {
            addSignFranchiseResponse.setLicenseName(licenseTransactDO.getBusinessLicense());
            addSignFranchiseResponse.setOpeAddress(licenseTransactDO.getLicenseAddress());
            addSignFranchiseResponse.setOperator(licenseTransactDO.getOperator());
            addSignFranchiseResponse.setLicenseCode(licenseTransactDO.getCreditCode());
            addSignFranchiseResponse.setType(LicenseTypeEnum.match(licenseTransactDO.getLicenseType()).getMessage());
        }
        if (Objects.nonNull(lineInfoDO)) {
            addSignFranchiseResponse.setPartnerName(lineInfoDO.getUsername());
        }
        if (Objects.nonNull(qualificationsInfoDO)) {
            addSignFranchiseResponse.setIdCardNo(qualificationsInfoDO.getIdCardNo());
            addSignFranchiseResponse.setIdCardAddress(qualificationsInfoDO.getHouseholdRegistrationAddress());
        }

        if (Objects.nonNull(franchiseFeeDO)) {
            addSignFranchiseResponse.setYearFranchiseFee(franchiseFeeDO.getYearFranchiseFee());
            addSignFranchiseResponse.setBigYearFranchiseFee(Convert.digitToChinese(Integer.valueOf(franchiseFeeDO.getYearFranchiseFee())));
            addSignFranchiseResponse.setLoanMargin(franchiseFeeDO.getLoanMargin());
            addSignFranchiseResponse.setBigLoanMargin(Convert.digitToChinese(Integer.valueOf(franchiseFeeDO.getLoanMargin())));
            addSignFranchiseResponse.setFirstYearStartTime(franchiseFeeDO.getFirstYearStartTime());
            addSignFranchiseResponse.setFirstYearEndTime(franchiseFeeDO.getFirstYearEndTime());
            addSignFranchiseResponse.setFirstYearFee(franchiseFeeDO.getFirstYearFee());
            addSignFranchiseResponse.setSecondYearStartTime(franchiseFeeDO.getSecondYearStartTime());
            addSignFranchiseResponse.setSecondYearEndTime(franchiseFeeDO.getSecondYearEndTime());
            addSignFranchiseResponse.setSecondYearFee(franchiseFeeDO.getSecondYearFee());
            addSignFranchiseResponse.setThirdYearStartTime(franchiseFeeDO.getThirdYearStartTime());
            addSignFranchiseResponse.setThirdYearEndTime(franchiseFeeDO.getThirdYearEndTime());
            addSignFranchiseResponse.setThirdYearFee(franchiseFeeDO.getThirdYearFee());
            addSignFranchiseResponse.setPerformanceBond(franchiseFeeDO.getPerformanceBond());
            addSignFranchiseResponse.setBigPerformanceBond(Convert.digitToChinese(Integer.valueOf(franchiseFeeDO.getPerformanceBond())));
        }
        return addSignFranchiseResponse;
    }

    public static String getDateTimeFormat(String pattern, Date date) {
        return new SimpleDateFormat(pattern).format(date);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean rePay(Long shopId) {
        shopStageInfoDAO.updateShopStageInfo(shopId, ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_74);
        shopStageInfoDAO.updateShopStageToNotStarted(shopId, ShopSubStageEnum.SHOP_STAGE_8);
        return true;
    }

    private int timeUtils(Date time, String type) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        switch (type) {
            case "year":
                return calendar.get(Calendar.YEAR);
            case "month":
                return calendar.get(Calendar.MONTH) + 1;
            case "day":
                return calendar.get(Calendar.DAY_OF_MONTH);
            default:
                return 0;
        }

    }
}
