package com.neusoft.smart.pos.order.controller;

import com.neusoft.smart.pos.constants.DictionaryConstant;
import com.neusoft.smart.pos.dto.order.request.*;
import com.neusoft.smart.pos.dto.order.response.*;
import com.neusoft.smart.pos.dto.trade.request.PostRefundRequest;
import com.neusoft.smart.pos.dto.trade.response.PostRefundResponse;
import com.neusoft.smart.pos.framework.constants.ApplicationConstants;
import com.neusoft.smart.pos.dto.payorder.request.PutDoRefundRequest;
import com.neusoft.smart.pos.dto.payorder.response.PutDoRefundResponse;
import com.neusoft.smart.pos.framework.dto.ResponseData;
import com.neusoft.smart.pos.framework.exception.BusinessCommonException;
import com.neusoft.smart.pos.framework.utils.ListUtils;
import com.neusoft.smart.pos.order.constants.TradeErrorCode;
import com.neusoft.smart.pos.order.persistent.domain.OrderMaster;
import com.neusoft.smart.pos.order.persistent.domain.OrderRefund;
import com.neusoft.smart.pos.order.persistent.domain.OrderTransaction;
import com.neusoft.smart.pos.order.repository.OrderTransactionRepository;
import com.neusoft.smart.pos.order.service.OrderService;
import com.neusoft.smart.pos.order.repository.OrderMasterRepository;
import com.neusoft.smart.pos.order.service.RefundOrderService;
import com.neusoft.smart.pos.dto.payorder.request.PostCreatePayRefundOrderRequest;
import com.neusoft.smart.pos.payment.service.PaymentService;
import com.neusoft.smart.pos.payorder.persistent.domain.PayOrder;
import com.neusoft.smart.pos.payorder.persistent.domain.PayRefundOrder;
import com.neusoft.smart.pos.payorder.service.PayOrderService;
import com.neusoft.smart.pos.payorder.service.PayRefundOrderService;
import com.neusoft.smart.pos.utils.PosDeviceRedisUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.val;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Api(value = "退款订单管理接口", description = "退款订单管理接口")
@RestController
@RequestMapping(path = "/orderRefund")
@Validated
public class RefundOrderController {
    @Autowired
    private RefundOrderService refundOrderService;//ServiceFactory.getRefundOrderServiceInstance(null,null);
    @Autowired
    private PayRefundOrderService payRefundOrderService;
    @Autowired
    private PayOrderService payOrderService;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderMasterRepository orderMasterRepository;
    @Autowired
    private OrderTransactionRepository orderTransactionRepository;

    @ApiOperation(value = "退款订单生成使用接口", notes = "退款订单生成使用方法")
    @PostMapping("/createRefundOrder")
    public ResponseData<PostRefundOrderResponse> createRefundOrder(@RequestBody PostCreateRefundOrderRequest createRefundOrderRequest) {
        PostRefundOrderResponse response = new PostRefundOrderResponse();
        if (checkRefundAmountValue(createRefundOrderRequest.getOriginalOrderNumber(), createRefundOrderRequest.getRefundableAmount())) {
            //根据设备SN校正orgId和shopId
            if (createRefundOrderRequest.getSerialNo() != null && !createRefundOrderRequest.getSerialNo().isEmpty()) {
                //1.查询订单信息，并进行校验
                val deviceInfo = PosDeviceRedisUtils.getDeviceInfoBySerialNo(createRefundOrderRequest.getSerialNo());
                if (null == deviceInfo) {
                    throw new BusinessCommonException(TradeErrorCode.DEVICE_ORG_EMPTY);
                }

                createRefundOrderRequest.setSellerOrgId(deviceInfo.getOrganizationId());
                createRefundOrderRequest.setSellerShopId(deviceInfo.getStoreId());
            }
            response = refundOrderService.createRefundOrder(createRefundOrderRequest);
            if (createRefundOrderRequest.getPayRefundInfos() != null && createRefundOrderRequest.getPayRefundInfos().size() > 0) {
                boolean result = createAndPayRefundOrders(createRefundOrderRequest.getPayRefundInfos(), response.getOriginalOrderNumber(), response.getRefundNumber());
                response.setSuccess(result);
            }

            orderService.computeOrderStatus(createRefundOrderRequest.getOriginalOrderNumber());
            //response = refundOrderService.getRefundOrderInfo(response.getRefundNumber());
        } else {
            response.setSuccess(false);
        }
        return new ResponseData<>(response);
    }

    private boolean checkRefundAmountValue(String originalOrderNumber, Long refundableAmount) {
        OrderMaster orderMaster = orderService.getOrderMasterObj(originalOrderNumber);
        if(orderMaster!= null && refundableAmount <= orderMaster.getRealPayAmount()){
            return true;
        }
        return false;
    }

    private boolean createAndPayRefundOrders(List<PostCreatePayRefundOrderRequest> payRefundInfos, String orderNumber, String refundNumber) {
        boolean bResult = true;
        for (PostCreatePayRefundOrderRequest payRefundInfo : payRefundInfos) {
            if (payRefundInfo.getTradeId() != null && !"".equals(payRefundInfo.getTradeId())) {
                PayOrder payOrder = payOrderService.getPayOrder(payRefundInfo.getTradeId());

                payRefundInfo.setMOrderNumber(payOrder.getmOrderNumber());
                payRefundInfo.setPayType(payOrder.getPayType());
                payRefundInfo.setMcode(payOrder.getMcode());
                payRefundInfo.setRequestDetailInfo(payOrder.getRequestDetailInfo());
                payRefundInfo.setRefundNumber(refundNumber);
                payRefundInfo.setRefundStatus(DictionaryConstant.REFUND_STATUS_DTK.getCode());
                val postPayRefundOrderResponse = payRefundOrderService.createPayRefundOrder(payRefundInfo);
                val payRefundOrder = payRefundOrderService.getPayRefundOrder(postPayRefundOrderResponse.getPayRefundOrderNumber());
                val result = paymentService.refundPayOrder(payOrder, payRefundOrder.getPayRefundOrderNumber(), payRefundOrder.getRefundedAmount());
                if (!result.getRefundStatus().equals("2")) {
                    bResult = false;
                    break;
                } else {
                    payRefundOrderService.updatePayRefundOrderStatusById(payRefundOrder.getPayRefundOrderNumber(),DictionaryConstant.PAY_REFUND_STATUS__YTK.getCode());
                    payOrderService.updatePayOrderInfo(payOrder.getTradeId());
                }
            } else {
                payRefundInfo.setMOrderNumber(orderNumber);
                payRefundInfo.setRefundNumber(refundNumber);
                payRefundInfo.setPayType(DictionaryConstant.PAY_TYPE_XJ.getCode());
                payRefundInfo.setRefundStatus(DictionaryConstant.PAY_REFUND_STATUS__YTK.getCode());
                payRefundOrderService.createPayRefundOrder(payRefundInfo);
            }
        }

        refundOrderService.updateRefundOrderStatus(refundNumber);
        return bResult;
    }

    @ApiOperation(value = "退款支付订单执行支付接口", notes = "退款支付订单执行支付接口")
    @PutMapping("/doRefundPay")
    public ResponseData<PutDoRefundResponse> doRefundPay(@RequestBody PutDoRefundRequest putDoRefundRequest) {
        boolean bResult = true;

        val payRefundOrder = payRefundOrderService.getPayRefundOrder(putDoRefundRequest.getPayRefundOrderNumber());
        if (payRefundOrder != null && payRefundOrder.getTradeId() != null && !"".equals(payRefundOrder.getTradeId()) && checkRefundAmountValue(payRefundOrder.getmOrderNumber(), payRefundOrder.getRefundedAmount())) {
            PayOrder payOrder = payOrderService.getPayOrder(payRefundOrder.getTradeId());
            val result = paymentService.refundPayOrder(payOrder, payRefundOrder.getPayRefundOrderNumber(), payRefundOrder.getRefundedAmount());
            if (!result.getRefundStatus().equals("2")) {
                bResult = false;
            } else {
                payRefundOrderService.updatePayRefundOrderStatusById(putDoRefundRequest.getPayRefundOrderNumber(), DictionaryConstant.PAY_REFUND_STATUS__YTK.getCode());
                payOrderService.updatePayOrderInfo(payOrder.getTradeId());
            }
        } else {
            bResult = false;
        }

        val payRefundOrderAfter = payRefundOrderService.getPayRefundOrder(putDoRefundRequest.getPayRefundOrderNumber());
        refundOrderService.updateRefundOrderStatus(payRefundOrder.getRefundNumber());
        orderService.computeOrderStatus(payRefundOrder.getmOrderNumber());
        val response = new PutDoRefundResponse(bResult);
        BeanUtils.copyProperties(payRefundOrderAfter, response);
        return new ResponseData<>(response);
    }

    @ApiOperation(value = "余额退款现金支付接口", notes = "余额退款现金支付接口")
    @PutMapping("/doCashRefundPay")
    public ResponseData<PutDoRefundResponse> doCashRefundPay(@RequestBody PutDoRefundRequest putDoRefundRequest) {
        PutDoRefundResponse response = new PutDoRefundResponse(false);
        PostRefundOrderResponse refundOrderResponse = refundOrderService.getRefundOrderInfo(putDoRefundRequest.getRefundNumber());
        long refundAmount = refundOrderResponse.getRefundableAmount() - refundOrderResponse.getRefundedAmount();
        if (checkRefundAmountValue(refundOrderResponse.getOriginalOrderNumber(), refundAmount)) {
            PostCreatePayRefundOrderRequest payRefundInfo = new PostCreatePayRefundOrderRequest();
            payRefundInfo.setRefundedAmount(refundAmount);
            payRefundInfo.setMOrderNumber(putDoRefundRequest.getOrderNumber());
            payRefundInfo.setRefundNumber(putDoRefundRequest.getRefundNumber());
            payRefundInfo.setPayType(DictionaryConstant.PAY_TYPE_XJ.getCode());
            payRefundInfo.setRefundStatus(DictionaryConstant.PAY_REFUND_STATUS__YTK.getCode());
            val createResponse = payRefundOrderService.createPayRefundOrder(payRefundInfo);

            List<PostRefundOrderResponse.PayRefundOrderInfo> payRefundOrders = refundOrderResponse.getPayRefundOrderInfos();
            if (payRefundOrders != null) {
                for (PostRefundOrderResponse.PayRefundOrderInfo payRefundOrderInfo : payRefundOrders) {
                    if (!DictionaryConstant.PAY_REFUND_STATUS__YTK.getCode().equals(payRefundOrderInfo.getRefundStatus())) {
                        payRefundOrderService.canclePayRefundOrder(payRefundOrderInfo.getPayRefundOrderNumber());
                    }
                }
            }

            PayRefundOrder payRefundOrderAfter = payRefundOrderService.getPayRefundOrder(createResponse.getPayRefundOrderNumber());
            boolean bResult = refundOrderService.updateRefundOrderStatus(putDoRefundRequest.getRefundNumber());
            orderService.computeOrderStatus(putDoRefundRequest.getOrderNumber());
            response = new PutDoRefundResponse(bResult);
            BeanUtils.copyProperties(payRefundOrderAfter, response);
        }
        return new ResponseData<>(response);
    }

    @ApiOperation(value = "退款订单保存使用接口", notes = "根据订单编号更新退款订单信息方法")
    @PostMapping("/saveRefundOrder")
    public ResponseData<PostRefundOrderResponse> saveRefundOrder(@RequestBody PostSaveRefundOrderRequest saveRefundOrderRequest) {
        return new ResponseData<>(refundOrderService.saveRefundOrder(saveRefundOrderRequest));
    }

    @ApiOperation(value = "退款订单取消使用接口", notes = "根据订单编号设置退款订单状态为已取消的方法")
    @PutMapping("/cancleRefundOrder")
    public ResponseData<PutCancelRefundOrderResponse> cancleRefundOrder(@RequestBody PutCancelRefundOrderRequest cancleRefundOrderRequest) {
        return new ResponseData<>(refundOrderService.cancleRefundOrder(cancleRefundOrderRequest));
    }

    //    @ApiOperation(value = "更新退款订单状态接口", notes = "根据订单编号计算并更新退款订单状态方法")
//    @PutMapping("/updatRefundeOrderStatus")
//    public ResponseData<PutUpdateRefundOrderStatusResponse> updateRefundOrderStatus(@Valid @RequestBody PutUpdateRefundOrderStatusRequest updateRefundOrderStatusRequest, BindingResult bindingResult) {
//        return new ResponseData<>(refundOrderService.updateOrderStatus(updateRefundOrderStatusRequest));
//    }
    //setOrderStatus
    @ApiOperation(value = "设置退款订单状态接口", notes = "根据订单编号设置退款订单状态方法")
    @PutMapping("/setRefundOrderStatus")
    public ResponseData<PutSetRefundOrderStatusResponse> setRefundOrderStatus(@Valid @RequestBody PutSetRefundOrderStatusRequest setRefundOrderStatusRequest, BindingResult bindingResult) {
        return new ResponseData<>(refundOrderService.setRefundOrderStatus(setRefundOrderStatusRequest));
    }

    @ApiOperation(value = "退款订单信息查询接口", notes = "根据订单编号查询退款订单信息方法")
    @GetMapping("/getRefundOrderInfo")
    public ResponseData<GetRefundOrderInfoResponse> getRefundOrderInfo(@RequestParam(value = "orderNumber", defaultValue = "") String orderNumber) {
        return new ResponseData<>(refundOrderService.getRefundOrderInfoByRefundNumber(orderNumber));
    }

    @ApiOperation(value = "退款订单商品信息列表查询接口", notes = "退款订单商品信息列表查询方法")
    @GetMapping("/geRefundtOrderGoodsList")
    public ResponseData<GetRefundOrderInfoResponse> getRefundOrderGoodsList(@RequestParam(value = "orderNumber", defaultValue = "") String orderNumber) {
        return new ResponseData<>(refundOrderService.getRefundOrderGoodsListByOrderNumber(orderNumber));
    }

    ////////////////////////////////////////// 原来的(北国)接口 ///////////////////////////////////////////
    @ApiOperation(value = "POS端支付订单退款申请接口", notes = "POS端支付订单退款申请保存方法")
    @PostMapping("/refund")
    public ResponseData<PostRefundResponse> saveOrderRefund(@Valid @RequestBody PostRefundRequest refundRequest, BindingResult bindingResult) {
        //1.根据设备sn查询集团及门店ID
        val deviceInfo = PosDeviceRedisUtils.getDeviceInfoBySerialNo(refundRequest.getSerialNo());
        if(null == deviceInfo){
            throw new BusinessCommonException(TradeErrorCode.DEVICE_ORG_EMPTY);
        }
        val orgId = deviceInfo.getOrganizationId();
        val shopId = deviceInfo.getStoreId();

        //2.根据集团门店ID及订单号查询订单主表信息
        val orderMaster = orderMasterRepository.queryOrderByOrderNumber(orgId,shopId,refundRequest.getOrderNumber());
        if(null == orderMaster){
            throw new BusinessCommonException(TradeErrorCode.ORDER_INFO_NOT_EXIST);
        }
        if(DictionaryConstant.ORDER_UPDATE_STATUS_TKWC.getCode().equals(orderMaster.getOrderStatus())){
            throw new BusinessCommonException(TradeErrorCode.ORDER_REFUND_OVER);
        }
        if(!DictionaryConstant.ORDER_UPDATE_STATUS_ZFWC.getCode().equals(orderMaster.getOrderStatus())){
            throw new BusinessCommonException(TradeErrorCode.ORDER_STATUS_NOT_OVER_PAY);
        }

        //3.根据不同的支付方式生成退款单信息
        PostCreateRefundOrderRequest createRefundOrderRequest = new PostCreateRefundOrderRequest();
        createRefundOrderRequest.setSellerOrgId(orgId);
        createRefundOrderRequest.setSellerShopId(shopId);
        createRefundOrderRequest.setOriginalOrderNumber(refundRequest.getOrderNumber());
        createRefundOrderRequest.setLocationNo(orderMaster.getLocationNo());
        createRefundOrderRequest.setSerialNo(refundRequest.getSerialNo());
        createRefundOrderRequest.setRefundableAmount(orderMaster.getRealPayAmount());

        //处理退款商品
        List<OrderTransaction> orderDetails = orderTransactionRepository.queryOrderDetails(orderMaster.getOrderNumber());
        if (null != orderDetails && orderDetails.size() > 0) {
            createRefundOrderRequest.setOrderRefundDetails(ListUtils.convertListToList(orderDetails, PostOrderDetailRequest.class));
        }

        //处理退款支付单
        List<PayOrder> payOrders = payOrderService.queryPayOrderList(orderMaster.getOrderNumber());
        if (null != payOrders && payOrders.size() > 0) {
            PayOrder payOrder = payOrders.get(payOrders.size()-1);
            List<PostCreatePayRefundOrderRequest> payRefundInfos = new ArrayList<>();
            PostCreatePayRefundOrderRequest postCreatePayRefundOrderRequest = new PostCreatePayRefundOrderRequest();
            postCreatePayRefundOrderRequest.setMOrderNumber(payOrder.getmOrderNumber());
            postCreatePayRefundOrderRequest.setMcode(payOrder.getMcode());
            postCreatePayRefundOrderRequest.setTradeId(payOrder.getTradeId());
            postCreatePayRefundOrderRequest.setPayType(payOrder.getPayType());
            postCreatePayRefundOrderRequest.setRefundedAmount(payOrder.getPayAmount());
            payRefundInfos.add(postCreatePayRefundOrderRequest);
            createRefundOrderRequest.setPayRefundInfos(payRefundInfos);
        }
        PostRefundOrderResponse response = refundOrderService.createRefundOrder(createRefundOrderRequest);
        if (createRefundOrderRequest.getPayRefundInfos() != null && createRefundOrderRequest.getPayRefundInfos().size() > 0) {
            boolean result = createAndPayRefundOrders(createRefundOrderRequest.getPayRefundInfos(), response.getOriginalOrderNumber(), response.getRefundNumber());
            response.setSuccess(result);
        }

        orderService.computeOrderStatus(createRefundOrderRequest.getOriginalOrderNumber());
        val refundResponse = new PostRefundResponse();
        refundResponse.setIsSuccess(ApplicationConstants.TRUE);
        refundResponse.setRefundNumber(response.getRefundNumber());
        refundResponse.setPayType(payOrders.get(payOrders.size()-1).getPayType());
        refundResponse.setRefundAmount(new BigDecimal(orderMaster.getRealPayAmount().toString()).divide(new BigDecimal(100)));
        refundResponse.setRefundTime(response.getRefundedTime());
        return new ResponseData<>(refundResponse);
    }


}
