package com.liquidnet.client.admin.zhengzai.kylin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.liquidnet.commons.lang.util.BeanUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.constant.KylinTableStatusConst;
import com.liquidnet.service.kylin.dao.KylinOrderRefundsEntitiesDao;
import com.liquidnet.service.kylin.dao.KylinOrderTicketEntitiesDao;
import com.liquidnet.service.kylin.dao.OrderRefundDao;
import com.liquidnet.service.kylin.dto.param.RefundApplyParam;
import com.liquidnet.service.kylin.dto.param.RefundSearchParam;
import com.liquidnet.service.kylin.dto.vo.admin.OrderDetailsAdminVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketEntitiesVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import com.liquidnet.service.kylin.dto.vo.returns.KylinOrderRefundsVo;
import com.liquidnet.service.kylin.dto.vo.returns.RefundOrderDetailsVo;
import com.liquidnet.service.kylin.entity.*;
import com.liquidnet.service.kylin.mapper.*;
import com.liquidnet.service.kylin.service.IKylinOrderRefundsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 订单退款表 服务实现类 处理逻辑判断
 * </p>
 *
 * @author jiangxiulong
 * @since 2021-05-26
 */
@Slf4j
@Service
public class KylinOrderRefundsServiceImpl extends ServiceImpl<KylinOrderRefundsMapper, KylinOrderRefunds> implements IKylinOrderRefundsService {
    @Autowired
    private KylinOrderTicketsMapper kylinOrderTicketsMapper;

    @Autowired
    private KylinRefundsStatusServiceImpl kylinRefundsStatusServiceImpl;

    @Autowired
    private KylinOrderRefundsMapper kylinOrderRefundsMapper;

    @Autowired
    private KylinOrderTicketStatusMapper kylinOrderTicketStatusMapper;

    @Autowired
    private KylinOrderTicketEntitiesMapper kylinOrderTicketEntitiesMapper;

    @Autowired
    private KylinOrderTicketRelationsMapper kylinOrderTicketRelationsMapper;

    @Autowired
    private KylinPerformancesMapper kylinPerformancesMapper;

    @Autowired
    MongoTemplate mongoTemplate;

    public ResponseDto refundApply(RefundApplyParam refundApplyParam) {
        String orderTicketsId = refundApplyParam.getOrderTicketsId();
        List<String> ticketEntityIds = refundApplyParam.getTicketEntityIds();
        Double RefundPriceExpress = refundApplyParam.getRefundPriceExpress();
        if (null == RefundPriceExpress) {
            RefundPriceExpress = 0.0;
        }

        KylinOrderTickets orderInfo = kylinOrderTicketsMapper.selectOne(
                new QueryWrapper<KylinOrderTickets>().eq("order_tickets_id", orderTicketsId)
        );
        KylinOrderTicketStatus orderStatus = kylinOrderTicketStatusMapper.selectOne(
                new QueryWrapper<KylinOrderTicketStatus>().eq("order_id", orderTicketsId)
        );
        int thisOrderStatus = orderStatus.getStatus();
        int thisPayStatus = orderStatus.getPayStatus();
        double priceExpress = orderInfo.getPriceExpress().doubleValue();

        // todo 转增是否能退
        // 订单状态需已付款
        if (thisOrderStatus != KylinTableStatusConst.ORDER_STATUS1) {
            return ResponseDto.failure("订单状态信息有误");
        }
        // 订单支付状态需为已支付
        if (thisPayStatus != KylinTableStatusConst.ORDER_PAY_STATUS1) {
            return ResponseDto.failure("订单支付信息有误");
        }
        // 传的快递费不能大于实际的快递费
        if (RefundPriceExpress > priceExpress) {
            return ResponseDto.failure("快递费不能大于实际的快递费");
        }
        // 该订单正在退款或已有退款
        QueryWrapper<KylinOrderRefunds> refundingCountQuery = new QueryWrapper<KylinOrderRefunds>()
                .eq("order_tickets_id", orderTicketsId)
                .ne("status", KylinTableStatusConst.ORDER_REFUND_STATUS_CANCEL);
        for (String v : ticketEntityIds) {
            refundingCountQuery.like("order_ticket_entities_ids", v);
        }
        int refundingCount = kylinOrderRefundsMapper.selectCount(refundingCountQuery);
        if (refundingCount > 0) {
            return ResponseDto.failure("该订单正在退款或已有退款");
        }

        // 选择退款的入场人是否正确
        // TODO: 2021/5/27 出票未出票不知是否要处理
        QueryWrapper<KylinOrderTicketEntities> choiceCountQuery = new QueryWrapper<KylinOrderTicketEntities>()
                .eq("order_id", orderTicketsId)
                .eq("is_payment", KylinTableStatusConst.ENTITIES_IS_PAYMENT1)
                .in("order_ticket_entities_id", ticketEntityIds);
        int choiceCount = kylinOrderTicketEntitiesMapper.selectCount(choiceCountQuery);
        int ticketEntityCount = ticketEntityIds.size();
        if (choiceCount < 0 || choiceCount != ticketEntityCount) {
            return ResponseDto.failure("入场人订单有误或不存在");
        }

        boolean res = kylinRefundsStatusServiceImpl.orderTicketRefunding(
                refundApplyParam, orderInfo, orderTicketsId,
                RefundPriceExpress, priceExpress,
                ticketEntityCount, ticketEntityIds
        );
        if (res) {
            return ResponseDto.success();
        } else {
            return ResponseDto.failure("操作失败");
        }
    }

    public ResponseDto refundCheckStatus(RefundApplyParam refundApplyParam) {
        String type = refundApplyParam.getType();
        List<String> orderRefundsIdList = refundApplyParam.getIds();
        if (orderRefundsIdList.size() <= 0) {
            return ResponseDto.failure("无退款订单");
        }
        Integer[] orderRefundStatus = null;
        Integer orderType = KylinTableStatusConst.ORDER_REFUND_TYPE_APPLY;
        switch (type) {
            default:
                return ResponseDto.failure("type类型错误");
            case "cancel":
                orderRefundStatus = new Integer[]{KylinTableStatusConst.ORDER_REFUND_STATUS_APPLY, KylinTableStatusConst.ORDER_REFUND_STATUS_REJECT, KylinTableStatusConst.ORDER_REFUND_STATUS_REFUSE};
                break;
            case "reapply":
                orderRefundStatus = new Integer[]{KylinTableStatusConst.ORDER_REFUND_STATUS_REJECT, KylinTableStatusConst.ORDER_REFUND_STATUS_REFUSE};
                break;
            case "approved":
                orderRefundStatus = new Integer[]{KylinTableStatusConst.ORDER_REFUND_STATUS_APPLY, KylinTableStatusConst.ORDER_REFUND_STATUS_REJECT, KylinTableStatusConst.ORDER_REFUND_STATUS_REFUSE};
                break;
            case "reject":
                orderRefundStatus = new Integer[]{KylinTableStatusConst.ORDER_REFUND_STATUS_APPLY, KylinTableStatusConst.ORDER_REFUND_STATUS_APPROVED, KylinTableStatusConst.ORDER_REFUND_STATUS_REFUSE};
                break;
            case "unfilled":
                orderRefundStatus = new Integer[]{KylinTableStatusConst.ORDER_REFUND_STATUS_APPROVED, KylinTableStatusConst.ORDER_REFUND_STATUS_ERROR};
                break;
            case "refuse":
                orderRefundStatus = new Integer[]{KylinTableStatusConst.ORDER_REFUND_STATUS_APPROVED, KylinTableStatusConst.ORDER_REFUND_STATUS_ERROR};
                break;
        }

        List<KylinOrderRefunds> refundList = kylinOrderRefundsMapper.selectList(
                new QueryWrapper<KylinOrderRefunds>()
                        .eq("type", orderType)
                        .in("order_refunds_id", orderRefundsIdList)
                        .in("status", orderRefundStatus)
        );
        if (orderRefundsIdList.size() != refundList.size()) {
            return ResponseDto.failure("当前状态不允许操作");
        }

        boolean res = false;
        String reject = refundApplyParam.getReject();
        String refuse = refundApplyParam.getRefuse();
        switch (type) {
            case "cancel":
                res = kylinRefundsStatusServiceImpl.orderTicketRefundCancel(refundList);
                break;
            case "reapply":
                res = kylinRefundsStatusServiceImpl.orderRefundChangeStatus(refundList, type, "", "");
                break;
            case "approved":
                res = kylinRefundsStatusServiceImpl.orderRefundChangeStatus(refundList, type, reject, "");
                break;
            case "Reject":
                res = kylinRefundsStatusServiceImpl.orderRefundChangeStatus(refundList, type, reject, "");
                break;
            case "unfilled":
                res = kylinRefundsStatusServiceImpl.orderTicketRefundUnfilled(refundList, refuse);
                break;
            case "refuse":
                res = kylinRefundsStatusServiceImpl.orderRefundChangeStatus(refundList, type, "", refuse);
                break;
        }
        if (res) {
            return ResponseDto.success();
        } else {
            return ResponseDto.failure("操作失败");
        }
    }

    public Boolean refundCompleted(RefundApplyParam refundApplyParam) {
        return false;
    }

    public KylinOrderRefundsVo detail(String orderRefundId) {
        KylinOrderRefunds data = kylinOrderRefundsMapper.selectOne(
                new QueryWrapper<KylinOrderRefunds>()
                        .eq("order_refunds_id", orderRefundId)
        );

        String orderTicketEntitiesId = data.getOrderTicketEntitiesIds();
        String[] orderTicketEntitiesIdS = orderTicketEntitiesId.split(",");
        List<KylinOrderRefundsEntitiesDao> entities = kylinOrderTicketEntitiesMapper.selectEntitiesList(orderTicketEntitiesIdS);
        for (KylinOrderRefundsEntitiesDao item : entities) {
            item.setPaymentName(item.getIsPayment());
        }

        KylinOrderRefundsVo kylinOrderRefundsVo = new KylinOrderRefundsVo();
        kylinOrderRefundsVo.setStatusName(data.getStatus());
        kylinOrderRefundsVo.setEntities(entities);
        BeanUtils.copyProperties(data, kylinOrderRefundsVo);

        return kylinOrderRefundsVo;
    }

    public PageInfo<OrderRefundDao> refundList(RefundSearchParam refundSearchParam) {
        PageInfo<OrderRefundDao> pageInfoTmp = null;
        try {
            PageHelper.startPage(refundSearchParam.getPageNum(), refundSearchParam.getPageSize());
            List<OrderRefundDao> voList = kylinOrderRefundsMapper.misRefundList(BeanUtil.convertBeanToMap(refundSearchParam));
            for (OrderRefundDao item : voList) {
                item.setStatusName(item.getStatus());
            }
            pageInfoTmp = new PageInfo(voList);
        } catch (Exception e) {
            return new PageInfo();
        }
        return pageInfoTmp;
    }

    public RefundOrderDetailsVo orderDetails(String orderCode) {
        // 订单
        KylinOrderTickets kylinOrderTickets = kylinOrderTicketsMapper.selectOne(
                new QueryWrapper<KylinOrderTickets>().eq("order_code", orderCode)
        );

        // 订单关联 获取演出id
        KylinOrderTicketRelations  kylinOrderTicketRelations = kylinOrderTicketRelationsMapper.selectOne(
                new QueryWrapper<KylinOrderTicketRelations>().eq("order_id", kylinOrderTickets.getOrderTicketsId())
        );

        // 演出
        KylinPerformances kylinPerformances = kylinPerformancesMapper.selectOne(
                new QueryWrapper<KylinPerformances>().eq("performances_id", kylinOrderTicketRelations.getPerformanceId())
        );

        List<KylinOrderTicketEntitiesDao> entitiesList = kylinOrderTicketEntitiesMapper.getRefundEntitiesList(kylinOrderTickets.getOrderTicketsId());

        KylinOrderTicketVo kylinOrderTicketVo = new KylinOrderTicketVo();
        BeanUtil.copy(kylinOrderTickets,kylinOrderTicketVo);

        KylinPerformanceVo performanceVo = new KylinPerformanceVo();
        BeanUtil.copy(kylinPerformances,performanceVo);

        /*List<KylinOrderTicketEntitiesDao> entitiesListDao = new ArrayList();
        KylinOrderTicketEntitiesDao kylinOrderTicketEntitiesDao = new KylinOrderTicketEntitiesDao();
        for (KylinOrderTicketEntitiesDao entities : entitiesList) {
            BeanUtil.copy(entities, kylinOrderTicketEntitiesDao);
            entitiesListDao.add(entities);
        }
        BeanUtil.copy(entitiesList,kylinOrderTicketEntitiesDao);*/

        RefundOrderDetailsVo refundOrderDetailsVo = new RefundOrderDetailsVo();
        refundOrderDetailsVo.setOrderTicketVo(kylinOrderTicketVo);
        refundOrderDetailsVo.setKylinPerformanceVo(performanceVo);
        refundOrderDetailsVo.setKylinOrderTicketEntitiesDao(entitiesList);

        return refundOrderDetailsVo;
    }
}
