package com.iformall.controller;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.iformall.common.ErrorCode;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.dto.OrderSaveDto;
import com.iformall.domain.po.*;
import com.iformall.domain.po.base.BaseEntity;
import com.iformall.domain.vo.WxCouponCVo;
import com.iformall.domain.vo.WxOrderCouponPressVo;
import com.iformall.domain.vo.WxOrderCouponVo;
import com.iformall.enums.*;
import com.iformall.exception.MallinkException;
import com.iformall.service.WxCUserBasicInfoService;
import com.iformall.service.WxCouponChannelService;
import com.iformall.service.WxCouponService;
import com.iformall.service.WxOrderService;
import com.iformall.utils.Constant;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.Map;

@RestController
@RequestMapping("/api/order/")
@Api(description = "订单相关接口")
public class WxOrderController extends BaseController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private WxCouponChannelService wxCouponChannelService;

    @Autowired
    private WxOrderService wxOrderService;

    @Autowired
    private WxCouponService wxCouponService;

    @Autowired
    private WxCUserBasicInfoService wxCUserBasicInfoService;

    @ApiOperation(value = "下订单", notes = "{\"couponChannelId\":\"String\",\"couponId\":\"String\",\"press\":\"String\",\"orderGroupId\":\"String\",\"formId\":\"String\"}")
    @PostMapping("save")
    public ResultData saveOrder(@RequestBody OrderSaveDto orderSaveDto) {
        logger.info("OrderSave: " + orderSaveDto);
        if (orderSaveDto.getCouponChannelId() == null) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "couponChannelId不能为空");
        }
        WxCouponChannel wxCouponChannel = wxCouponChannelService.getById(orderSaveDto.getCouponChannelId());
        if (wxCouponChannel == null) {
            logger.error("couponChannelId find error, " + orderSaveDto.getCouponChannelId());
            return new ResultData(ErrorCode.COUPON_CHANNEL_IS_TAKE_OFF);
        }
        ResultData resultData = couponChannelCheck(orderSaveDto, wxCouponChannel);
        if (resultData != null) return resultData;

        WxCUser user = getUser();
        WxCUserBasicInfo wxCUserBasicInfo = wxCUserBasicInfoService.getById(user.getId());
        if (wxCUserBasicInfo != null && wxCUserBasicInfo.getStatus().equals(EnumCUserBasicInfoStatus.LOCKED.getCode())) {
            logger.info("会员权益被锁定:cUserId:" + user.getId());
            return new ResultData(ErrorCode.MEMBER_IS_LOCKED);
        }

        resultData = couponUserCheck(user, wxCouponChannelService.findDetailVo(orderSaveDto.getCouponChannelId()));
        if (resultData != null) return resultData;

        Long couponId = orderSaveDto.getCouponId() == null ? wxCouponChannel.getCouponId() : orderSaveDto.getCouponId();
        if (couponId == null) {
            logger.error("couponChannelId或者couponId不能为空");
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "couponChannelId或者couponId不能为空");
        }
        // 是否砍价
        boolean isPress = orderSaveDto.getPress() != null ? orderSaveDto.getPress() : false;

        try {

            WxCoupon coupon = wxCouponService.getById(couponId);
            if (coupon == null) {
                return new ResultData(ErrorCode.COUPON_IS_EMPTY);
            }
            if (coupon.getStatus().equals(EnumCouponStatus.COUPON_STATUS_TAKE_OFFF.getCode())) {
                return new ResultData(ErrorCode.COUPON_IS_TAKE_OFF);
            }
            WxOrder order = wxOrderService.saveOrderForCoupon(user, coupon, orderSaveDto, isPress);
            return new ResultData(order);
        } catch (MallinkException e) {
            logger.error(e.getMessage());
            return new ResultData(e.getErrorCode(), e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage());
            return new ResultData(ErrorCode.ORDER_IS_FAIL, e.getMessage());
        }
    }

    private ResultData couponUserCheck(WxCUser user, WxCouponCVo coupon) {
        if (coupon.getConditions() == null) return null;
        JSONObject jo = null;
        try {
            jo = JSONObject.parseObject(coupon.getConditions());
        } catch (Exception e) {
            logger.error("购买券条件判断错误:ID=" + coupon.getId() + e.getMessage());
        }
        if (jo != null) {
            if (jo.getIntValue("type") == EnumCouponConditionType.NEW_MEMBER.getCode()){
                WxCUserBasicInfo cUserBasicInfo = wxCUserBasicInfoService.getById(user.getId());
                if (cUserBasicInfo != null && cUserBasicInfo.getActRecord() > 0)
                    return new ResultData(ErrorCode.COUPON_ONLY_FOR_NEW_MEMBER);
                if (wxOrderService.countCouponConditionType1(user) > 0)
                    return new ResultData(ErrorCode.COUPON_ALREADY_IN_NEW_MEMBER);
            }else if (jo.getIntValue("type") == EnumCouponConditionType.SCORE_SCOPE.getCode()){
                int max = jo.getIntValue("max");
                int min = jo.getIntValue("min");

                if (max!=0 && min ==0 && user.getScore() > max) {
                    return new ResultData(ErrorCode.COUPON_SCORE_NOT_IN_RANGE);
                }
                if (max==0 && min !=0 && user.getScore() < min) {
                    return new ResultData(ErrorCode.COUPON_SCORE_NOT_IN_RANGE);
                }
                if (max!=0 && min !=0 && (user.getScore() < min || user.getScore() > max)) {
                    return new ResultData(ErrorCode.COUPON_SCORE_NOT_IN_RANGE);
                }
            }
        }

        return null;
    }

    private ResultData couponChannelCheck(@RequestBody OrderSaveDto orderSaveDto, WxCouponChannel wxCouponChannel) {
        if (wxCouponChannel.getTargetAd().equals(EnumCouponChannelType.COUPON_CHANNEL_ID_TIMED.getCode())) {
            Date now = new Date();
            if (wxCouponChannel.getBeginTime().getTime() > now.getTime()) {
                logger.error("此券活动未开始:" + orderSaveDto.getCouponChannelId());
                return new ResultData(ErrorCode.COUPON_CHANNEL_IS_NOT_STARTED);
            }
            if (wxCouponChannel.getEndTime().getTime() < now.getTime()) {
                logger.error("此券活动已结束:" + orderSaveDto.getCouponChannelId());
                return new ResultData(ErrorCode.COUPON_CHANNEL_IS_END);
            }
        }

        if (wxCouponChannel.getStatus() == EnumCouponChannelStatus.STATUS_TAKE_OFFF.getCode()) {
            logger.error("此券已下架:" + orderSaveDto.getCouponChannelId());
            return new ResultData(ErrorCode.COUPON_CHANNEL_IS_TAKE_OFF);
        }
        return null;
    }

    @ApiOperation(value = "取消订单", notes = "{\"orderId\":\"string\"}")
    @PostMapping("cancel")
    public ResultData cancelOrder(@RequestBody Map<String, String> paramMap) {
        //Assert.notNull(wxOrders.getName(), "角色名不能为空");
        //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名");
        String orderIdStr = paramMap.get("orderId");
        if (StringUtils.isBlank(orderIdStr) || orderIdStr.equalsIgnoreCase(Constant.UNDEFINED)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "orderId不能为空");
        }
        Long orderId = 0L;
        try {
            orderId = Long.valueOf(orderIdStr);
        } catch (NumberFormatException e) {
            logger.error(e.getMessage());
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL, "orderId: " + orderIdStr + ", e: " + e.getMessage());
        }
        try {
            WxOrder order = wxOrderService.getById(orderId);
            if (order != null) {
                wxOrderService.updateOrderStatus(order, EnumOrderStatus.ORDER_STATUS_OVERTIME_CANCEL);
            }
        } catch (Exception e) {
            logger.error("取消订单失败: " + e.getMessage());
            return new ResultData(ErrorCode.ORDER_IS_FAIL.getCode(), "取消订单失败: " + e.getMessage());
        }

        return new ResultData();
    }

    @ApiOperation(value = "订单已过期", notes = "{\"orderId\":\"string\"}")
    @PostMapping("expired")
    public ResultData expiredOrder(@RequestBody Map<String, String> paramMap) {
        //Assert.notNull(wxOrders.getName(), "角色名不能为空");
        //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名");
        String orderIdStr = paramMap.get("orderId");
        if (StringUtils.isBlank(orderIdStr) || orderIdStr.equalsIgnoreCase(Constant.UNDEFINED)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "退款订单ID不能为空");
        }
        Long orderId = 0L;
        try {
            orderId = Long.valueOf(orderIdStr);
        } catch (NumberFormatException e) {
            logger.error(e.getMessage());
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "退款订单ID转换失败");
        }
        try {
            WxOrder order = wxOrderService.getById(orderId);
            if (order != null) {
                wxOrderService.updateOrderStatus(order, EnumOrderStatus.ORDER_STATUS_REFUND_SUCCESS);
            }
        } catch (Exception e) {
            logger.error("更新退款订单状态失败:" + e.getMessage());
            return new ResultData(ErrorCode.REFUND_ORDER_ERROR.getCode(), "更新退款订单状态失败:" + e.getMessage());
        }
        return new ResultData();
    }

    @ApiOperation("分页订单列表接口")
    @GetMapping("list")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true),
    })
    public ResultData list(@ModelAttribute WxOrder wxOrder, Integer pageNum, Integer pageSize) {
        // c端用户应该只能看到自己的订单
        if (wxOrder == null) wxOrder = new WxOrder();
        wxOrder.setCUserId(getUserId());
        wxOrder.setSortColumns(BaseEntity.SortField.UpdateDate_DESC);
        final PageInfo<WxOrderCouponVo> page = wxOrderService.listCUserVoAsPage(wxOrder, pageNum, pageSize);

        Date now = new Date();
        page.getList().stream().forEach(oc->{
            if (oc.getValidStartDate() != null && oc.getValidEndDate() != null ) {
                if (oc.getValidStartDate().getTime() > now.getTime()) {
                    oc.setValidStatus(EnumCouponOrderValidStatus.PREPARED.getCode());
                } else if (oc.getValidEndDate().getTime() < now.getTime()) {
                    oc.setValidStatus(EnumCouponOrderValidStatus.ENDED.getCode());
                } else {
                    oc.setValidStatus(EnumCouponChannelActivityStatus.STARTED.getCode());
                }
            }
        });


        return new ResultData(page);
    }

    @ApiOperation("订单详情接口")
    @GetMapping("detail")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderId", value = "订单id", dataType = "String", paramType = "query", required = true)
    })
    public ResultData detail(String orderId) {
        if (StringUtils.isBlank(orderId) || orderId.equalsIgnoreCase(Constant.UNDEFINED)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
        }
        // c端用户应该只能看到自己的订单细节
        WxOrder wxOrder = new WxOrder();
        Long id = 0L;
        try {
            id = Long.valueOf(orderId);
        } catch (NumberFormatException e) {
            logger.error("parse orderId failed");
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "订单ID转换异常");
        }
        wxOrder.setId(id);
        wxOrder.setCUserId(getUserId());
        WxOrderCouponVo wxOrderCVo = wxOrderService.detailCUserVo(wxOrder);
        if (wxOrderCVo == null)
            return new ResultData(ErrorCode.ORDER_IS_NOT_FIND);

        Date now = new Date();

        if (wxOrderCVo.getValidStartDate() != null && wxOrderCVo.getValidEndDate() != null ) {
            if (wxOrderCVo.getValidStartDate().getTime() > now.getTime()) {
                wxOrderCVo.setValidStatus(EnumCouponOrderValidStatus.PREPARED.getCode());
            } else if (wxOrderCVo.getValidEndDate().getTime() < now.getTime()) {
                wxOrderCVo.setValidStatus(EnumCouponOrderValidStatus.ENDED.getCode());
            } else {
                wxOrderCVo.setValidStatus(EnumCouponChannelActivityStatus.STARTED.getCode());
            }
        }

        return new ResultData(wxOrderCVo);
    }

    @ApiOperation(value = "根据orderId查询接口", notes = "{\"orderId\":\"string\"}")
    @GetMapping("/findById")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderId", value = "订单id", dataType = "String", paramType = "query", required = true)
    })
    public ResultData findById(String orderId) {
        if (orderId == null || orderId.equalsIgnoreCase(Constant.UNDEFINED)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
        }
        Long id = 0L;
        try {
            id = Long.valueOf(orderId);
        } catch (NumberFormatException e) {
            logger.error("parse orderId failed");
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "订单ID转换异常");
        }
        WxOrder order = null;
        try {
            order = wxOrderService.getById(id);
            if (order != null) {
                return new ResultData(Result.SUCCESS, "查询成功", order);
            } else {
                return new ResultData(ErrorCode.ORDER_IS_NOT_FIND);
            }
        } catch (Exception e) {
            logger.error("parse orderId failed");
            return new ResultData(ErrorCode.DB_FAIL.getCode(), "订单查询未成功,e:" + e.getMessage());
        }
    }

    @ApiOperation(value = "获取未支付订单", notes = "{\"couponId\":\"string\"}")
    @GetMapping("getUnPaidOrder")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "couponId", value = "券id", dataType = "String", paramType = "query", required = true)
    })
    public ResultData getUnPaidOrder(String couponId) {
        if (couponId == null || couponId.equalsIgnoreCase(Constant.UNDEFINED)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
        }
        Long id = 0L;
        try {
            id = Long.valueOf(couponId);
        } catch (NumberFormatException e) {
            logger.error("parse couponId failed");
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "券ID转换异常");
        }
        WxCoupon wxCoupon = null;
        try {
            wxCoupon = wxCouponService.getById(id);
        } catch (Exception e) {
            logger.error("券ID获取券信息失败, couponId: " + couponId);
            return new ResultData(ErrorCode.COUPON_IS_EMPTY);
        }
        if(wxCoupon == null) {
            logger.error("券ID获取券信息失败, couponId: " + couponId);
            return new ResultData(ErrorCode.COUPON_IS_EMPTY);
        }

        WxOrder order = null;
        try {
            order = wxOrderService.getUnPaidOrder(getUser(), wxCoupon);
            if (order != null) {
                return new ResultData(Result.SUCCESS, "查询成功", order);
            } else {
                return new ResultData(ErrorCode.ORDER_IS_NOT_FIND);
            }
        } catch (Exception e) {
            logger.error("parse orderId failed");
            return new ResultData(ErrorCode.DB_FAIL.getCode(), "订单查询未成功,e:" + e.getMessage());
        }
    }

    @ApiOperation("我的砍价-分页列表接口")
    @GetMapping("pressOrderList")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)})
    public ResultData pressOrderList(@ModelAttribute WxOrder wxOrder, Integer pageNum, Integer pageSize) {
        // c端用户应该只能看到自己的订单
        if (wxOrder == null) wxOrder = new WxOrder();
        wxOrder.setCUserId(getUserId());
        wxOrder.setSortColumns(BaseEntity.SortField.CreateDate_DESC);
        final PageInfo<WxOrderCouponPressVo> page = wxOrderService.listPressVoAsPage(wxOrder, pageNum, pageSize);
        return new ResultData(page);
    }

    @ApiOperation("砍价订单-详情接口")
    @GetMapping("pressOrderDetail")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderId", value = "订单id", dataType = "String", paramType = "query", required = true)
    })
    public ResultData pressOrderDetail(String orderId) {
        // c端用户应该只能看到自己的订单细节
        WxOrder wxOrder = new WxOrder();
        if(StringUtils.isBlank(orderId)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "订单ID不能为空");
        }
        Long id = 0L;
        try {
            id = Long.valueOf(orderId);
        } catch (NumberFormatException e) {
            logger.error("parse orderId failed");
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "订单ID转换异常");
        }
        wxOrder.setId(id);
        final WxOrderCouponPressVo orderCouponPressVo = wxOrderService.detailPressVo(wxOrder);
        if (orderCouponPressVo == null)
            return new ResultData(ErrorCode.ORDER_IS_NOT_FIND);
        return new ResultData(orderCouponPressVo);
    }


}
