package com.tzy.base.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.tzy.base.dto.*;
import com.tzy.base.mapper.SysBaseMapper;
import com.tzy.base.service.SysBaseService;
import com.tzy.common.constant.Constants;
import com.tzy.common.core.domain.entity.SysDictData;
import com.tzy.common.exception.ServiceException;
import com.tzy.common.utils.AddressResolutionUtil;
import com.tzy.common.utils.DateUtils;
import com.tzy.common.utils.NoticeType;
import com.tzy.common.utils.StringUtils;
import com.tzy.common.utils.bean.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 */
@Slf4j
@Service
public class SysBaseServiceImpl implements SysBaseService {

    @Autowired
    private SysBaseMapper sysBaseMapper;

    @Override
    public List<String> selectPayType(String type ,String status){
        return sysBaseMapper.selectPayType("pay_type", "0");
    }

    /**
     * 退款
     * @param orderNo
     */
    @Override
    public void refundBack(String orderNo){
        OrderBaseInfoDto orderInfo = sysBaseMapper.selectOrderInfoByCode(orderNo);
        //根据订单编号查询订单信息
        List<SysFinanceDto> sysFinances = sysBaseMapper.getFinanceByOrderNo(orderNo,null);
        if(!sysFinances.isEmpty()){
            SysFinanceDto sysFinance = sysFinances.get(0);
            List<SysFinanceDto> collect = sysFinances.stream().filter(finance -> Constants.FINANCE_TYPE_RETURN.equals(finance.getType())).collect(Collectors.toList());
            sysFinance.setType(Constants.FINANCE_TYPE_RETURN);
            int i = 0;
            BigDecimal refundPrice = sysFinance.getRefundFee();
            if(null != collect && collect.size() > 0){
                sysFinance = collect.get(0);
                refundPrice = sysFinance.getRefundFee();
                BigDecimal refundFee = orderInfo.getRefundFee();
                sysFinance.setRefundFee(refundFee);
                i = sysBaseMapper.updateSysFinance(sysFinance);
                if(null != refundFee){
                    refundPrice = refundFee.subtract(refundPrice);
                }
            }else{
                insertSysFinceByOrder(orderInfo,"退款");
            }
            log.info("添加财务退款记录订单编码【{}】{}",orderNo,((i > 0)?"成功":"失败"));
            OrderBaseInfoDto orderInfos = sysBaseMapper.selectOrderInfoByCode(sysFinance.getOrderNo());
            AppUserInfoDtos user = sysBaseMapper.searchUserInfoById(sysFinance.getUserId());
            // 减积分
            refundPrice=refundPrice==null?orderInfos.getActualPayment():refundPrice;
            int points = 0-refundPrice.multiply(new BigDecimal(100)).intValue();
            sysBaseMapper.addVipPoint(points, points, sysFinance.getUserId().intValue());
            //增加积分明细记录
            UserPointRecordDto pointRecord = new UserPointRecordDto();
            pointRecord.setChangePoint(points);
            pointRecord.setUserId(orderInfos.getUserId());
            pointRecord.setOrderId(orderInfos.getId());
            pointRecord.setLastPoint(Long.valueOf(user.getPoint()));
            pointRecord.setCurrPoint(Long.valueOf(user.getPoint()+points));
            pointRecord.setCreateTime(new Date());
            sysBaseMapper.insertAppUserPointRecord(pointRecord);
            //退款通知
            payReturnNotice(sysBaseMapper.selectOrderInfoByCode(orderNo));
        }else{
            insertSysFinceByOrder(orderInfo,"支付");
            insertSysFinceByOrder(orderInfo,"退款");
        }

    }
    // 退款通知
    private void payReturnNotice(OrderBaseInfoDto orderInfo) {
        SysNoticeRecordDto noticeRecord = new SysNoticeRecordDto();
        if("shop".equals(orderInfo.getOrderType())){
            noticeRecord.setFromUser("HOBBY STOCKS");
            noticeRecord.setTitle("退款申请");
            //noticeRecord.setCode(RandomUtil.getRandom(RandomUtil.SYS_NOTICE));
            noticeRecord.setToUserid(orderInfo.getUserId());
            noticeRecord.setToUser(orderInfo.getNickname());
            noticeRecord.setContentId(orderInfo.getId());
            noticeRecord.setMsg("您好！您购买的[编号为:" + orderInfo.getOrderNo() + "]退款已完成,请注意查收！");
            noticeRecord.setType(NoticeType.PAY_RETURN);
            noticeRecord.setContentUrl(Constants.MALL_ORDER_DETAIL_URL+orderInfo.getId());
        }else {
            String title = orderInfo.getStatus() == 205L ? "已完成退款" : "已申请退款"; //判断退款状态
            noticeRecord.setFromUser("HOBBY STOCKS");
            noticeRecord.setTitle(title);
            //noticeRecord.setCode(RandomUtil.getRandom(RandomUtil.SYS_NOTICE));
            noticeRecord.setToUserid(orderInfo.getUserId());
            noticeRecord.setToUser(orderInfo.getNickname());
            noticeRecord.setContentId(orderInfo.getId());
            noticeRecord.setMsg("您好！[编号为:" + orderInfo.getOrderNo() + "]的订单" + title + ",请注意查收！");
            noticeRecord.setType(NoticeType.PAY_RETURN);
        }
        if (orderInfo.getStatus() == 205L || orderInfo.getStatus() == 204L) {//判断退款状态是否添加记录
            if (!checkNoticeSend(noticeRecord.getToUserid(), noticeRecord.getType())) {
                return;
            }
            noticeRecord.setCreateTime(DateUtils.getNowDate());
            sysBaseMapper.insertSysNoticeRecord(noticeRecord);
        }
    }
    /**
     *
     * @param orderInfo
     * @param type
     */
    public void insertSysFinceByOrder(OrderBaseInfoDto orderInfo,String type) {
        if(orderInfo==null || StringUtils.isEmpty(type)){
            return;
        }
        synchronized(this){
            List<SysFinanceDto> sysFinanceDtos = sysBaseMapper.getFinanceByOrderNo(orderInfo.getOrderNo(),type);
            boolean isNew=false;
            SysFinanceDto sysFinance = new SysFinanceDto();
            if(null != sysFinanceDtos && sysFinanceDtos.size() > 0){
                sysFinance = sysFinanceDtos.get(0);
            }else{
                isNew=true;
            }
            BeanUtils.copyProperties(orderInfo, sysFinance);
            //查询用户信息
            AppUserInfoDtos appBaseUser = sysBaseMapper.searchUserInfoById(sysFinance.getUserId());
            if(null != appBaseUser){
                sysFinance.setUserName(appBaseUser.getNickname());
                sysFinance.setUserPhone(appBaseUser.getPhone());
            }
            sysFinance.setType(type);
            if(isNew){
                sysFinance.setCreateTime(DateUtils.getNowDate());
                sysBaseMapper.insertSysFinance(sysFinance);
            }else{
                sysFinance.setUpdateTime(DateUtils.getNowDate());
                sysBaseMapper.updateSysFinance(sysFinance);
            }
            log.info("新增:{},财务对账记录,订单编码【{}】,类型:{}",isNew,orderInfo.getOrderNo(),type);
        }
    }


    public AppUserInfoDtos searchUserInfoById(Long id){
        return sysBaseMapper.searchUserInfoById(id);
    }

    /**
     * 验证用户权限
     * @param userId
     * @param type
     * @return
     */
    public boolean checkNoticeSend(Long userId, String type) {
        AppUserInfoDtos user = sysBaseMapper.searchUserInfoById(userId);
        if (user == null) {
            return false;
        }
        if (org.apache.commons.lang3.StringUtils.isEmpty(user.getNotifyType()) || Arrays.asList(user.getNotifyType().split(",")).contains(type)) {
            return true;
        }
        return false;
    }

    /**
     *
     * @param username
     * @return
     */
    @Override
    public SysMerchantDto selectMerchantInfo(String username){
        return sysBaseMapper.selectMerchantInfo(username);
    }

    @Override
    public String getAppMenuByCode (String code) {
        return sysBaseMapper.getAppMenuByCode(code);
    }

    @Override
    public MerchantDto selectMerchantInfoByid(Long id){
        return sysBaseMapper.selectMerchantInfoByid(id);
    }

    @Override
    public AddressInfoDto searchAddressById(Integer id){
        return sysBaseMapper.searchAddressById(id);
    }

    @Override
    public List<DictBaseDto> selectDictData(String type,String key){
        return sysBaseMapper.selectDictDataByType(type,key);
    }
    @Override
    public List<DictBaseDto> selectDictDataByLabel(String type,String key){
        return sysBaseMapper.selectDictDataByLabel(type,key);
    }
    @Override
    public List<DictBaseDto> selectDictDataByDictType(String type){
        return sysBaseMapper.selectDictDataByDictType(type);
    }
    @Override
    public ExpresPriceDto selectOneExpresPriceRules(String appid,String fromProvince ,String toProvince){
        ExpresPriceDto expresPriceDto = new ExpresPriceDto();
        expresPriceDto.setAppid(appid);
        expresPriceDto.setFromProvince(AddressResolutionUtil.provinceResolution(fromProvince));
        expresPriceDto.setToProvince(AddressResolutionUtil.provinceResolution(toProvince));
        List<ExpresPriceDto> expresPriceDtos = sysBaseMapper.selectExpresPriceRules(expresPriceDto);
        return null != expresPriceDtos && expresPriceDtos.size() > 0 ? expresPriceDtos.get(0): null;
    }
    @Override
    public List<ExpresPriceDto> selectExpresPriceRulesV2(ExpresPriceDto expresPriceDto){
        return sysBaseMapper.selectExpresPriceRulesV2(expresPriceDto);
    }
    @Override
    public int addUserBankInfo(BankInfoDto bankInfoDto){
        return sysBaseMapper.addUserBankInfo(bankInfoDto);
    }
    @Override
    public int bandUserBankInfo(BankInfoDto bankInfoDto){
        return sysBaseMapper.bandUserBankInfo(bankInfoDto);
    }
    @Override
    public int unbandUserBankInfo(BankInfoDto bankInfoDto){
        return sysBaseMapper.unbandUserBankInfo(bankInfoDto);
    }

    @Override
    public BankInfoDto selectUserBankInfoById(Integer userId,Integer id){
        return sysBaseMapper.selectUserBankInfoById(userId,id);
    }

    @Override
    public BankInfoDto selectUserRechargeAccountInfo(BankInfoDto bankInfoDto){
        return sysBaseMapper.selectUserRechargeAccountInfo(bankInfoDto);
    }
    @Override
    public BankInfoDto selectUserBankInfoByAccount(BankInfoDto bankInfoDto){
        return sysBaseMapper.selectUserBankInfoByAccount(bankInfoDto);
    }
    @Override
    public BankInfoDto selectMerchantInfoByAccount(BankInfoDto bankInfoDto){
        return sysBaseMapper.selectMerchantInfoByAccount(bankInfoDto);
    }

    @Override
    public List<BankInfoDto> selectUserBankInfoByUserId(Integer userId,Integer status,String type){
        return sysBaseMapper.selectUserBankInfoByUserId(userId,status,type);
    }

    @Override
    public List<BankInfoDto> getBankList(Integer userId,Integer status,String type){
        List<BankInfoDto> bankInfoDtos = sysBaseMapper.selectUserBankInfoByUserId(userId, status,type);
        bankInfoDtos.forEach(item->{//脱敏
            item.setBankNo(item.desensitization());
        });
        return bankInfoDtos;
    }

    @Override
    public List<BankInfoDto> selectUserBankInfo(BankInfoDto bankInfoDto){
            return sysBaseMapper.selectUserBankInfo(bankInfoDto);
    }

    @Override
    public ChecklistBaseConfigDto selectChecklistBaseConfigAndPrice (Integer id){
        ChecklistBaseConfigDto checklistBaseConfigDto = sysBaseMapper.selectChecklistBaseConfigAndPrice(id);
//        if(null != checklistBaseConfigDto && StringUtils.isNotEmpty(checklistBaseConfigDto.getBaseConfig()) && null != checklistBaseConfigDto.getBasePrice() ){
//            return checklistBaseConfigDto;
//        }
//        return null;
        return checklistBaseConfigDto;
    }
    @Override
    public ChecklistBaseConfigDto selectChecklistBaseConfigAndPriceV2 (Integer id){
        return Optional.ofNullable(sysBaseMapper.selectChecklistBaseConfigAndPriceV2(id)).orElse(new ChecklistBaseConfigDto());
    }
    @Override
    public Integer selectChecklistBaseCustom (Integer id){
        Integer custom = sysBaseMapper.selectChecklistBaseCustom(id);
        return null == custom? 0: custom ;
    }
    /**
     * 验证商家快递权限
     * @return
     */
    public List<DictBaseDto> checkMerchantExpressAuth(Integer id ,String level ){
        List<DictBaseDto> merAuth = selectDictData(Constants.stop_courier_mer, id.toString());
        if(null != merAuth && merAuth.size() > 0){
            throw new ServiceException("没有该权限，请联系客服【快递权限停用】！");
        }
        if(StringUtils.isEmpty( level)){
            throw new ServiceException("没有该权限，请联系客服【快递权限】！");
        }
        return selectDictData(Constants.express_level_type, level);
    }

    /**
     * 验证商家快递权限 - v2
     * @param id
     * @param level
     * @return
     */
    public MerchantExpressConfigDto checkMerchantExpressAuthV2(Integer id ,String level ){
        List<DictBaseDto> merAuth = selectDictData(Constants.stop_courier_mer, id.toString());
        if(null != merAuth && merAuth.size() > 0){
            throw new ServiceException("没有该权限，请联系客服【快递权限停用】！");
        }
        if(StringUtils.isEmpty( level)){
            throw new ServiceException("没有该权限，请联系客服【快递权限】！");
        }
        MerchantExpressConfigDto merchantExpressConfigDto = new MerchantExpressConfigDto();
        final String[] type = {"baoli"};
        //判断该商家使用的快递平台 默认baoli
        try{
            //根据商家id查询 tzy_merchant_detail  type = express_platform[快递平台] or express_limit[快递额度]
            List<DictBaseDto> sysDictData = sysBaseMapper.selectDictDataByDictType("merchant_detail_type");
            if(CollectionUtils.isNotEmpty(sysDictData)){
                List<DictBaseDto> express = sysDictData.stream()
                                                       .filter(item -> StringUtils.isNotBlank(item.getKey()))
                                                       .filter(item -> item.getKey().contains("express"))
                                                       .collect(Collectors.toList());
                Set<String> columnNames = express.stream()
                                                 .map(DictBaseDto::getKey)
                                                 .collect(Collectors.toSet());
                //查询商家已经存在的 快递配置
                List<MerchantDetailDto> merchantDetailDtos = sysBaseMapper.selectByMerchantIdAndColumnNames(id, columnNames);
                if(CollectionUtils.isNotEmpty(merchantDetailDtos)){
                    merchantDetailDtos.forEach(item->{
                        if(StringUtils.isNotBlank(item.getColumnName()) && Objects.equals(item.getColumnName(), "express_platform")){
                            //如果有快递类型
                            merchantExpressConfigDto.setType(item.getColumnValue());
                        }
                        //如果有快递额度
                        if(StringUtils.isNotBlank(item.getColumnName()) && Objects.equals(item.getColumnName(), "express_limit")){
                            merchantExpressConfigDto.setExpressLimit(item.getColumnValue());
                        }
                    });
                }
            }
        } catch (Exception e) {
//            throw new ServiceException("没有该权限，请联系客服【快递权限】！");
            log.error("查询商家快递配置异常：设置默认快递配置", e);
        }
        List<DictBaseDto> dictBaseDtos = selectDictData(Constants.express_level_type, level);
        if(CollectionUtils.isNotEmpty(dictBaseDtos)){
            merchantExpressConfigDto.setRemark(dictBaseDtos.get(0).getRemark());
        }
        if(StringUtils.isBlank(merchantExpressConfigDto.getType()) || !"sfgf".equals(merchantExpressConfigDto.getType())){
            merchantExpressConfigDto.setType(type[0]);//设置默认值
        }
        return merchantExpressConfigDto;
    }

    public boolean checkPresaleTime(Integer groupInfoId){
        String presaleTimeStr = sysBaseMapper.selectChecklistBasePresaleTime(groupInfoId);
        if(StringUtils.isEmpty(presaleTimeStr)){
            return true;
        }
        try{
            JSONObject presaleTimeJSON = JSONObject.parseObject(presaleTimeStr);
            presaleTimeStr = presaleTimeJSON.getString("presaleTime");
        } catch (Exception e){
            log.error(" 解析checklist基础库预售开播时间异常，{} ",e);
            return true;
        }
        Date presaleTime = DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, presaleTimeStr);
        if(null != presaleTime && presaleTime.after(new Date())){
            throw new ServiceException("当前时间未达到设置的预售最早开播时间【"+presaleTimeStr+"】！");
        }
        return true;
    }

    public String selectChecklistBaseConfig(Long groupInfoId) {
        return sysBaseMapper.selectChecklistBaseConfig(groupInfoId);
    }

    public boolean checkPresaleTimeV2(Integer groupInfoId){
        String presaleTimeStr = sysBaseMapper.selectChecklistBasePresaleTimeV2(groupInfoId);
        if(StringUtils.isBlank(presaleTimeStr)){
            return true;
        }
        try{
            JSONObject presaleTimeJSON = JSONObject.parseObject(presaleTimeStr);
            presaleTimeStr = presaleTimeJSON.getString("presaleTime");
        } catch (Exception e){
            log.error(" 解析checklist基础库预售开播时间异常，{} ",e);
        }
        Date presaleTime = DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, presaleTimeStr);
        if(null != presaleTime && presaleTime.after(new Date())){
            throw new ServiceException("当前时间未达到设置的预售最早开播时间【"+presaleTimeStr+"】！");
        }
        return true;
    }

}
