package com.xxfc.platform.order.rest;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
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.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.BaseController;
import com.github.wxiaoqi.security.common.util.AssertUtils;
import com.github.wxiaoqi.security.common.util.OrderUtil;
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.github.wxiaoqi.security.common.vo.PageParam;
import com.xxfc.platform.order.biz.BaseOrderBiz;
import com.xxfc.platform.order.biz.OrderRentVehicleBiz;
import com.xxfc.platform.order.biz.ShuntApplyBiz;
import com.xxfc.platform.order.biz.inner.OrderCalculateBiz;
import com.xxfc.platform.order.entity.BaseOrder;
import com.xxfc.platform.order.entity.ShuntApply;
import com.xxfc.platform.order.mqhandler.RabbitProduct;
import com.xxfc.platform.order.pojo.order.OrderPageVO;
import com.xxfc.platform.order.pojo.order.RentVehicleBO;
import com.xxfc.platform.order.pojo.order.add.AddRentVehicleDTO;
import com.xxfc.platform.order.service.OrderRentVehicleService;
import com.xxfc.platform.vehicle.entity.Vehicle;
import com.xxfc.platform.vehicle.entity.VehicleBrand;
import com.xxfc.platform.vehicle.entity.VehicleCategory;
import com.xxfc.platform.vehicle.entity.VehicleModel;
import com.xxfc.platform.vehicle.feign.VehicleFeign;
import com.xxfc.platform.vehicle.pojo.BookVehicleVO;
import com.xxfc.platform.vehicle.pojo.RentVehicleBookDTO;
import com.xxfc.platform.vehicle.pojo.vo.UsableVeicleVO;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

import static com.github.wxiaoqi.security.common.constant.CommonConstants.SYS_FALSE;
import static com.github.wxiaoqi.security.common.constant.CommonConstants.SYS_TRUE;
import static com.github.wxiaoqi.security.common.vo.PageDataVO.pageInfo;
import static com.xxfc.platform.order.entity.ShuntApply.*;

@RestController
@RequestMapping("shuntApply")
public class ShuntApplyController extends BaseController<ShuntApplyBiz, ShuntApply> implements UserRestInterface {


    @Autowired
    VehicleFeign vehicleFeign;

    @Autowired
    UserFeign userFeign;

    @Autowired
    OrderRentVehicleBiz orderRentVehicleBiz;

    @Autowired
    OrderCalculateBiz orderCalculateBiz;

    @Autowired
    OrderRentVehicleService orderRentVehicleService;

    @Autowired
    BaseOrderBiz baseOrderBiz;

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

    @Autowired
    RabbitProduct rabbitProduct;

    @RequestMapping(value = "/addApply", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "添加申请")
    public ObjectRestResponse addApply(@RequestBody ShuntApply shuntApply) {

        //查询列表数据
        if (StrUtil.isBlank(getCurrentUserId())) {
            throw new BaseException(ResultCode.AJAX_WECHAT_NOTEXIST_CODE);
        }
        if(null != shuntApply.getStartCompanyId()) {
            shuntApply.setStartCityCode(vehicleFeign.getCompanyDetail(shuntApply.getStartCompanyId()).getData().getAddrCity());
        }
        if(null != shuntApply.getEndCompanyId()) {
            shuntApply.setEndCityCode(vehicleFeign.getCompanyDetail(shuntApply.getEndCompanyId()).getData().getAddrCity());
        }
//        if(null != shuntApply.getCategoryId()) {
//            VehicleCategory vehicleCategory = vehicleFeign.getVehicleCategory(shuntApply.getCategoryId()).getData();
//            shuntApply.setCategoryName(vehicleCategory.getName());
//        }else if{
//
//        }

        shuntApply.setUserId(getCurrentUserIdInt());
        shuntApply.setStatus(STATUS_CRT);
        return add(shuntApply);
    }

    @RequestMapping(value = "/cancelApply", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "取消申请")
    public ObjectRestResponse addApply(@RequestBody CnlApplyDTO dto) {

        //查询列表数据
        if (StrUtil.isBlank(getCurrentUserId())) {
            throw new BaseException(ResultCode.AJAX_WECHAT_NOTEXIST_CODE);
        }

        ShuntApply shuntApply = baseBiz.selectById(dto.getApplyId());
        if(null == shuntApply) {
            throw new BaseException(ResultCode.PARAM_ILLEGAL_CODE);
        }

        baseBiz.updateSelectiveById(new ShuntApply(){{
            setId(shuntApply.getId());
            setStatus(STATUS_CNL);
        }});
        return ObjectRestResponse.succ();
    }

    @RequestMapping(value = "/pageList", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "申请列表")
    public ObjectRestResponse<PageDataVO<ShuntApplyVO>> pageList(QueryDTO dto) {
        //查询列表数据
        if (StrUtil.isBlank(getCurrentUserId())) {
            throw new BaseException(ResultCode.AJAX_WECHAT_NOTEXIST_CODE);
        }
        dto.setUserId(Integer.valueOf(BaseContextHandler.getUserID()));
        Query query = new Query(dto);
        PageDataVO<ShuntApplyVO> pages = PageDataVO.pageInfo(query, () -> baseBiz.selectByWeekend(w -> {
            w.andEqualTo(ShuntApply::getUserId, dto.getUserId());
            return w;
        }, " crt_time desc "), ShuntApplyVO.class);
//        pages.getData().forEach(data -> {
//            if(null != data.getCategoryId()) {
//                data.setVehicleCategory(vehicleFeign.getVehicleCategory(data.getCategoryId()).getData());
//            }
//        });

        return ObjectRestResponse.succ(pages);
    }

    @RequestMapping(value = "/applyOrder", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "申请调车下单")
    public ObjectRestResponse applyOrder(@RequestBody ApplyOrderDTO dto) {

        //查询列表数据
        if (StrUtil.isBlank(getCurrentUserId())) {
            throw new BaseException(ResultCode.AJAX_WECHAT_NOTEXIST_CODE);
        }

        if(null == dto.getApplyId()) {
            throw new BaseException(ResultCode.PARAM_ILLEGAL_CODE);
        }

        ShuntApply shuntApply = baseBiz.selectById(dto.getApplyId());
        if(null == shuntApply) {
            throw new BaseException(ResultCode.PARAM_ILLEGAL_CODE);
        }

        if(ShuntApply.STATUS_ORDER == shuntApply.getStatus()) {
            throw new BaseException("该申请已下单", ResultCode.PARAM_ILLEGAL_CODE);
        }

        dto.setVehicleId(shuntApply.getVehicleId());
        dto.setStartTime(shuntApply.getStartTime());
        dto.setEndTime(shuntApply.getEndTime());
        dto.setStartCompanyId(shuntApply.getStartCompanyId());
        dto.setEndCompanyId(shuntApply.getEndCompanyId());
        RentVehicleBO bo = orderRentVehicleBiz.initRentVehicleBO(dto);
        bo.setApplyOrderSign(SYS_TRUE);
        bo.setAppUserDTO(userFeign.userDetailByToken(BaseContextHandler.getToken()).getData());
        orderRentVehicleService.applyCreateOrder(bo, shuntApply.getOrderNo());
        baseBiz.updateSelectiveById(new ShuntApply(){{
            setId(shuntApply.getId());
            setStatus(ShuntApply.STATUS_ORDER);
            setOrderStatus(ShuntApply.ORDER_STATUS_TOPAY);
        }});
        return ObjectRestResponse.succ(bo.getOrder());
    }

    @Data
    public static class QueryDTO extends PageParam {
        Integer userId;
    }

    @Data
    public static class ShuntApplyVO extends ShuntApply {
//        VehicleModel vehicleModel;
        OrderPageVO orderPageVO;
        VehicleCategory vehicleCategory;
        VehicleBrand vehicleBrand;
    }

    @Data
    public static class ApplyOrderDTO extends AddRentVehicleDTO {
        Integer applyId;
    }

    @Data
    public static class CnlApplyDTO {
        Integer applyId;
    }


    /********************************************app商家端**********************************************************/
    @RequestMapping(value = "/appBusiness/list", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "根据城市查询待确认申请列表")
    public ObjectRestResponse<PageDataVO<StewardShuntApply>> stewardList(ListDTO dto) {
        AssertUtils.isBlank(getBusinessUserByAppUser());
        //获取该城市的申请最大和最小时间
        //获取该店铺
        PageDataVO<StewardShuntApply> list = PageDataVO.pageInfo(dto.initQuery(), () -> baseBiz.selectByWeekend(w -> {
            if(null != dto.getCityCode()) {
                w.andEqualTo(ShuntApply::getStartCityCode, dto.getCityCode());
            }
            w.andEqualTo(ShuntApply::getStatus, STATUS_CRT);
            return w;
        }, " crt_time desc "), StewardShuntApply.class);

//        list.getData().forEach(data -> {
//            if(null != data.getCategoryId()) {
//                data.setVehicleCategory(vehicleFeign.getVehicleCategory(data.getCategoryId()).getData());
//            }
//        });

        return ObjectRestResponse.succ(list);
    }

    @RequestMapping(value = "/appBusiness/confirmApply", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "app商家用户确认申请")
    public ObjectRestResponse stewardConfirmApply(@RequestBody ConfirmApplyDTO dto) {
        UserDTO userDTO = getBusinessUserByAppUser();
        AssertUtils.isBlank(userDTO);
        //查询列表数据
        if (StrUtil.isBlank(getCurrentUserId())) {
            throw new BaseException(ResultCode.AJAX_WECHAT_NOTEXIST_CODE);
        }

        if(null == dto.getApplyId()) {
            throw new BaseException(ResultCode.PARAM_ILLEGAL_CODE);
        }

        ShuntApply shuntApply = baseBiz.selectById(dto.getApplyId());
        if(null == shuntApply && shuntApply.getStatus() != STATUS_CRT) {
            throw new BaseException(ResultCode.PARAM_ILLEGAL_CODE);
        }

        RentVehicleBO detail = new RentVehicleBO();
        detail.setStartTime(shuntApply.getStartTime());
        detail.setEndTime(shuntApply.getEndTime());
        detail.setVehicleId(dto.getVehicleId());
//        detail.setModelId(shuntApply.getModelId());
        detail.setStartAddr(shuntApply.getStartCompanyName());
        detail.setStartCompanyId(shuntApply.getStartCompanyId());
        detail.setEndCompanyId(shuntApply.getEndCompanyId());
        detail.setOrder(new BaseOrder(){{setNo(OrderUtil.GetOrderNumber("", OrderUtil.APP_MID));}});
        detail.setRentFreeDay(SYS_FALSE);
        detail.setBookVehicleVO(new BookVehicleVO(){{
            setBookStartDate(DateUtil.date(shuntApply.getStartTime()).toDateStr());
            setBookEndDate(DateUtil.date(shuntApply.getEndTime()).toDateStr());
            setBookStartDateTime(DateUtil.date(shuntApply.getStartTime()).toString());
            setBookEndDateTime(DateUtil.date(shuntApply.getEndTime()).toString());
        }});

        //预约车辆
        orderRentVehicleService.acquireVehicle(detail, null , null);

        shuntApply.setVehicleId(dto.getVehicleId());
        shuntApply.setStatus(STATUS_CONFIRM);
        shuntApply.setOrderNo(detail.getOrder().getNo());
        shuntApply.setOverTime(DateUtil.offsetHour(DateUtil.date(), 1).getTime());
        shuntApply.setConfirmUserId(userDTO.getId());
        shuntApply.setConfirmCompanyId(userDTO.getCompanyId());
        shuntApply.setBookRecordId(detail.getBookRecordId());
        baseBiz.updateSelectiveByIdRe(shuntApply);

        rabbitProduct.sendApplyDelayMessage(baseBiz.selectById(shuntApply.getId()), 1000L * 3601L);

        return ObjectRestResponse.succ();
    }

    @RequestMapping(value = "/appBusiness/applyDetail", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "申请的详情")
    public ObjectRestResponse stewardApplyDetail(Integer applyId) {
        UserDTO userDTO = getBusinessUserByAppUser();
        AssertUtils.isBlank(userDTO);
        Integer companyId = userDTO.getCompanyId();
        ShuntApply shuntApply = baseBiz.selectById(applyId);
        StewardShuntApply shuntApplyVO = BeanUtil.toBean(shuntApply, StewardShuntApply.class);
        shuntApplyVO.setVehicleCategory(vehicleFeign.getVehicleCategory(shuntApply.getCategoryId()).getData());
        RentVehicleBookDTO rbd = new RentVehicleBookDTO();
        //rbd.setModelId(shuntApply.getModelId());
        rbd.setBrandId(shuntApply.getBrandId());
        rbd.setCategoryId(shuntApply.getCategoryId());
        rbd.setParkBranchCompanyId(companyId);
        rbd.setStartCompanyId(companyId);
        rbd.setEndCompanyId(companyId);
        rbd.setBookStartDate(DateUtil.date(shuntApply.getStartTime()).toDateStr());
        rbd.setBookEndDate(DateUtil.date(shuntApply.getEndTime()).toDateStr());
        rbd.setBookStartDateTime(DateUtil.date(shuntApply.getStartTime()).toString());
        rbd.setBookEndDateTime(DateUtil.date(shuntApply.getEndTime()).toString());
        //查询本公司时间段内可用车辆
        ObjectRestResponse<PageDataVO<UsableVeicleVO>> usableVehiclePage = vehicleFeign.applyUsableVehicle(rbd);

        if(CollUtil.isNotEmpty(usableVehiclePage.getData().getData())) {
            List<UsableVeicleVO> vehicles = CollUtil.newArrayList();

            usableVehiclePage.getData().getData().forEach(usableVeicleVO -> {
                //判断是否预定时间内可租
                usableVeicleVO.setAllowRent(SYS_TRUE);
                //如果"必须在这时间后预定" 存在 并且 比预定开始时间 要晚，那么不允许预定
                if(null != usableVeicleVO.getToLiftMustAfterDate() && DateUtil.date(shuntApply.getStartTime()).isBeforeOrEquals(usableVeicleVO.getToLiftMustAfterDate())) {
                    usableVeicleVO.setAllowRent(SYS_FALSE);
                }

                //如果"必须在这时间前预定" 存在 并且 比预定结束时间 要早，那么不允许预定
                if(null != usableVeicleVO.getToReturnMustBeforeDate() && DateUtil.date(shuntApply.getEndTime()).isAfterOrEquals(usableVeicleVO.getToReturnMustBeforeDate())) {
                    usableVeicleVO.setAllowRent(SYS_FALSE);
                }
                if(SYS_TRUE.equals(usableVeicleVO.getAllowRent())) {
                    vehicles.add(BeanUtil.toBean(usableVeicleVO, UsableVeicleVO.class));
                }
            });

            if(CollUtil.isNotEmpty(vehicles)) {
                shuntApplyVO.setVehicles(vehicles);
            }
        }
        return ObjectRestResponse.succ(shuntApplyVO);
    }


    @RequestMapping(value = "/appBusiness/myApplyList", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "我的申请")
    public ObjectRestResponse myApplyList(PageDTO dto) {
        UserDTO userDTO = getBusinessUserByAppUser();
        AssertUtils.isBlank(userDTO);
        PageDataVO<ShuntApplyController.ShuntApplyVO> pages = PageDataVO.pageInfo(dto.initQuery(), () -> baseBiz.selectByWeekend(w -> {
            w.andEqualTo(ShuntApply::getConfirmUserId, userDTO.getId());
            if(StrUtil.isNotBlank(dto.getMultiStatus())) {
                w.andIn(ShuntApply::getStatus, CollUtil.toList(dto.getMultiStatus().split(",")));
            }
            return w;
        }), ShuntApplyController.ShuntApplyVO.class);

        pages.getData().forEach(data -> {
//            if(null != data.getCategoryId()) {
//                data.setVehicleCategory(vehicleFeign.getVehicleCategory(data.getCategoryId()).getData());
//            }

            if(StrUtil.isNotBlank(data.getOrderNo())) {
                Map<String, Object> map = CollUtil.newHashMap();
                map.put("no", data.getOrderNo());
                List<OrderPageVO> list = baseOrderBiz.pageByParm(map);
                if(CollUtil.isNotEmpty(list)) {
                    data.setOrderPageVO(list.get(0));
                }
            }
        });

        return ObjectRestResponse.succ(pages);
    }


    @Data
    public static class ConfirmApplyDTO {
        Integer applyId;
        String vehicleId;
    }

    @Data
    public static class ListDTO extends PageParam {
        Integer cityCode;
    }

    @Data
    public static class PageDTO extends PageParam {
        String multiStatus;
    }

    @Data
    public static class StewardShuntApply extends ShuntApply {
        List<UsableVeicleVO> vehicles;
        VehicleCategory vehicleCategory;
        VehicleBrand vehicleBrand;
    }
}