package com.xxfc.platform.vehicle.rest;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.github.wxiaoqi.security.admin.feign.UserFeign;
import com.github.wxiaoqi.security.admin.feign.dto.UserDTO;
import com.github.wxiaoqi.security.auth.client.annotation.IgnoreClientToken;
import com.github.wxiaoqi.security.auth.client.annotation.IgnoreUserToken;
import com.github.wxiaoqi.security.auth.client.config.UserAuthConfig;
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.util.process.ResultCode;
import com.github.wxiaoqi.security.common.vo.PageDataVO;
import com.xxfc.platform.vehicle.biz.VehicleBiz;
import com.xxfc.platform.vehicle.biz.VehicleBookRecordBiz;
import com.xxfc.platform.vehicle.biz.VehiclePlatCataBiz;
import com.xxfc.platform.vehicle.common.BaseController;
import com.xxfc.platform.vehicle.common.CustomIllegalParamException;
import com.xxfc.platform.vehicle.common.RestResponse;
import com.xxfc.platform.vehicle.constant.ResCode.ResCode;
import com.xxfc.platform.vehicle.constant.VehicleBookRecordStatus;
import com.xxfc.platform.vehicle.entity.Vehicle;
import com.xxfc.platform.vehicle.entity.VehicleBookInfo;
import com.xxfc.platform.vehicle.entity.VehiclePlatCata;
import com.xxfc.platform.vehicle.pojo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.weekend.WeekendSqls;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.xxfc.platform.vehicle.constant.VehicleConstant.USER_APP;

@RestController
@RequestMapping("/vehicleInfo")
@Slf4j
@IgnoreClientToken
@Api(value="车辆管理controller",tags={"车辆管理接口"})
public class VehicleController extends BaseController<VehicleBiz> {

    @Autowired
    private VehicleBookRecordBiz vehicleBookRecordBiz;

    @Autowired
    VehicleBiz vehicleBiz;

    @Autowired
    UserFeign userFeign;

    @Autowired
    private UserAuthConfig userAuthConfig;

    @Autowired
    private VehiclePlatCataBiz vehiclePlatCataBiz;

    private static Integer MAX_DRIVING_LICENSE_SIZE = 10 * 1024 * 1024;//10M

    public static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public RestResponse<Vehicle> get(@PathVariable String id) {
        return RestResponse.data(baseBiz.get(id));
    }

    @RequestMapping(value = "", method = RequestMethod.POST)
    public RestResponse add(@RequestBody List<AddOrUpdateVehicleVo> addOrUpdateVehicleVoList) throws Exception {
        return baseBiz.add(addOrUpdateVehicleVoList);
    }

    @RequestMapping(value = "", method = RequestMethod.PUT)
    public RestResponse update(@RequestBody List<AddOrUpdateVehicleVo> addOrUpdateVehicleVoList) throws Exception {
        return baseBiz.update(addOrUpdateVehicleVoList);
    }

    @RequestMapping(value = "", method = RequestMethod.DELETE)
    public RestResponse discard(@RequestBody List<String> idList) throws Exception {
        return baseBiz.discard(idList);
    }

    @RequestMapping(value = "/page", method = RequestMethod.GET)
    public RestResponse<PageDataVO<QueryVehicleVo>> getByPage(@RequestParam String vehiclePageQueryVoJson) throws Exception {
        VehiclePageQueryVo vehiclePageQueryVo = null;
        try {
            vehiclePageQueryVo = JSON.parseObject(vehiclePageQueryVoJson, VehiclePageQueryVo.class);

            UserDTO userDTO = userFeign.userinfoByToken(userAuthConfig.getToken(request)).getData();
            if (userDTO != null) {
                if (userDTO.getDataAll() == 2) {
                    List<Integer> companyList = vehicleBiz.dataCompany(userDTO.getDataZone(), userDTO.getDataCompany());
                    return RestResponse.data(baseBiz.getByPageNotAllData(vehiclePageQueryVo, companyList));
                }
            }

            return RestResponse.data(baseBiz.getByPage(vehiclePageQueryVo));
        } catch (JSONException ex) {
            return RestResponse.code(ResCode.INVALID_REST_REQ_PARAM.getCode());
        } catch (CustomIllegalParamException ex) {
            return RestResponse.code(ResCode.INVALID_REST_REQ_PARAM.getCode());
        }
    }

    @RequestMapping(value = "/upload/drivingLicense", method = RequestMethod.POST)
    public RestResponse uploadDrivingLicense(@RequestParam("file") MultipartFile file)
            throws Exception {
        String contentType = file.getContentType();   //图片文件类型
//        String fileName = file.getOriginalFilename();  //图片名字
        if (!contentType.equals("image/jpeg") && !contentType.equals("image/gif")) {
            return RestResponse.code(ResCode.INVALID_REST_REQ_PARAM.getCode());
        }
        if (file.getSize() > MAX_DRIVING_LICENSE_SIZE) {
            return RestResponse.code(ResCode.INVALID_REST_REQ_PARAM.getCode());
        }
        return baseBiz.uploadDrivingLicense(file);
    }


    @IgnoreUserToken
    @RequestMapping(value = "/download/drivingLicense", method = RequestMethod.GET) //匹配的是href中的download请求
    public ResponseEntity<byte[]> downloadDrivingLicense(@RequestParam("realFileRelPath") String realFileRelPath) throws Exception {
        return baseBiz.downloadDrivingLicense(realFileRelPath);
    }

    @RequestMapping(value = "/bookedInfo/{vehicleId}/{yearMonth}", method = RequestMethod.GET)
    public RestResponse<VehicleBookInfo> getBookedInfo(@PathVariable String vehicleId, @PathVariable String yearMonth) {
        return RestResponse.data(baseBiz.getByVehicleIdAndYearMonth(vehicleId, yearMonth));
    }

    @RequestMapping(value = "/bookedInfo/{vehicleId}", method = RequestMethod.GET)
    public RestResponse<List<VehicleBookInfo>> getBookedInfo(@PathVariable String vehicleId) {
        return RestResponse.data(baseBiz.getByVehicleIdAndYearMonth(vehicleId));
    }

    /**
     * 申请预定车辆
     *
     * @param bookVehicleVo
     * @return
     */
    @RequestMapping(value = "/book/4employee", method = RequestMethod.POST)
    public RestResponse<Integer> applyVehicle(@RequestBody BookVehicleVO bookVehicleVo) throws Exception {
        Integer operatorId = Integer.parseInt(BaseContextHandler.getUserID());
        String userName = BaseContextHandler.getName();
        baseBiz.applyVehicle4Employee(operatorId, bookVehicleVo, userName);
        return RestResponse.suc();
    }

    /**
     * 批准预定车辆预定
     *
     * @param bookRecordId
     * @return
     */
    @RequestMapping(value = "/book/4employee/prove/{bookRecordId}", method = RequestMethod.PUT)
    public RestResponse<Integer> proveVehicleBooking(@PathVariable Long bookRecordId) throws Exception {
        Integer operatorId = Integer.parseInt(BaseContextHandler.getUserID());
        String userName = BaseContextHandler.getName();
        return baseBiz.reviewVehicleBooking(operatorId, bookRecordId, VehicleBookRecordStatus.APPROVE.getCode(), userName);
    }

    /**
     * 拒绝预定车辆申请
     *
     * @param bookRecordId
     * @return
     */
    @RequestMapping(value = "/book/4employee/reject/{bookRecordId}", method = RequestMethod.PUT)
    public RestResponse<Integer> rejectVehicleBooking(@PathVariable Long bookRecordId) throws Exception {
        Integer operatorId = Integer.parseInt(BaseContextHandler.getUserID());
        String userName = BaseContextHandler.getName();
        return baseBiz.reviewVehicleBooking(operatorId, bookRecordId, VehicleBookRecordStatus.REJECTED.getCode(), userName);
    }

//    /**
//     * 车辆归还
//     * @param bookRecordId
//     * @return
//     */
//    @RequestMapping(value ="/book/4employee/return/{bookRecordId}",method = RequestMethod.PUT)
//    public RestResponse<Integer> returnVehicle(@PathVariable String bookRecordId){
//        //此处待加入获取当前操作用户id信息以及相关权限验证
//        Integer operator = -1;//测试用
//        return baseBiz.returnVehicle(operator, bookRecordId);
//
//    }


    /**
     * 取消车辆预订
     *
     * @param bookRecordId
     * @return
     */
    @RequestMapping(value = "/unbook/4employee/{bookRecordId}", method = RequestMethod.DELETE)
    public RestResponse<Integer> unbookVehicle(@PathVariable Long bookRecordId) throws Exception {
        Integer operatorId = Integer.parseInt(BaseContextHandler.getUserID());
        String userName = BaseContextHandler.getName();
        return baseBiz.unbookVehicle4Employee(operatorId, bookRecordId, userName);
    }

    @RequestMapping(value = "/bookedRecord/{bookEndDate}/{id}", method = RequestMethod.GET)
    public RestResponse<QueryVehicleBookRecordVo> getBookedRecord(@PathVariable String bookEndDate, @PathVariable Long id) throws Exception {
        try {
            return RestResponse.codeAndData(RestResponse.SUC_CODE, vehicleBookRecordBiz.getById(id, DateTime.parse(bookEndDate, DEFAULT_FORMATTER)));
        } catch (JSONException ex) {
            return RestResponse.code(ResCode.INVALID_REST_REQ_PARAM.getCode());
        } catch (CustomIllegalParamException ex) {
            return RestResponse.code(ResCode.INVALID_REST_REQ_PARAM.getCode());
        }

    }


    @RequestMapping(value = "/bookedRecord", method = RequestMethod.GET)
    public RestResponse<PageDataVO<QueryVehicleBookRecordVo>> getBookedRecord(@RequestParam String vehicleBookRecordQueryVoJson) throws Exception {

        VehicleBookRecordQueryVo vehicleBookRecordQueryVo = null;
        try {
            vehicleBookRecordQueryVo = JSON.parseObject(vehicleBookRecordQueryVoJson, VehicleBookRecordQueryVo.class);
            return RestResponse.data(vehicleBookRecordBiz.page(vehicleBookRecordQueryVo));
        } catch (JSONException ex) {
            return RestResponse.code(ResCode.INVALID_REST_REQ_PARAM.getCode());
        } catch (CustomIllegalParamException ex) {
            return RestResponse.code(ResCode.INVALID_REST_REQ_PARAM.getCode());
        }

    }

    /**
     * 提车
     *
     * @param liftVehicleVo
     * @return
     */
    @RequestMapping(value = "/book/4employee/lift", method = RequestMethod.PUT)
    public RestResponse<Integer> liftVehicle(@RequestBody LiftVehicleVo liftVehicleVo) throws Exception {
        Integer operatorId = Integer.parseInt(BaseContextHandler.getUserID());
        String userName = BaseContextHandler.getName();
        return vehicleBookRecordBiz.lift(operatorId, userName, liftVehicleVo);
    }

    /**
     * 还车
     *
     * @param retVehicleVo
     * @return
     */
    @RequestMapping(value = "/book/4employee/ret", method = RequestMethod.PUT)
    public RestResponse<Integer> retVehicle(@RequestBody RetVehicleVo retVehicleVo) throws Exception {
        Integer operatorId = Integer.parseInt(BaseContextHandler.getUserID());
        String userName = BaseContextHandler.getName();
        return vehicleBookRecordBiz.retVehicle(operatorId, userName, retVehicleVo);
    }

    /**
     * 可用车辆查询
     *
     * @param dto
     * @return
     */
    @ApiOperation("可用车辆查询")
    @RequestMapping(value = "/rent/usable-vehicle", method = RequestMethod.GET)
    @IgnoreUserToken
    public ObjectRestResponse<PageDataVO<UsableVehicleModelVO>> rentUsableVehicle(UsableVeicleDTO dto) throws Exception {
        //根据时间 获得 可用车辆
        //结合车型
        if(StringUtils.isNotBlank(dto.getCatasStr())) {
            List<Integer> catasIds = Pattern.compile(",").splitAsStream(dto.getCatasStr()).map((s)-> Integer.parseInt(s)).collect(Collectors.toList());
            List<VehiclePlatCata> catas = vehiclePlatCataBiz.selectByExample(new Example.Builder(VehiclePlatCata.class)
                    .where(WeekendSqls.<VehiclePlatCata>custom().andIn(VehiclePlatCata::getId, catasIds)).build());
            Map<Integer, List<VehiclePlatCata>> vpcMap = new HashMap<Integer, List<VehiclePlatCata>>();
            for(VehiclePlatCata vpc : catas) {
                List<VehiclePlatCata> vpcs = vpcMap.get(vpc.getParentId());
                if(null == vpcs) {
                    vpcs = new ArrayList<VehiclePlatCata>();
                }
                vpcs.add(vpc);
                vpcMap.put(vpc.getParentId(), vpcs);
            }

            dto.setCatas(vpcMap);
        }
        return new ObjectRestResponse<>().data(vehicleBiz.searchUsableModel(dto)).rel(true);
    }

    /**
     * 热门车型
     *
     * @param dto
     * @return
     */
    @ApiOperation("热门车型")
    @RequestMapping(value = "/rent/hot-vehicle", method = RequestMethod.GET)
    @IgnoreUserToken
    public ObjectRestResponse<PageDataVO<UsableVehicleModelVO>> hotVehicle(HotVeicleDTO dto) throws Exception {
        return ObjectRestResponse.succ(vehicleBiz.hotModel(dto));
    }

    /**
     * 租车触发的申请预定车辆
     *
     * @param dto
     * @return
     */
    @ApiOperation("租车触发的申请预定车辆")
    @RequestMapping(value = "/rent/book/vehicle", method = RequestMethod.POST)
    @IgnoreClientToken
    @IgnoreUserToken
    public ObjectRestResponse<String> rentApplyVehicle(@RequestBody RentVehicleBookDTO dto) throws Exception {
        //默认USER_APP 预约
        Integer operatorId = USER_APP;
        String userName = dto.getUserName();
                //BaseContextHandler.getName();
        BookVehicleVO bookVehicleVo = BeanUtil.toBean(dto, BookVehicleVO.class);
        dto.setLimit(1);
        dto.setPage(1);

        //查询可车辆信息
        PageDataVO<Vehicle> pageDataVO = vehicleBiz.searchUsableVehicle(dto);
        if(pageDataVO.getData().size() <= 0) {
            throw new BaseException(ResultCode.NOTEXIST_CODE);
        }
        bookVehicleVo.setVehicle(pageDataVO.getData().get(0).getId());

        baseBiz.applyVehicle4Employee(operatorId, bookVehicleVo, userName);

        return ObjectRestResponse.succ(bookVehicleVo.getVehicle());
    }

}
