package com.ruoyi.bst.order.utils;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;

import com.ruoyi.bst.area.domain.AreaVO;
import com.ruoyi.bst.area.utils.AreaUtil;
import com.ruoyi.bst.areaSub.domain.AreaSubVO;
import com.ruoyi.bst.areaSub.utils.AreaSubUtil;
import com.ruoyi.bst.device.domain.DeviceQuery;
import com.ruoyi.bst.device.domain.DeviceVO;
import com.ruoyi.bst.device.domain.enums.DeviceStatus;
import com.ruoyi.bst.order.domain.OrderVO;
import com.ruoyi.bst.order.domain.vo.OrderFeeVO;
import com.ruoyi.bst.order.domain.vo.OrderInParkingVO;
import com.ruoyi.bst.order.domain.vo.OrderPrePriceVO;
import com.ruoyi.bst.suit.domain.SuitVO;
import com.ruoyi.bst.suit.domain.enums.SuitRentalUnit;
import com.ruoyi.bst.suit.domain.enums.SuitRidingRule;
import com.ruoyi.bst.suit.utils.SuitUtil;
import com.ruoyi.common.utils.MathUtils;

public class OrderUtil {

    public static OrderPrePriceVO calcPrePrice(SuitVO suit) {
        if (suit == null) {
            return null;
        }
        OrderPrePriceVO vo = new OrderPrePriceVO();
        vo.setDepositPrice(suit.getDepositAmount());
        vo.setPayAmount(vo.getDepositPrice());
        return vo;
    }

    /**
     * 判断两个价格是否一致
     * @param a 价格A
     * @param b 价格B
     * @return 是否一致
     */
    public static boolean isEquals(OrderPrePriceVO a, OrderPrePriceVO b) {
        if (a == null || b == null) {
            return false;
        }
        return MathUtils.equals(a.getDepositPrice(), b.getDepositPrice())
            && MathUtils.equals(a.getPayAmount(), b.getPayAmount());
    }


    /**
     * 计算订单费用
     * @param order 订单
     * @param area 运营区
     * @param inParkingVO 还车点
     * @param endTime 结束时间
     * @return 结果
     */
    public static OrderFeeVO calcOrderFee(OrderVO order, AreaVO area, OrderInParkingVO inParkingVO, LocalDateTime endTime) {
        OrderFeeVO vo = new OrderFeeVO();

        // 骑行费
        Duration duration = Duration.between(order.getStartTime(), endTime);
        long seconds = duration.getSeconds();   // 使用时长
        Integer freeRideMinutes = order.getSuitFreeRideTime();  // 免费骑行时长
        boolean isFree = freeRideMinutes != null && seconds <= freeRideMinutes * 60;  // 是否免费

        // 若免费，则骑行费为0
        if (isFree) {
            vo.setRidingFee(BigDecimal.ZERO);
        }
        // 否则，计算骑行费
        else {
            SuitRentalUnit rentalUnit = SuitRentalUnit.parse(order.getSuitRentalUnit());
            if (SuitRidingRule.START_FEE.getCode().equals(order.getSuitRidingRule())) {
                vo.setRidingFee(SuitUtil.calcAmountForStartFee(seconds, order.getSuitStartRule(), rentalUnit));
            } else {
                vo.setRidingFee(SuitUtil.calcAmountForIntervalFee(seconds, order.getSuitIntervalRule(), rentalUnit));
            }
        }

        // 剩余押金金额
        BigDecimal surplusDepositFee = MathUtils.subtractDecimal(
            order.getDepositFee(),
            vo.getRidingFee()
        );

        // 运营区外调度费
        if (!inParkingVO.getInArea()) {
            BigDecimal manageFee = area.getVehicleManagementFee();
            manageFee = MathUtils.min(manageFee, surplusDepositFee);
            if (manageFee == null) {
                manageFee = BigDecimal.ZERO;
            }
            vo.setManageFee(manageFee);
        }
        // 停车点外调度费
        else if (!inParkingVO.getInParking()) {
            BigDecimal dispatchFee = area.getDispatchFee();
            dispatchFee = MathUtils.min(dispatchFee, surplusDepositFee);
            if (dispatchFee == null) {
                dispatchFee = BigDecimal.ZERO;
            }
            vo.setDispatchFee(dispatchFee);
        }

        // 总费用
        vo.setTotalFee(MathUtils.addDecimal(
                vo.getRidingFee(),
                vo.getDispatchFee(),
                vo.getManageFee()
        ));

        return vo;
    }

    /**
     * 获取在停车点信息
     * @param area 运营区
     * @param areaSubList 运营区子区域列表
     * @param device 设备
     * @param lon 手机定位经度
     * @param lat 手机定位纬度
     * @return
     */
    public static OrderInParkingVO getInParkingVO(AreaVO area, List<AreaSubVO> parkingList, List<AreaSubVO> noParkingList, DeviceVO device, BigDecimal lon, BigDecimal lat) {
        if (device == null) {
            return null;
        }
        OrderInParkingVO vo = new OrderInParkingVO();
        BigDecimal areaError = area == null ? BigDecimal.ZERO : area.getError();
        BigDecimal deviceLon = device.getLongitude();
        BigDecimal deviceLat = device.getLatitude();

        // 通过设备定位获取所在停车点
        AreaSubVO deviceAreaSub = AreaSubUtil.getInAreaSub(parkingList, deviceLon, deviceLat, areaError);
        vo.setDeviceAreaSub(deviceAreaSub);
        // 通过手机定位获取所在停车点
        AreaSubVO mobileAreaSub = AreaSubUtil.getInAreaSub(parkingList, lon, lat, areaError);
        vo.setMobileAreaSub(mobileAreaSub);
        // 是否在停车点
        boolean inParking = deviceAreaSub != null || mobileAreaSub != null;
        vo.setInParking(inParking);

        // 实际停车点
        if (deviceAreaSub != null) {
            vo.setActualAreaSub(deviceAreaSub);
            vo.setActualLon(device.getLongitude());
            vo.setActualLat(device.getLatitude());
        } else if (mobileAreaSub != null) {
            vo.setActualAreaSub(mobileAreaSub);
            vo.setActualLon(lon);
            vo.setActualLat(lat);
        }

        // 通过设备定位获取是否在禁停区
        AreaSubVO deviceNoParking = AreaSubUtil.getInAreaSub(noParkingList, deviceLon, deviceLat, areaError);
        vo.setDeviceNoParking(deviceNoParking);
        // 通过手机定位获取是否在禁停区
        AreaSubVO mobileNoParking = AreaSubUtil.getInAreaSub(noParkingList, lon, lat, areaError);
        vo.setMobileNoParking(mobileNoParking);
        // 是否在禁停区
        boolean inNoParking = deviceNoParking != null || mobileNoParking != null;
        vo.setInNoParking(inNoParking);

        // 通过设备定位获取是否在运营区
        boolean deviceInArea = AreaUtil.isInAreaMax(area, deviceLon, deviceLat);  // 是否在运营区
        vo.setDeviceInArea(deviceInArea);
        // 通过手机定位获取是否在运营区
        boolean mobileInArea = AreaUtil.isInAreaMax(area, lon, lat);  // 是否在运营区
        vo.setMobileInArea(mobileInArea);
        // 是否在运营区
        boolean inArea = deviceInArea || mobileInArea;
        vo.setInArea(inArea);

        return vo;
    }

    public static BigDecimal calcCanRefundAmount(OrderVO order) {
        if (order == null) {
            return BigDecimal.ZERO;
        }
        return MathUtils.subtractDecimal(order.getPayAmount(), order.getPayRefunding(), order.getPayRefunded());
    }

    /**
     * 转为可替换的设备查询
     * @param order
     * @return
     */
    public static DeviceQuery toChangeDeviceQuery(OrderVO order) {
        DeviceQuery query = new DeviceQuery();
        query.setAreaId(order.getAreaId());
        query.setSuitId(order.getSuitId());
        query.setMchId(order.getDeviceMchId());
        query.setStatusList(DeviceStatus.canUse());
        return query;
    }

}
