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

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.JsonNode;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.kylin.constant.KylinTableStatusConst;
import com.liquidnet.service.kylin.dto.vo.KylinBannersVo;
import com.liquidnet.service.kylin.dto.vo.KylinOrderTicketEntitiesVo;
import com.liquidnet.service.kylin.dto.vo.KylinOrderTicketVo;
import com.liquidnet.service.kylin.entity.*;
import com.liquidnet.service.kylin.mapper.KylinOrderRefundsMapper;
import com.liquidnet.service.kylin.mapper.KylinOrderTicketEntitiesMapper;
import com.liquidnet.service.kylin.mapper.KylinOrderTicketStatusMapper;
import com.liquidnet.service.kylin.mapper.KylinOrderTicketsMapper;
import com.liquidnet.service.kylin.utils.DataUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReturnDocument;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpException;
import org.bson.Document;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * <p>
 * 退款表 服务实现类
 * </p>
 *
 * @author jiaangxiulong
 * @since 2021-05-26
 */
@Service
public class KylinRefundsStatusServiceImpl {

    @Autowired
    private KylinOrderTicketsMapper kylinOrderTicketsMapper;

    @Autowired
    private KylinOrderTicketStatusMapper kylinOrderTicketStatusMapper;

    @Autowired
    private KylinOrderRefundsMapper kylinOrderRefundsMapper;

    @Autowired
    private KylinOrderTicketEntitiesMapper kylinOrderTicketEntitiesMapper;

    @Autowired
    MongoTemplate mongoTemplate;

    public Boolean orderTicketRefunding(String orderTicketsId, String refundData, String reason, String orderRefundBatchesId) throws HttpException {
        // 处理数据
        String authId = "434";
        String authName = "sss";
        JsonNode refundDataJson = JsonUtils.fromJson(refundData, JsonNode.class);
        JsonNode ticketEntityIds = refundDataJson.get("ticketEntityIds");
        double RefundpriceExpress = refundDataJson.get("RefundpriceExpress").doubleValue();

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

        // todo 转增是否能退

        // 订单状态需已付款
        if (thisOrderStatus != KylinTableStatusConst.ORDER_STATUS1) {
            throw new HttpException("订单状态信息有误");
        }
        // 订单支付状态需为已支付
        if (thisPayStatus != KylinTableStatusConst.ORDER_PAY_STATUS1) {
            throw new HttpException("订单支付信息有误");
        }
        // 传的快递费不能大于实际的快递费
        if (RefundpriceExpress > priceExpress) {
            throw new HttpException("快递费不能大于实际的快递费");
        }
        // 该订单正在退款或已有退款
        QueryWrapper<com.liquidnet.service.kylin.entity.KylinOrderRefunds> refundingCountQuery = new QueryWrapper<KylinOrderRefunds>()
                .eq("order_tickets_id", orderTicketsId)
                .ne("status", KylinTableStatusConst.ORDER_REFUND_STATUS_CANCEL);
        for (JsonNode v : ticketEntityIds) {
            refundingCountQuery.like("order_ticket_entities_ids", v);
        }
        int refundingCount = kylinOrderRefundsMapper.selectCount(refundingCountQuery);
        if (refundingCount > 0) {
            throw new HttpException("该订单正在退款或已有退款");
        }

        // 该订单的入场人未付款/正在退款/已退款
        // TODO: 2021/5/27 出票未出票不知是否要处理
        QueryWrapper<KylinOrderTicketEntities> notPayCountQuery = new QueryWrapper<KylinOrderTicketEntities>()
                .in("order_ticket_entities_id", ticketEntityIds)
                .in("is_payment", new Integer[]{
                        KylinTableStatusConst.ENTITIES_IS_PAYMENT0,
                        KylinTableStatusConst.ENTITIES_IS_PAYMENT2,
                        KylinTableStatusConst.ENTITIES_IS_PAYMENT3});
        int notPayCount = kylinOrderTicketEntitiesMapper.selectCount(notPayCountQuery);

        // 选择退款的入场人是否正确
        // 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) {
            throw new HttpException("入场人订单有误或不存在");
        }

        // 本次退款总金额
        // 总入场人数量 排出未付款的 用来计算单入场人的价格
        int allEntitiesCount = kylinOrderTicketEntitiesMapper.selectCount(
                new QueryWrapper<KylinOrderTicketEntities>()
                        .eq("order_id", orderTicketsId)
                        .ne("is_payment", KylinTableStatusConst.ENTITIES_IS_PAYMENT0)
        );
        double refundTotalPrice = RefundpriceExpress + ((priceActual - priceExpress) / allEntitiesCount * ticketEntityCount);

        // 更新数据
        // 订单状态表
        KylinOrderTicketStatus orderStatusTable = new KylinOrderTicketStatus();
        // TODO: 2021/5/27 事物 and 部分退款
        orderStatusTable.setStatus(KylinTableStatusConst.ORDER_STATUS3);
        kylinOrderTicketStatusMapper.update(orderStatusTable, new UpdateWrapper<KylinOrderTicketStatus>()
                .eq("order_ticket_status_id", orderTicketsId));

        KylinOrderTicketVo kylinOrderTicketVo = new KylinOrderTicketVo();
        kylinOrderTicketVo.setStatus(KylinTableStatusConst.ORDER_STATUS3);
        BasicDBObject orderObject = new BasicDBObject("$set", JSON.parse(JsonUtils.toJson(kylinOrderTicketVo)));
        Document orderDoc = mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).findOneAndUpdate(
                Query.query(Criteria.where("orderTicketsId").is(orderTicketsId)).getQueryObject(),
                orderObject,
                new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
        );
        new DataUtils().delOrderTicketRedis(orderTicketsId);


        // 入场人
        for (JsonNode v : ticketEntityIds) {
            KylinOrderTicketEntities entitiesTable = new KylinOrderTicketEntities();
            // TODO: 2021/5/27 事物 and 部分退款
            entitiesTable.setIsPayment(KylinTableStatusConst.ENTITIES_IS_PAYMENT2);
            kylinOrderTicketEntitiesMapper.update(entitiesTable, new UpdateWrapper<KylinOrderTicketEntities>()
                    .eq("order_ticket_entities_id", v));

            KylinOrderTicketEntitiesVo kylinOrderTicketEntitiesVo = new KylinOrderTicketEntitiesVo();
            kylinOrderTicketEntitiesVo.setIsPayment(KylinTableStatusConst.ORDER_STATUS3);
            BasicDBObject entitiesObject = new BasicDBObject("$set", JSON.parse(JsonUtils.toJson(kylinOrderTicketEntitiesVo)));
            Document entitiesDoc = mongoTemplate.getCollection(KylinOrderTicketEntitiesVo.class.getSimpleName()).findOneAndUpdate(
                    Query.query(Criteria.where("orderTicketEntitiesId").is(v)).getQueryObject(),
                    entitiesObject,
                    new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
            );

            new DataUtils().delOrderTicketEntitiesRedis(v.toString());
        }

        // 退款明细
        KylinOrderRefunds kylinOrderRefunds = new KylinOrderRefunds();
        String orderRefundsId = IDGenerator.nextSnowId().toString();
        kylinOrderRefunds.setOrderRefundsId(orderRefundsId);
        kylinOrderRefunds.setOrderTicketsId(orderTicketsId);
        kylinOrderRefunds.setOrderRefundBatchesId(orderRefundBatchesId);

        Integer refundCount = kylinOrderRefundsMapper.selectCount(
                new QueryWrapper<KylinOrderRefunds>()
                        .eq("order_tickets_id", orderTicketsId)
        );

        String orderRefundCode = orderInfo.getOrderCode();
        String codeNum = StringUtils.leftPad(String.valueOf(refundCount), 3, "0");
        kylinOrderRefunds.setOrderRefundCode(orderRefundCode + codeNum);
        kylinOrderRefunds.setPrice(BigDecimal.valueOf(refundTotalPrice));
        kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_APPLY);
        kylinOrderRefunds.setType(0);
        kylinOrderRefunds.setApplicantId(authId);
        kylinOrderRefunds.setApplicantName(authName);
        kylinOrderRefunds.setApplicantAt(LocalDateTime.now());
        kylinOrderRefunds.setReason(reason);
        // TODO: 2021/5/27 判断tyoe
        if (RefundpriceExpress > 0) {
            kylinOrderRefunds.setRefundType("all");
        } else {
            kylinOrderRefunds.setRefundType("ticket");
        }
        kylinOrderRefunds.setOrderTicketEntitiesIds(ticketEntityIds.toString());
        kylinOrderRefunds.setCreatedAt(LocalDateTime.now());

        return true;
    }
}
