package cn.pluss.platform.merchantIncome.impl;

import cn.pluss.platform.api.PageInfo;
import cn.pluss.platform.dto.LeshuaBillsDTO;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.mapper.*;
import cn.pluss.platform.merchant.StaffPermissionService;
import cn.pluss.platform.merchantChannel.MerchantChannelService;
import cn.pluss.platform.merchantChannelStatus.MerchantChannelStatusService;
import cn.pluss.platform.merchantIncome.MerchantIncomeService;
import cn.pluss.platform.userApp.UserAppService;
import cn.pluss.platform.util.PageUtils;
import cn.pluss.platform.util.StringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;

@RequiredArgsConstructor
@Service
public class MerchantIncomeServiceImpl extends ServiceImpl<MerchantIncomeMapper, MerchantIncome> implements MerchantIncomeService {

    private final MakeMoneyMapper makeMoneyMapper;

    private final UserAppMapper userAppMapper;
    private final MerchantBaseInfoMapper merchantBaseInfoMapper;
    private final MerchantOrderMapper merchantOrderMapper;

    @Setter(onMethod_ = {@Lazy, @Autowired})
    private UserAppService userAppService;

    private final MerchantChannelStatusService mcsService;

    private final MerchantChannelService merchantChannelService;

    @Autowired
    private StaffPermissionService staffPermissionService;

    @Override
    public PageInfo<MakeMoney> queryLeshuaBills(LeshuaBillsDTO leshuaBillsDTO) throws ParseException {
        int size = 20;

        if (leshuaBillsDTO.getPageNo() == null || leshuaBillsDTO.getPageNo() == 0) {
            leshuaBillsDTO.setPageNo(1);
        }

        UserApp uaToken = userAppService.queryUserAppByToken();
        if ("staff".equals(uaToken.getUserType()) && !"1".equals(uaToken.getPermissionBill()))  {
            return new PageInfo<>(0L, 1L, 1L, 10L, new ArrayList<>());
        }

        LambdaQueryWrapper<MerchantChannelStatus> qW = Wrappers.lambdaQuery();
        qW.select(MerchantChannelStatus::getMerchantId);
        qW.eq(MerchantChannelStatus::getMerchantCode, uaToken.getMerchantCode())
                .in(MerchantChannelStatus::getStatus, MerchantChannelStatus.AUDIT_STATUS_SUCCESS, MerchantChannelStatus.AUDIT_STATUS_DATA_EDIT);

        List<Map<String, Object>> merchantIdListMap = mcsService.listMaps(qW);
        if (merchantIdListMap.size() == 0) {
            Page<MakeMoney> page = new Page<>(leshuaBillsDTO.getPageNo(), size);
            return PageUtils.page(page);
        }

        List<String> merchantIdList = new ArrayList<>();
        for (Map<String, Object> merchantId : merchantIdListMap) {
            if (merchantId != null && merchantId.get("merchantId") != null) {
                merchantIdList.add((String) merchantId.get("merchantId"));
            }
        }

        Page<MakeMoney> page = new Page<>(leshuaBillsDTO.getPageNo(), size);
        QueryWrapper<MakeMoney> queryWrapper = new QueryWrapper<>();
        List<MerchantChannel> list;
        if (!"staff".equals(uaToken.getUserType())) {
            queryWrapper.and(wrapper ->
                    wrapper.eq("nrr.userId", uaToken.getUserId())
                    .or().isNull("nrr.userId"));
        }

        queryWrapper.in("mm.merchantId", merchantIdList);
        queryWrapper.orderByDesc("mm.createTime");
        page = makeMoneyMapper.selectPage(page, queryWrapper);
        list = merchantChannelService.list();

        LambdaQueryWrapper<MerchantChannelStatus> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(MerchantChannelStatus::getMerchantCode, uaToken.getMerchantCode());
        lambdaQueryWrapper.eq(MerchantChannelStatus::getMerchantId, leshuaBillsDTO.getMerchantId());
        MerchantChannelStatus merchantChannelStatus = mcsService.getOne(lambdaQueryWrapper);

        if (merchantChannelStatus == null) {
            throw new MsgException("商编异常");
        }

        for (MakeMoney l : page.getRecords()) {
            l.setRealAmount(StringUtil.bigDecimal(l.getRealAmount() * 0.01));
            l.setSuspendAmount(StringUtil.bigDecimal(l.getSuspendAmount() * 0.01));
            l.setPlanAmount(StringUtil.bigDecimal(l.getPlanAmount() * 0.01));

            for (MerchantChannel merchantChannel: list) {
                if (merchantChannelStatus.getChannel().equals(merchantChannel.getId())) {
                    l.setChannelName(merchantChannel.getChannelName());
                }
            }

            if ("staff".equals(uaToken.getUserType())) {
                l.setReadStatus(1);
            }
        }

        LambdaQueryWrapper<UserApp> lambdaQueryWrapper2 = Wrappers.lambdaQuery();
        lambdaQueryWrapper2.eq(UserApp::getMerchantCode, merchantChannelStatus.getMerchantCode());
        lambdaQueryWrapper2.eq(UserApp::getUserType, "promoter");
        UserApp userApp = userAppMapper.selectOne(lambdaQueryWrapper2);

        if (page.getRecords().size() == 0) {
            return PageUtils.page(page);
        }

        String start = page.getRecords().get(page.getRecords().size() - 1).getCreateTime();
        String end = page.getRecords().get(0).getCreateTime();

        FastDateFormat dateFormat = FastDateFormat.getInstance("yyyy-MM-dd", Locale.CHINA);
        Date startTime = dateFormat.parse(start);
        startTime = DateUtils.addDays(startTime, -1);
        Date endTime = dateFormat.parse(end);

        setDailyCount(startTime, endTime, userApp.getMerchantCode(), page.getRecords());

        return PageUtils.page(page);
    }

    @Override
    public Map<String, Object> queryTotalEnterFee(String merchantCode, String startTime, String endTime) {
        if (merchantCode == null || StringUtil.isEmpty(merchantCode)) {
            UserApp tokenUa = userAppService.queryUserAppByToken();
            merchantCode = tokenUa.getMerchantCode();
        }
        MerchantBaseInfo queryMerchantBaseInfo = new MerchantBaseInfo();
        queryMerchantBaseInfo.setMerchantCode(merchantCode);
        queryMerchantBaseInfo = merchantBaseInfoMapper.queryMerchantBaseInfo(queryMerchantBaseInfo);
        if (queryMerchantBaseInfo == null) {
            throw new MsgException("该商家不存在！");
        }
        //校验日期格式是否正确
        if (!cn.pluss.platform.util.DateUtils.isDate(startTime, "yyyy-MM-dd")) {
            throw new MsgException("开始时间格式不正确！");
        }
        if (!cn.pluss.platform.util.DateUtils.isDate(endTime, "yyyy-MM-dd")) {
            throw new MsgException("结束时间格式不正确！");
        }

        QueryWrapper<MerchantOrder> queryWrapper = new QueryWrapper<MerchantOrder>()
                .between("updateTime", startTime + " 00:00:00", endTime + " 23:59:59")
                .eq("merchantCode", merchantCode)
                .ne("settlementType", 0)
                .in("status", "1", "2");

        Map<String, Object> sumMap = merchantOrderMapper.getSumEnterFee(queryWrapper);

        BigDecimal totalIncomeFee = new BigDecimal(sumMap.get("fee").toString());

        // 返回参数
        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("totalIncomeFee", totalIncomeFee);

        return returnMap;
    }

    @Override
    public List<MerchantIncome> queryLastFiveMerchantIncome2(UserApp userApp) {
        UserApp tokenUa = userAppService.queryUserAppByToken();

        // step 1. 查出最后五条收款记录
        MerchantOrder merchantOrder = new MerchantOrder()
                .setMerchantCode(userApp.getMerchantCode())
                .setStatus("1");
        LambdaQueryWrapper<MerchantOrder> queryWrapper = Wrappers.lambdaQuery(merchantOrder);
        queryWrapper.orderByDesc(MerchantOrder::getCreateDt)
                .last("limit 5");

        if ("staff".equals(tokenUa.getUserType())) {
            StaffPermission entity = staffPermissionService.getEntity(tokenUa.getUserId(), userApp.getMerchantCode());
            if ("0".equals(entity.getPermissionBill())) {
                queryWrapper.eq(MerchantOrder::getStaffCode, tokenUa.getUserId());
            }
        }

        List<MerchantOrder> merchantOrderList = merchantOrderMapper.selectList(queryWrapper);

        // step 2. 将merchantOrder信息转换成merchantIncome
        List<MerchantIncome> result = new ArrayList<>();
        for (MerchantOrder item : merchantOrderList) {
            MerchantIncome merchantIncome = new MerchantIncome();
            merchantIncome.setMerchantCode(item.getMerchantCode());
            merchantIncome.setMerchantName(item.getMerchantName());
            merchantIncome.setStoreName(item.getStoreName());
            merchantIncome.setStoreId(item.getStoreId());
            merchantIncome.setDealFee(item.getConsumeFee());
            // TODO 这里暂定为交易金额，因为已存在数据库的消息记录里面都是这样的数据
            merchantIncome.setIncomeFee(item.getConsumeFee());
            merchantIncome.setCreateTime(item.getUpdateTime());
            merchantIncome.setPayTypeCode(item.getPayTypeCode());
            merchantIncome.setDealCode(item.getOrderNumber());

            if (MerchantOrder.isVipRecharge(item)) {
                merchantIncome.setPayTypeName("会员充值");
            } else {
                String payTypeName = item.getPayTypeName();
                payTypeName = payTypeName.replaceAll("随行付|随行|乐刷|支付$", "");
                merchantIncome.setPayTypeName(payTypeName);
            }

            result.add(merchantIncome);
        }

        return result;
    }

    /**
     * 查询每日的总流水，并放入结果集中
     *
     * @param start        开始时间
     * @param end          截止时间
     * @param merchantCode 店铺code
     * @param targetList   结算信息
     */
    private void setDailyCount(Date start, Date end, String merchantCode, List<MakeMoney> targetList) {
        List<Map<String, Object>> dailyCountList = merchantOrderMapper.queryDailyCount(merchantCode, start, end);

        for (MakeMoney makeMoney : targetList) {
            for (Map<String, Object> dailyCount : dailyCountList) {
                java.lang.String billDate = makeMoney.getCreateTime().substring(0, 10);
                String dailyDate;
                if (dailyCount.get("date") instanceof byte[]) {
                    dailyDate = new String((byte[]) dailyCount.get("date"));
                } else {
                    dailyDate = dailyCount.get("date").toString();
                }

                if (billDate.equals(dailyDate)) {
                    makeMoney.setConsumeFeeSum(BigDecimal.valueOf((double) dailyCount.get("consumeFeeSum")));
                    dailyCountList.remove(dailyCount);
                    break;
                }
            }
        }
    }
}

