package com.xxfc.platform.vehicle.biz;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.xxfc.platform.vehicle.common.RestResponse;
import com.xxfc.platform.vehicle.constant.*;
import com.xxfc.platform.vehicle.constant.ResCode.ResCode;
import com.xxfc.platform.vehicle.entity.*;
import com.xxfc.platform.vehicle.mapper.*;
import com.xxfc.platform.vehicle.pojo.*;
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.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class VehicleActiveService {

    @Autowired
    VehicleMapper vehicleMapper;

    @Autowired
    VehicleDepartureLogMapper vehicleDepartureLogMapper;

    @Autowired
    VehicleActiveLogMapper vehicleActiveLogMapper;

    @Autowired
    VehicleUpkeepLogMapper vehicleUpkeepLogMapper;

    @Autowired
    VehicleUpkeepItemMapper vehicleUpkeepItemMapper;

    @Autowired
    VehicleBookRecordBiz vehicleBookRecordBiz;

    @Autowired
    VehicleBiz vehicleBiz;

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

    @Value("${vehicle.mileage}")
    private Integer Mileage;

    /**
     * 出车
     *
     * @param departureVo
     */
    @Transactional
    public void departure(VehicleDepartureVo departureVo) {
        Vehicle vehicle = vehicleMapper.selectByPrimaryKey(departureVo.getVehicleId());
        if (vehicle == null) {
            throw new BaseException(ResCode.VEHICLE_DEPARTURE_VEHICLE_UNEXIST.getDesc(),
                    ResCode.VEHICLE_DEPARTURE_VEHICLE_UNEXIST.getCode());
        }
        if(StringUtils.isBlank(departureVo.getCheckMan()) || StringUtils.isBlank(departureVo.getCheckManTel())) {
            throw new BaseException(ResCode.CHECKUSER_AND_PHONE_NOT_NULL.getDesc(),
                    ResCode.CHECKUSER_AND_PHONE_NOT_NULL.getCode());
        }
        if (!vehicle.getStatus().equals(VehicleStatus.NORMAL.getCode())) {
            throw new BaseException(ResCode.VEHICLE_DEPARTURE_VEHICLE_DISABLE.getDesc() + ", 车辆状态是：" + getVehicleStatus(vehicle.getStatus(), vehicle.getId()),
                    ResCode.VEHICLE_DEPARTURE_VEHICLE_DISABLE.getCode());
        }
        //添加出车时间过滤 再出车开始时间前一天至结束时间内可以出车,并且预定记录为已审核状态
        checkDateInvalide(departureVo);
        Integer MileageLift=vehicle.getMileageLastUpdate();
        Integer MileageLift1=departureVo.getMileage();
        if(MileageLift1==null){
            throw new BaseException(ResCode.VEHICLE_BOOKED_RECORD_MILEAGE_CHANGED.getDesc(),
                    ResCode.VEHICLE_BOOKED_RECORD_MILEAGE_CHANGED.getCode());
        }
        if(MileageLift==null||MileageLift1>=MileageLift){
            // 写入车辆公里数,预计目的地
            vehicle.setMileageLastUpdate(MileageLift1);
            vehicle.setExpectDestinationBranchCompanyId(departureVo.getExpectArrivalBranchCompanyId());
            vehicleMapper.updateByPrimaryKeySelective(vehicle);

            // 修改车辆状态，确认是空闲状态
            int result = vehicleMapper.updateStatusByIdAndStatus(departureVo.getVehicleId(), VehicleStatus.DEPARTURE.getCode(),
                    VehicleStatus.NORMAL.getCode());

            if (!vehicle.getStatus().equals(VehicleStatus.NORMAL.getCode())) {
                throw new BaseException(ResCode.VEHICLE_DEPARTURE_VEHICLE_DISABLE.getDesc() + ", 车辆状态是：" + getVehicleStatus(vehicle.getStatus(), vehicle.getId()),
                        ResCode.VEHICLE_DEPARTURE_VEHICLE_DISABLE.getCode());
            }
            //修改预约记录状态
            VehicleBookRecord vehicleBookRecord = null;
            if(departureVo.getBookRecordId() != null) {
                vehicleBookRecord = vehicleBookRecordBiz.selectById(departureVo.getBookRecordId());
                updateBookRecordStatus(vehicleBookRecord, 1);
            }
            VehicleDepartureLogVo vehicleDepartureLogVo = vehicleDepartureLogMapper.selectByBookRecordId(departureVo.getBookRecordId());
           if(vehicleDepartureLogVo != null) {
               BeanUtil.copyProperties(departureVo, vehicleDepartureLogVo, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
               VehicleDepartureLog departureLog = vehicleDepartureLogVo.getVehicleDeparture(vehicleDepartureLogVo);
               departureLog.setDepartureTime(new Date());
               departureLog.setUpdateTime(new Date());
               departureLog.setState(VehicleDepartureState.DEPARTURE.getCode());
               departureLog.setDepartureRemark(departureVo.getRemark());
               if(vehicleBookRecord != null) {
                   departureLog.setDepartureBranchCompanyId(vehicleBookRecord.getLiftCompany());
                   departureLog.setUse(BookType.getByCode(vehicleBookRecord.getBookType()));
                   departureLog.setUser(vehicleBookRecord.getVehicleUsername());
                   departureLog.setUserTel(vehicleBookRecord.getVehicleUserPhone());
               }
               vehicleDepartureLogMapper.updateByPrimaryKeySelective(departureLog);
           } else {
               // 出车记录
               VehicleDepartureLog departureLog = new VehicleDepartureLog();
               BeanUtils.copyProperties(departureVo, departureLog);
               departureLog.setDepartureTime(new Date());
               departureLog.setCreateTime(new Date());
               departureLog.setMileageStart(departureVo.getMileage());
               departureLog.setState(VehicleDepartureState.DEPARTURE.getCode());
               departureLog.setBookRecordId(departureVo.getBookRecordId());
               departureLog.setDepartureRemark(departureVo.getRemark());
               if(vehicleBookRecord != null) {
                   departureLog.setDepartureBranchCompanyId(vehicleBookRecord.getLiftCompany());
                   departureLog.setUse(BookType.getByCode(vehicleBookRecord.getBookType()));
                   departureLog.setUser(vehicleBookRecord.getVehicleUsername());
                   departureLog.setUserTel(vehicleBookRecord.getVehicleUserPhone());
               }
               vehicleDepartureLogMapper.insert(departureLog);
           }


            // 车辆活动日志
            VehicleActiveLog activeLog = new VehicleActiveLog();
            activeLog.setVehicleId(departureVo.getVehicleId());
            activeLog.setActiveType(VehicleActiveType.Departure.getCode());
            activeLog.setStartTime(new Date());
            activeLog.setCreateTime(new Date());
            vehicleActiveLogMapper.insert(activeLog);
        }else {
            throw new BaseException(ResCode.VEHICLE_BOOKED_RECORD_MILEAGE_CHANGED.getDesc(),
                    ResCode.VEHICLE_BOOKED_RECORD_MILEAGE_CHANGED.getCode());
        }
    }


    public String getVehicleStatus(Integer status, String vehicleId) {
        StringBuilder stringBuilder = new StringBuilder();
        switch (status) {
            case 1:
                stringBuilder.append("正常运行");
                break;
            case 2:
                stringBuilder.append("维修");
                break;
            case 3:
                stringBuilder.append("报废");
                break;
            case 4:
                stringBuilder.append("出车");
                break;
            case 5:
                stringBuilder.append("保养");
                break;
        }
            List<VehicleBookRecordVo> vehicleBookRecordVos = vehicleBookRecordBiz.selectByVehicleId(vehicleId);
            if(vehicleBookRecordVos != null && vehicleBookRecordVos.size() > 0) {
                stringBuilder.append("中，使用人：");
                stringBuilder.append(vehicleBookRecordVos.get(0).getVehicleUsername());
                stringBuilder.append(" 使用人电话：");
                stringBuilder.append(vehicleBookRecordVos.get(0).getVehicleUserPhone());
            }
        return stringBuilder.toString();
    }

    @Transactional
    public void arrival(VehicleArrivalVo arrivalVo) {
        Vehicle vehicle = vehicleMapper.selectByPrimaryKey(arrivalVo.getVehicleId());
        if (vehicle == null) {
            throw new BaseException(ResCode.VEHICLE_DEPARTURE_VEHICLE_UNEXIST.getDesc(),
                    ResCode.VEHICLE_DEPARTURE_VEHICLE_UNEXIST.getCode());
        }
        if(StringUtils.isBlank(arrivalVo.getRecycleMan()) || StringUtils.isBlank(arrivalVo.getRecycleManTel())) {
            throw new BaseException(ResCode.CHECKUSER_AND_PHONE_NOT_NULL.getDesc(),
                    ResCode.CHECKUSER_AND_PHONE_NOT_NULL.getCode());
        }
        if (!vehicle.getStatus().equals(VehicleStatus.DEPARTURE.getCode())) {
            throw new BaseException(ResCode.VEHICLE_DEPARTURE_VEHICLE_UNDEPARTURE.getDesc() + ", 车辆状态是：" + getVehicleStatus(vehicle.getStatus(), vehicle.getId()),
                    ResCode.VEHICLE_DEPARTURE_VEHICLE_UNDEPARTURE.getCode());
        }
        Integer Mileagerest = vehicle.getMileageLastUpdate();
        Integer Mileagerest1 = arrivalVo.getMileage();
        if (Mileagerest1 == null) {
            throw new BaseException(ResCode.VEHICLE_BOOKED_RECORD_MILEAGE_CHANGED.getDesc(),
                    ResCode.VEHICLE_BOOKED_RECORD_MILEAGE_CHANGED.getCode());
        }
        if (Mileagerest != null && Mileagerest1 >= Mileagerest) {
            VehicleBookRecord vehicleBookRecord = null;
            if(arrivalVo.getBookRecordId() != null) {
                vehicleBookRecord = vehicleBookRecordBiz.selectById(arrivalVo.getBookRecordId());
                updateBookRecordStatus(vehicleBookRecord, 2);
            }

            // 写入车辆公里数,还车分公司id
            vehicle.setMileageLastUpdate(Mileagerest1);
            if(vehicleBookRecord != null) {
                vehicle.setParkBranchCompanyId(vehicleBookRecord.getRetCompany());
            }
            vehicle.setExpectDestinationBranchCompanyId(0);
            vehicleMapper.updateByPrimaryKeySelective(vehicle);

            // 修改状态，确认是出车状态
            int result = vehicleMapper.updateStatusByIdAndStatus(arrivalVo.getVehicleId(), VehicleStatus.NORMAL.getCode(),
                    VehicleStatus.DEPARTURE.getCode());
            if (result == 0) {
                throw new BaseException(ResCode.VEHICLE_DEPARTURE_VEHICLE_UNDEPARTURE.getDesc(),
                        ResCode.VEHICLE_DEPARTURE_VEHICLE_UNDEPARTURE.getCode());
            }


            // 出车记录
            VehicleDepartureLog departureLog = vehicleDepartureLogMapper.selectLastByVehicleId(arrivalVo.getVehicleId());
            if (departureLog == null) {
                throw new BaseException(ResCode.VEHICLE_DEPARTURE_VEHICLE_UNDEPARTURE.getDesc(),
                        ResCode.VEHICLE_DEPARTURE_VEHICLE_UNDEPARTURE.getCode());
            }
                departureLog.setMileageEnd(arrivalVo.getMileage());
                departureLog.setRecycleMan(arrivalVo.getRecycleMan());
                departureLog.setRecycleManTel(arrivalVo.getRecycleManTel());
                departureLog.setArrivalBranchCompanyId(arrivalVo.getArrivalBranchCompanyId());
                departureLog.setUpdateTime(new Date());
                departureLog.setArrivalTime(new Date());
                departureLog.setState(VehicleDepartureState.END.getCode());
                departureLog.setIllegalPic(arrivalVo.getIllegalPic());
                departureLog.setIllegalAmount(arrivalVo.getIllegalAmount());
                departureLog.setArrivalPic(arrivalVo.getArrivalPic());
                departureLog.setArrivalRemark(arrivalVo.getRemark());
                if(vehicleBookRecord != null) {
                    departureLog.setArrivalBranchCompanyId(vehicleBookRecord.getRetCompany());
                }
                vehicleDepartureLogMapper.updateByPrimaryKeySelective(departureLog);
            // 车辆活动日志
            VehicleActiveLog activeLog = vehicleActiveLogMapper.selectLastByVehicleId(arrivalVo.getVehicleId());
            if (activeLog == null) {
                throw new BaseException(ResCode.VEHICLE_DEPARTURE_VEHICLE_UNDEPARTURE.getDesc(),
                        ResCode.VEHICLE_DEPARTURE_VEHICLE_UNDEPARTURE.getCode());
            }
            activeLog.setEndTime(new Date());
            activeLog.setUpdateTime(new Date());
            vehicleActiveLogMapper.updateByPrimaryKeySelective(activeLog);

            //取消预定时间 bookInfo和bookRecord
//            BookVehicleVO bookVehicleVo = new BookVehicleVO();
//            BeanUtils.copyProperties(vehicleBookRecord, bookVehicleVo);
//            bookVehicleVo.setNotCheckTimeLegal(Boolean.TRUE);
//            bookVehicleVo.setBookStartDate(null);
//            bookVehicleVo.setBookEndDate(null);
//            bookVehicleVo.setUnbookStartDate(new DateTime(vehicleBookRecord.getBookStartDate()).toString(DATE_TIME_FORMATTER));
//            bookVehicleVo.setUnbookEndDate(new DateTime(vehicleBookRecord.getBookEndDate()).toString(DATE_TIME_FORMATTER));
//           try {
//               Boolean hasSuc = vehicleBiz.unbookVehicle(bookVehicleVo);
//               if(!hasSuc){
//                   throw new BaseException(ResCode.VEHICLE_UNBOOK_FAIL.getDesc(), ResCode.VEHICLE_UNBOOK_FAIL.getCode());
//               }
//           } catch ( Exception e) {
//                e.printStackTrace();
//           }
        } else {
            throw new BaseException(ResCode.VEHICLE_BOOKED_RECORD_MILEAGE_CHANGED.getDesc(),
                    ResCode.VEHICLE_BOOKED_RECORD_MILEAGE_CHANGED.getCode());
        }
    }

    //添加出车时间过滤 再出车开始时间前一天至结束时间内可以出车,并且预定记录为已审核状态
    public void checkDateInvalide(VehicleDepartureVo arrivalVo) {
        if(arrivalVo.getBookRecordId() != null) {
            VehicleBookRecord   vehicleBookRecord = vehicleBookRecordBiz.selectById(arrivalVo.getBookRecordId());
            if(vehicleBookRecord != null) {
                DateTime startDate = new DateTime(vehicleBookRecord.getBookStartDate());
                DateTime endDate = new DateTime(vehicleBookRecord.getBookEndDate());
                Map<String, Object> param = new HashMap<>();
                param.put("vehicleId", vehicleBookRecord.getVehicleId());
                param.put("bookedEndDate", vehicleBookRecord.getBookStartDate());
                List<VehicleBookRecordVo> list = vehicleBookRecordBiz.selectByVehicleIdAndTime(param);
                if(!(startDate.minusDays(1).compareTo(DateTime.now()) <= 0 && DateTime.now().compareTo(endDate) <= 0 && vehicleBookRecord.getStatus() == VehicleBookRecordStatus.APPROVE.getCode() && (list == null || list.size() <= 0))) {
                    throw new BaseException(ResCode.VEHICLE_DEPARTURE_DATE_IS_NOT_ABLED.getDesc(),
                            ResCode.VEHICLE_DEPARTURE_DATE_IS_NOT_ABLED.getCode());
                }
            }
        }
    }


    public void updateBookRecordStatus(VehicleBookRecord vehicleBookRecord, Integer type) {

        if(vehicleBookRecord != null) {
            if(type == 1) {
                vehicleBookRecord.setActualStartDate(new Date());
            } else {
                vehicleBookRecord.setActualEndDate(new Date());
            }
            vehicleBookRecordBiz.updateSelectiveByIdRe(vehicleBookRecord);
        } else {
            throw new BaseException(ResCode.VEHICLE_BOOK_RECORD_IS_NOT_EXIST.getDesc(),
                    ResCode.VEHICLE_BOOK_RECORD_IS_NOT_EXIST.getCode());
        }
    }



    /**
     * 车辆保养
     * @param vehicleUpkeepVo
     */
    @Transactional
    public void upkeep(VehicleUpkeepVo vehicleUpkeepVo) {

        Vehicle vehicle = vehicleMapper.selectByPrimaryKey(vehicleUpkeepVo.getVehicleId());
        if (vehicle == null) {
            throw new BaseException(ResCode.VEHICLE_UPKEEP_VEHICLE_UNEXIST.getDesc(),
                    ResCode.VEHICLE_UPKEEP_VEHICLE_UNEXIST.getCode());
        }
        if (!vehicle.getStatus().equals(VehicleStatus.NORMAL.getCode())) {
            // 车辆非正常状态
            throw new BaseException(ResCode.VEHICLE_UPKEEP_VEHICLE_DISABLE.getDesc(),
                    ResCode.VEHICLE_UPKEEP_VEHICLE_DISABLE.getCode());
        }
        Integer lastMileage=vehicleUpkeepVo.getMileage();
        int result = vehicleMapper.upMileageByIdAndStatus(vehicleUpkeepVo.getVehicleId(), VehicleStatus.UPKEEP.getCode(),
                VehicleStatus.NORMAL.getCode(),lastMileage);
        if (result == 0) {
            // 车辆状态异常
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new BaseException(ResCode.VEHICLE_UPKEEP_VEHICLE_DISABLE.getDesc(),
                    ResCode.VEHICLE_UPKEEP_VEHICLE_DISABLE.getCode());
        }

        // 维修记录
        VehicleUpkeepLog vehicleUpkeepLog = new VehicleUpkeepLog();
        BeanUtils.copyProperties(vehicleUpkeepVo, vehicleUpkeepLog);
        vehicleUpkeepLog.setCreateTime(new Date());
        vehicleUpkeepLogMapper.insertSelective(vehicleUpkeepLog);

        // 维修项目
        List<Integer> upkeepItems = vehicleUpkeepVo.getUpkeepItems();
        for (Integer itemId : upkeepItems) {
            if (vehicleUpkeepItemMapper.selectByPrimaryKey(itemId) == null) {
                // 保养项目不存在
                throw new BaseException(ResCode.VEHICLE_UPKEEP_ITEM_UNEXIST.getDesc(),
                        ResCode.VEHICLE_UPKEEP_ITEM_UNEXIST.getCode());
            }
        }
        vehicleUpkeepLogMapper.addItems(vehicleUpkeepLog.getId(), upkeepItems);

        // 活动记录
        VehicleActiveLog vehicleActiveLog = new VehicleActiveLog();
        vehicleActiveLog.setVehicleId(vehicleUpkeepVo.getVehicleId());
        vehicleActiveLog.setActiveType(VehicleActiveType.UPKEEP.getCode());
        vehicleActiveLog.setCreateTime(new Date());
        vehicleActiveLog.setStartTime(new Date());
        vehicleActiveLogMapper.insertSelective(vehicleActiveLog);
    }

    /**
     * 保养结束
     * @param vehicleUpkeepEndVo
     */
    @Transactional
    public void upkeepEnd(VehicleUpkeepEndVo vehicleUpkeepEndVo) {
        String vehicleId = vehicleUpkeepEndVo.getVehicleId();
        Vehicle vehicle = vehicleMapper.selectByPrimaryKey(vehicleId);
        if (vehicle == null) {
            throw new BaseException(ResCode.VEHICLE_UPKEEP_VEHICLE_UNEXIST.getDesc(),
                    ResCode.VEHICLE_UPKEEP_VEHICLE_UNEXIST.getCode());
        }
        if (!vehicle.getStatus().equals(VehicleStatus.UPKEEP.getCode())) {
            // 车辆非保养状态
            throw new BaseException(ResCode.VEHICLE_UPKEEP_VEHICLE_UNUPKEEP.getDesc(),
                    ResCode.VEHICLE_UPKEEP_VEHICLE_UNUPKEEP.getCode());
        }
        Integer mileageLastUpdate=vehicle.getMileageLastUpdate()==null?0:vehicle.getMileageLastUpdate();
        Integer maintenance_mileage=Mileage+mileageLastUpdate;
        int result = vehicleMapper.updateMileageStatusByIdAndStatus(vehicleId, VehicleStatus.NORMAL.getCode(), VehicleStatus.UPKEEP.getCode(),maintenance_mileage);
        if (result == 0) {
            throw new BaseException(ResCode.VEHICLE_UPKEEP_VEHICLE_UNUPKEEP.getDesc(),
                    ResCode.VEHICLE_UPKEEP_VEHICLE_UNUPKEEP.getCode());
        }

        VehicleUpkeepLog vehicleUpkeepLog = vehicleUpkeepLogMapper.selectLastByVehicleId(vehicleId);
        if (vehicleUpkeepLog == null) {
            throw new BaseException(ResCode.VEHICLE_UPKEEP_VEHICLE_UNUPKEEP.getDesc(),
                    ResCode.VEHICLE_UPKEEP_VEHICLE_UNUPKEEP.getCode());
        }

        VehicleActiveLog vehicleActiveLog = vehicleActiveLogMapper.selectLastByVehicleId(vehicleId);
        if (vehicleActiveLog == null || !vehicleActiveLog.getActiveType().equals(VehicleActiveType.UPKEEP.getCode())) {
            throw new BaseException(ResCode.VEHICLE_UPKEEP_VEHICLE_UNUPKEEP.getDesc(),
                    ResCode.VEHICLE_UPKEEP_VEHICLE_UNUPKEEP.getCode());
        }
        vehicleActiveLog.setEndTime(new Date());
        vehicleActiveLog.setUpdateTime(new Date());
        vehicleActiveLogMapper.updateByPrimaryKeySelective(vehicleActiveLog);


    }


    public static void main(String[] args) {
        DateTime startDate = DateTime.parse("2019-08-21 17:00:00", DATE_TIME_FORMATTER);
        DateTime endDate = DateTime.parse("2019-08-21 21:00:00", DATE_TIME_FORMATTER);
        System.out.println();
        System.out.println(!(DateTime.now().compareTo(endDate) <= 0) && (startDate.minusDays(1).compareTo(DateTime.now()) <= 0));
    }
}
