package com.xxfc.platform.order.rest;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.github.wxiaoqi.security.admin.entity.AppUserLogin;
import com.github.wxiaoqi.security.admin.feign.UserFeign;
import com.github.wxiaoqi.security.admin.feign.dto.UserDTO;
import com.github.wxiaoqi.security.admin.feign.rest.UserRestInterface;
import com.github.wxiaoqi.security.admin.vo.AppUserVo;
import com.github.wxiaoqi.security.auth.client.annotation.IgnoreClientToken;
import com.github.wxiaoqi.security.auth.client.annotation.IgnoreUserToken;
import com.github.wxiaoqi.security.common.context.BaseContextHandler;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.rest.CommonBaseController;
import com.github.wxiaoqi.security.common.util.ClientUtil;
import com.github.wxiaoqi.security.common.util.Query;
import com.github.wxiaoqi.security.common.util.process.ResultCode;
import com.github.wxiaoqi.security.common.vo.PageDataVO;
import com.xxfc.platform.activity.user.UserInfoBiz;
import com.xxfc.platform.order.biz.BaseOrderBiz;
import com.xxfc.platform.order.biz.OrderMemberDetailBiz;
import com.xxfc.platform.order.biz.OrderUserLicenseBiz;
import com.xxfc.platform.order.biz.OrderVehicalCrosstownBiz;
import com.xxfc.platform.order.contant.enumerate.OrderStatusEnum;
import com.xxfc.platform.order.entity.BaseOrder;
import com.xxfc.platform.order.entity.OrderUserLicense;
import com.xxfc.platform.order.mqhandler.RabbitProduct;
import com.xxfc.platform.order.pojo.order.*;
import com.xxfc.platform.order.pojo.pay.OrderPayDTO;
import com.xxfc.platform.universal.constant.DictionaryKey;
import com.xxfc.platform.universal.entity.Dictionary;
import com.xxfc.platform.universal.feign.ThirdFeign;
import com.xxfc.platform.universal.vo.OrderPayVo;
import com.xxfc.platform.vehicle.common.RestResponse;
import com.xxfc.platform.vehicle.entity.Vehicle;
import com.xxfc.platform.vehicle.feign.VehicleFeign;
import com.xxfc.platform.vehicle.pojo.CompanyDetail;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.github.wxiaoqi.security.auth.common.constatns.CommonConstants.DATA_ALL_FALSE;
import static com.xxfc.platform.universal.constant.DictionaryKey.APP_ORDER;

@Controller
@RequestMapping("baseOrder")
@Api(value = "订单", tags = {"订单"})
@Slf4j
public class BaseOrderController extends CommonBaseController implements UserRestInterface {

    public static final Integer STATUS_SUCCESS = 1;
    @Autowired
    BaseOrderBiz baseOrderBiz;
    @Autowired
    ThirdFeign thirdFeign;
    @Autowired
    UserFeign userFeign;
    @Resource
    VehicleFeign vehicleFeign;
    @Autowired
    RabbitProduct rabbitProduct;

    @Autowired
    OrderMemberDetailBiz orderMemberDetailBiz;
    @Autowired
    OrderUserLicenseBiz orderUserLicenseBiz;
    @Autowired
    OrderVehicalCrosstownBiz orderVehicalCrosstownBiz;

    @Override
    public UserFeign getUserFeign() {
        return userFeign;
    }

    @Value("${gateway.insideHost}")
    String insideHost;

    @Value("${gateway.host}")
    String host;

    @Value("${gateway.order}")
    String order;


    String qrcodePrefix = "fcwx://order";
    String notifyUrl = "/baseOrder/app/unauth/notifyUrl";

    @RequestMapping(value = "/app/unauth/getOrderUnitPrice", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "获取订单相关的单价")
    @IgnoreClientToken
    @IgnoreUserToken
    public ObjectRestResponse<OrderAboutParamDTO> getOrderUnitPrice() {
        Map<String, Dictionary> dictionaryMap = thirdFeign.dictionaryGetAll4Map().getData();
        return ObjectRestResponse.succ(new OrderAboutParamDTO(){{
            setInsurePrice(new BigDecimal(dictionaryMap.get(APP_ORDER+ "_"+ DictionaryKey.INSURE_PRICE).getDetail()));
        }});
    }

    @RequestMapping(value = "/app/unauth/getOrderParam", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "获取订单相关的参数")
    @IgnoreClientToken
    @IgnoreUserToken
    public ObjectRestResponse<OrderAboutParamDTO> getOrderParam() {
        Map<String, Dictionary> dictionaryMap = thirdFeign.dictionaryGetAll4Map().getData();
        return ObjectRestResponse.succ(new OrderAboutParamDTO(){{
            setInsurePrice(new BigDecimal(dictionaryMap.get(APP_ORDER+ "_"+ DictionaryKey.INSURE_PRICE).getDetail()));
            setActRent(new Long(dictionaryMap.get(APP_ORDER+ "_"+ DictionaryKey.ACT_RENT).getDetail()));
            setActTour(new Long(dictionaryMap.get(APP_ORDER+ "_"+ DictionaryKey.ACT_TOUR).getDetail()));
            setActMember(new Long(dictionaryMap.get(APP_ORDER+ "_"+ DictionaryKey.ACT_MEMBER).getDetail()));
            setDamageSafe(new BigDecimal(dictionaryMap.get(APP_ORDER+ "_"+ DictionaryKey.DAMAGE_SAFE).getDetail()));
            setDriverPrice(new BigDecimal(dictionaryMap.get(APP_ORDER+ "_"+ DictionaryKey.DRIVER_PRICE).getDetail()));
        }});
    }


    @RequestMapping(value = "/page", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "订单列表")
    @IgnoreClientToken
    public ObjectRestResponse<PageDataVO<OrderPageVO>> list(QueryOrderDTO dto) {
        //查询列表数据
        if (StringUtils.isBlank(BaseContextHandler.getUserID())) {
            throw new BaseException(ResultCode.AJAX_WECHAT_NOTEXIST_CODE);
        }
        dto.setCrtUser(Integer.valueOf(BaseContextHandler.getUserID()));
        Query query = new Query(dto);
        PageDataVO<OrderPageVO> pages = PageDataVO.pageInfo(query, () -> baseOrderBiz.pageByParm(query.getSuper()));
        pages.getData().parallelStream().forEach(data -> data.setQrcodeStr(qrcodePrefix));
        return new ObjectRestResponse<>().data(pages);
    }

    @RequestMapping(value = "/getOrderList", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "获取后台订单列表")
    @IgnoreClientToken
    @CrossOrigin
    public ObjectRestResponse<PageDataVO<OrderListVo>> selectByUser(QueryOrderList dto, HttpServletRequest request) {
        if (dto.getStartTime() != null) {
            if (dto.getEndTime() == null) {
                dto.setEndTime(new Date().getTime());
            }
        }
        if(StringUtils.isNotBlank(dto.getPhone())) {
            AppUserLogin appUserLogin = userFeign.one(dto.getPhone());
            if(appUserLogin != null) {
                dto.setUserId(appUserLogin.getId());
            }
        }

        UserDTO userDTO = getAdminUserInfo();
        if(userDTO == null) {
            return ObjectRestResponse.succ(new PageDataVO<>());
        }
        if(DATA_ALL_FALSE.equals(userDTO.getDataAll())) { //不能获取全部数据
            if(StringUtils.isNotBlank(userDTO.getDataZone())) {
               dto.setStartZoneId(userDTO.getZoneId());
            }
            if(StringUtils.isNotBlank(userDTO.getDataCompany())) {
                dto.setStartCompanyId(userDTO.getCompanyId());
            }
        }
        Query query = new Query(dto);
        PageDataVO pageDataVO = PageDataVO.pageInfo(query, () -> baseOrderBiz.listOrder(query.getSuper()));
        List<OrderListVo> list = pageDataVO.getData();
        List<Integer> userIds = list.stream().map(OrderListVo::getUserId).distinct().collect(Collectors.toList());
       if(userIds != null && userIds.size() >0) {
           ObjectRestResponse<List<AppUserVo>> objectRestResponse = userFeign.getByUserIds(userIds);
           log.info("获取用户信息：objectRestResponse = {}", objectRestResponse.getMessage());

           for (OrderListVo orderPageVO : list) {
               if (objectRestResponse.getData() != null && objectRestResponse.getData().size() > 0) {
                   for (AppUserVo appUserVo : objectRestResponse.getData()) {
                       if (appUserVo != null) {
                           orderPageVO.setTelephone(appUserVo.getUsername());
                           orderPageVO.setUsername(appUserVo.getNickname());
                       }
                   }
               }
               if (orderPageVO.getOrderRentVehicleDetail() != null && orderPageVO.getOrderRentVehicleDetail().getVehicleId() != null) {
                   RestResponse<Vehicle> restResponse = vehicleFeign.findById(orderPageVO.getOrderRentVehicleDetail().getVehicleId());
                   log.info("获取车辆信息返回消息：{}", restResponse.getMessage());
                   if (restResponse.getData() != null) {
                       orderPageVO.setVehicleNumberPlat(restResponse.getData().getNumberPlate());
                   }
                   if(StringUtils.isNotBlank(orderPageVO.getOrderRentVehicleDetail().getMyDriverIds())) {
                       List<OrderUserLicense> orderUserLicenses = orderUserLicenseBiz.selectByIds(orderPageVO.getOrderRentVehicleDetail().getMyDriverIds()).getData();

                       if(orderUserLicenses != null && orderUserLicenses.size() > 0) {
                           OrderVehicleCrosstownDto orderVehicleCrosstownDto = new OrderVehicleCrosstownDto();
                           orderVehicleCrosstownDto.setLicenseIdCard(orderUserLicenses.get(0).getLicenseIdCard());
                           orderVehicleCrosstownDto.setLicenseImg(orderUserLicenses.get(0).getLicenseImg());
                           orderVehicleCrosstownDto.setLicenseName(orderUserLicenses.get(0).getLicenseName());
                           orderVehicleCrosstownDto.setLicensePhone(orderUserLicenses.get(0).getLicensePhone());
                           orderPageVO.setOrderVehicleCrosstownDto(orderVehicleCrosstownDto);
                       }
                   }

               }
               if(orderPageVO.getOrderRentVehicleDetail() != null && orderPageVO.getOrderRentVehicleDetail().getStartCompanyId()!= null && orderPageVO.getOrderRentVehicleDetail().getEndCompanyId() != null) {
                   ObjectRestResponse<CompanyDetail> startResponse =  vehicleFeign.getCompanyDetail(orderPageVO.getOrderRentVehicleDetail().getStartCompanyId());
                    if(startResponse.getData() != null) {
                        orderPageVO.setStartCompanyName(startResponse.getData().getName());
                    }
                    
                   ObjectRestResponse<CompanyDetail> restResponse =  vehicleFeign.getCompanyDetail(orderPageVO.getOrderRentVehicleDetail().getEndCompanyId());
                   if(restResponse.getData() != null) {
                       orderPageVO.setEndCompanyName(restResponse.getData().getName());
                   }
               }

               if(orderPageVO.getOrderTourDetail() != null && orderPageVO.getOrderTourDetail().getStartCompanyId()!= null) {
                   ObjectRestResponse<CompanyDetail> startResponse =  vehicleFeign.getCompanyDetail(orderPageVO.getOrderTourDetail().getStartCompanyId());
                   if(startResponse.getData() != null) {
                       orderPageVO.setStartCompanyName(startResponse.getData().getName());
                   }
               }


           }
       }

        return new ObjectRestResponse<>().data(pageDataVO);
    }

    @RequestMapping(value = "/getVehicleList", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "交还车租车订单列表")
    @IgnoreClientToken
    public ObjectRestResponse<List<OrderPageVO>> getVehicleList(QueryOrderList dto) {
        log.info("请求参数：dto = {}", dto);
        if (dto.getStartTime() != null) {
            if (dto.getEndTime() == null) {
                dto.setEndTime(new Date().getTime());
            }
        }
        Query query = new Query(dto);
        PageDataVO<OrderPageVO> pageDataVO = PageDataVO.pageInfo(query, () -> baseOrderBiz.getRentVehicle(query.getSuper()));
        for(OrderPageVO orderPageVO : pageDataVO.getData()) {
            if (orderPageVO.getOrderRentVehicleDetail() != null && orderPageVO.getOrderRentVehicleDetail().getVehicleId() != null) {
                ObjectRestResponse<Vehicle> restResponse = vehicleFeign.get(orderPageVO.getOrderRentVehicleDetail().getVehicleId());
                log.info("获取车辆信息返回消息：{}", restResponse.getMessage());
                if (restResponse.getData() != null) {
                    orderPageVO.setVehicalNumberPlat(restResponse.getData().getNumberPlate());
                }
            }

        }
        return new ObjectRestResponse<>().data(pageDataVO);
    }

    @RequestMapping(value = "/getTourList", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "交还车旅游订单列表")
    @IgnoreClientToken
    public ObjectRestResponse<List<OrderPageVO>> getTourList(QueryOrderList dto) {
        if (dto.getStartTime() != null) {
            if (dto.getEndTime() == null) {
                dto.setEndTime(dto.getStartTime());
            }

        }
        Query query = new Query(dto);
        PageDataVO pageDataVO = PageDataVO.pageInfo(query, () -> baseOrderBiz.getTourList(query.getSuper()));
        return new ObjectRestResponse<>().data(pageDataVO);
    }

    @ApiOperation("订单详情")
    @RequestMapping(value = "/{no}", method = RequestMethod.GET)
    @IgnoreClientToken
    @ResponseBody
    public ObjectRestResponse<OrderPageVO> get(@PathVariable String no) {
        log.info("no:"+ no + ",时间戳："+ System.currentTimeMillis());
        checkAppUser();

        //查询列表数据
        Query query = initQuery(no);
        PageDataVO<OrderPageVO> page = PageDataVO.pageInfo(query, () -> baseOrderBiz.pageByParm(query.getSuper()));
        if (page.getData().isEmpty()) {
            throw new BaseException(ResultCode.NOTEXIST_CODE);
        }
        log.info("no:"+ no + ",时间戳："+ System.currentTimeMillis());
        return new ObjectRestResponse<>().data(page.getData().get(0));
    }

    @GetMapping(value = "/orderDetail")
    @ApiOperation(value = "交还车获取订单详情，带驾驶人信息")
    @IgnoreClientToken
    @ResponseBody
    public ObjectRestResponse getOrderDetail(String orderNo) {
        if(StringUtils.isBlank(orderNo)) {
            return ObjectRestResponse.paramIsEmpty();
        }
        return baseOrderBiz.getOrderDetail(orderNo);
    }


    @ApiOperation("结合后台人员所属公司查询订单详情")
    @RequestMapping(value = "/company/{no}", method = RequestMethod.GET)
    @IgnoreClientToken
    @ResponseBody
    public ObjectRestResponse<OrderPageVO> companyGet(@PathVariable String no) {
        //查询列表数据
        if (StringUtils.isBlank(BaseContextHandler.getUserID())) {
            throw new BaseException(ResultCode.AJAX_WECHAT_NOTEXIST_CODE);
        }

        Query query = initCompanyQuery(no);
        PageDataVO<OrderPageVO> page = PageDataVO.pageInfo(query, () -> baseOrderBiz.pageByParm(query.getSuper()));
        if (page.getData().isEmpty()) {
            throw new BaseException(ResultCode.NOTEXIST_CODE);
        }
        return new ObjectRestResponse<>().data(page.getData().get(0));
    }

    private Query initQuery(String no) {
        QueryOrderDetailDTO qodd = new QueryOrderDetailDTO();
        qodd.setCrtUser(Integer.valueOf(BaseContextHandler.getUserID()));
        qodd.setNo(no);
        qodd.setLimit(1);
        qodd.setPage(1);
        Query query = new Query(qodd);
        return query;
    }

    private Query initCompanyQuery(String no) {
        QueryOrderDetailDTO qodd = new QueryOrderDetailDTO();
        //查询公司id
        UserDTO userDto = userFeign.userinfoByToken(BaseContextHandler.getToken()).getData();
        qodd.setCrtCompanyId(userDto.getCompanyId());
        qodd.setNo(no);
        qodd.setLimit(1);
        qodd.setPage(1);
        Query query = new Query(qodd);
        return query;
    }

    @RequestMapping(value = "/pay", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "订单支付")
    @IgnoreClientToken
    public ObjectRestResponse pay(@RequestBody OrderPayDTO dto) {
        //查询列表数据
        if (StringUtils.isBlank(BaseContextHandler.getUserID())) {
            throw new BaseException(ResultCode.AJAX_WECHAT_NOTEXIST_CODE);
        }

        OrderPayVo orderPayVo = BeanUtil.toBean(dto, OrderPayVo.class);

        BaseOrder baseOrder = baseOrderBiz.selectOne(new BaseOrder() {{
            setNo(dto.getOrderNo());
        }});

        if (null == baseOrder || !OrderStatusEnum.ORDER_UNPAY.getCode().equals(baseOrder.getStatus())) {
            throw new BaseException("订单不可支付", ResultCode.EXCEPTION_CODE);
        }

        orderPayVo.setAmount(baseOrder.getRealAmount().multiply(new BigDecimal("100")).intValue());
        orderPayVo.setBody(baseOrder.getName());
        orderPayVo.setBuyerIp(StringUtils.defaultIfBlank(request.getHeader("userHost"), ClientUtil.getClientIp(request)));
        orderPayVo.setChannel(baseOrder.getType());
        orderPayVo.setNotifyUrl(insideHost + order + notifyUrl + "?orderNo=" + baseOrder.getNo());
        orderPayVo.setSubject(baseOrder.getName());
        orderPayVo.setUserId(baseOrder.getUserId());
        ObjectRestResponse response = BeanUtil.toBean(thirdFeign.wx(orderPayVo), ObjectRestResponse.class);
        return response;
    }

    @RequestMapping(value = "/cancel/{no}", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "取消订单")
    @IgnoreClientToken
    public ObjectRestResponse cancel(@PathVariable String no, @RequestBody CancelOrderDTO cancelOrderDto) {
        //查询列表数据
        if (StringUtils.isBlank(BaseContextHandler.getUserID())) {
            throw new BaseException(ResultCode.AJAX_WECHAT_NOTEXIST_CODE);
        }
        BaseOrder dbBaseOrder = baseOrderBiz.selectOne(new BaseOrder() {{
            setNo(no);
        }});
        if (null == dbBaseOrder || !BaseContextHandler.getUserID().equals(dbBaseOrder.getUserId().toString())) {
            throw new BaseException(ResultCode.NOTEXIST_CODE);

        }
        dbBaseOrder.setCancelReason(cancelOrderDto.getCancelReason());
        baseOrderBiz.cancel(dbBaseOrder);
        return ObjectRestResponse.succ();
    }

    @RequestMapping(value = "/app/unauth/notifyUrl", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "订单支付回调")
    @IgnoreClientToken
    @IgnoreUserToken
    public ObjectRestResponse notifyUrl(NotifyUrlDTO dto) {
        //判断是否成功，并且订单是未支付状态，则添加支付编号和修改状态
        if (StrUtil.isNotBlank(dto.getOrderNo())) {
            baseOrderBiz.payNotifyHandle(dto.getOrderNo(), dto.getTradeNo(), dto.getType());
        }else{
            log.error(" exception notifyUrl : " + JSONUtil.toJsonStr(dto));
        }
        return ObjectRestResponse.succ();
    }

    @RequestMapping(value = "/app/unauth/send-msg", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "mq发送消息")
    @IgnoreClientToken
    @IgnoreUserToken
    public ObjectRestResponse sendMsg() {
        rabbitProduct.sendDelayMessage(baseOrderBiz.selectById(93), 1000L * 60);
        return ObjectRestResponse.succ();
    }
    public UserDTO getAdminUserInfo() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        if(request.getHeader("Authorization") !=null) {
            return userFeign.userinfoByToken(request.getHeader("Authorization")).getData();
        }
        return null;
    }


    /**
     * 订单查询类
     */
    @Data
    public class QueryOrderDetailDTO extends QueryOrderDTO {
        private String no;
    }

    @Data
    public class QueryOrderList extends QueryOrderDetailDTO {

        private Long startTime;

        private Long endTime;

        private Integer startCompanyId;

        private Integer startZoneId;

        private Integer userId;

        private Integer type;

        private String phone;

        @ApiModelProperty("当前页码")
        Integer page;
        @ApiModelProperty("每页限制")
        Integer limit;
    }

    @Data
    public class NotifyUrlDTO {
        //订单号
        @ApiModelProperty(value = "订单号")
        private String orderNo;

        //订单号
        @ApiModelProperty(value = "支付订单（流水）号")
        private String tradeNo;

        //支付类型
        @ApiModelProperty(value = "支付类型")
        private Integer type;
    }
}
