package com.xxfc.platform.order.rest;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
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.AppUserDTO;
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.VehicleBrand;
import com.xxfc.platform.vehicle.entity.VehicleCategory;
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.mockito.internal.util.collections.Sets;
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 = "/app/del", method = RequestMethod.DELETE)
    @ResponseBody
    @ApiOperation(value = "删除申请")
    public ObjectRestResponse appDel(@RequestBody IdDTO idDTO) {

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

        baseBiz.updateByWeekendSelective(new ShuntApply(){{
            setIsDel(SYS_TRUE);
        }}, w -> {
            w.andEqualTo(ShuntApply::getId, idDTO.getApplyId())
             .andEqualTo(ShuntApply::getUserId, getCurrentUserIdInt());
            return w;
        });

        return ObjectRestResponse.succ();
    }

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

        DateTime startDateTime = DateUtil.date(shuntApply.getStartTime());
        DateTime afterDateTime = DateUtil.offsetHour(DateUtil.date(), 1);

        if(!startDateTime.isAfterOrEquals(afterDateTime)) {
            throw new BaseException(ResultCode.FAILED_CODE, Sets.newSet("请提前一小时需求预定"));
        }
        //查询列表数据
        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());
//        }

        shuntApply.setUserId(getCurrentUserIdInt());
        shuntApply.setStatus(STATUS_CRT);

        Long delayTime = DateUtil.date().getTime() - DateUtil.offsetMinute(startDateTime, -30).getTime();
        shuntApply.setOverTime(delayTime);
        baseBiz.insertSelective(shuntApply);
        rabbitProduct.sendApplyRequireDelayMessage(baseBiz.selectById(shuntApply.getId()), delayTime);
        return ObjectRestResponse.succ();
    }

    @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.pageList(dto), ShuntApplyVO.class);
        pages.getData().forEach(data -> {
            data.setAppUserDTO(userFeign.userDetailById(data.getUserId()).getData());
        });

        return ObjectRestResponse.succ(pages);
    }

    @RequestMapping(value = "/toOrderPayCount", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "待下单、待支付数量")
    public ObjectRestResponse<Integer> toPayCount() {
        //查询列表数据
        if (StrUtil.isBlank(getCurrentUserId())) {
            throw new BaseException(ResultCode.AJAX_WECHAT_NOTEXIST_CODE);
        }
        QueryDTO dto = new QueryDTO();
        dto.setUserId(Integer.valueOf(BaseContextHandler.getUserID()));
        dto.setPageStatus(QueryDTO.PAGE_STATUS_TOORDERPAY);
        Query query = new Query(dto);

        return ObjectRestResponse.succ(baseBiz.pageList(dto).size());
    }

    @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());
        dto.setAppUserDTO(userFeign.userDetailByToken(BaseContextHandler.getToken()).getData());
        RentVehicleBO bo = orderRentVehicleBiz.initRentVehicleBO(dto);
        bo.setOrderSign(BaseOrder.ORDER_SIGN_APPLY);
        bo.setBookRecordId(shuntApply.getBookRecordId());
        orderRentVehicleService.applyCreateOrder(bo, shuntApply.getOrderNo());
        baseBiz.updateSelectiveById(new ShuntApply(){{
            setId(shuntApply.getId());
            setStatus(ShuntApply.STATUS_ORDER);
            setOrderStatus(ShuntApply.ORDER_STATUS_TOPAY);
            setRealAmount(bo.getOrder().getRealAmount());
        }});
        return ObjectRestResponse.succ(bo.getOrder());
    }

    @Data
    public static class QueryDTO extends PageParam {
        public static final int PAGE_STATUS_ING = 1;
        public static final int PAGE_STATUS_TOORDERPAY = 2;
        public static final int PAGE_STATUS_PAYED = 3;
        public static final int PAGE_STATUS_CNL = 4;

        Integer userId;
        Integer pageStatus;
    }

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

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

    @Data
    public static class CnlApplyDTO {
        Integer applyId;
    }


    /********************************************app商家端**********************************************************/
    @RequestMapping(value = "/appBusiness/del", method = RequestMethod.DELETE)
    @ResponseBody
    @ApiOperation(value = "删除申请")
    public ObjectRestResponse appBusinessDel(@RequestBody IdDTO idDTO) {
        //查询列表数据
        if (StrUtil.isBlank(getCurrentUserId())) {
            throw new BaseException(ResultCode.AJAX_WECHAT_NOTEXIST_CODE);
        }

        UserDTO userDTO = getBusinessUserByAppUser();
        AssertUtils.isBlank(userDTO);

        baseBiz.updateByWeekendSelective(new ShuntApply(){{
            setIsBizdel(SYS_TRUE);
        }}, w -> {
            w.andEqualTo(ShuntApply::getId, idDTO.getApplyId())
             .andEqualTo(ShuntApply::getConfirmUserId, userDTO.getId());
            return w;
        });

        return ObjectRestResponse.succ();
    }

    @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::getIsDel, SYS_FALSE);
            w.andEqualTo(ShuntApply::getStatus, STATUS_CRT);
            return w;
        }, " crt_time desc "), StewardShuntApply.class);

        list.getData().forEach(data -> {
            data.setAppUserDTO(userFeign.userDetailById(data.getUserId()).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());
        }});

        try {
            //预约车辆
            orderRentVehicleService.acquireVehicle(detail, null , null);
        }catch (Exception e) {
            getLog().error(e.getMessage(), e);
            throw new BaseException("无法选择该车辆", ResultCode.PARAM_ILLEGAL_CODE);
        }

        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.setAppUserDTO(userFeign.userDetailById(shuntApplyVO.getUserId()).getData());
        RentVehicleBookDTO rbd = new RentVehicleBookDTO();
        //rbd.setModelId(shuntApply.getModelId());
        rbd.setBrandId(shuntApply.getBrandId());
        rbd.setCategoryId(shuntApply.getCategoryId());
        rbd.setGoodsType(shuntApply.getGoodsType());
        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());
            w.andEqualTo(ShuntApply::getIsBizdel, SYS_FALSE);
            if(StrUtil.isNotBlank(dto.getMultiStatus())) {
                w.andIn(ShuntApply::getStatus, CollUtil.toList(dto.getMultiStatus().split(",")));
            }
            return w;
        }), ShuntApplyController.ShuntApplyVO.class);

        pages.getData().forEach(data -> {
            data.setAppUserDTO(userFeign.userDetailById(data.getUserId()).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 IdDTO {
        Integer applyId;
    }

    @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;
        AppUserDTO appUserDTO;
    }
}