import java.time.LocalDateTime;
import java.time.Duration;

public class CalculoTarifa {

    //originalmente calculaba el monto total aquí y en Main, pero codex sugirió mantener cálculos fuera de main. El prompt fué: "Remove the duplicate and adjust the text."
    public static class DetalleCobro {
        private long minutos;
        private int tarifaAplicada;
        private long unidCobro;
        private int subtotal;
        private int descuento;
        private int total;

        public DetalleCobro(long minutos, int tarifaAplicada, long unidCobro, int subtotal, int descuento, int total) {
            this.minutos = minutos;
            this.tarifaAplicada = tarifaAplicada;
            this.unidCobro = unidCobro;
            this.subtotal = subtotal;
            this.descuento = descuento;
            this.total = total;
        }

        public long getMinutos() {
            return minutos;
        }

        public int getTarifaAplicada() {
            return tarifaAplicada;
        }

        public long getUnidCobro() {
            return unidCobro;
        }

        public int getSubtotal() {
            return subtotal;
        }

        public int getDescuento() {
            return descuento;
        }

        public int getTotal() {
            return total;
        }
    }

    public int calcularMonto(TiqueteParqueo t) {
        DetalleCobro detalle = calcularDetalle(t);
        t.setMontoTotal(detalle.getTotal());
        return detalle.getTotal();
    }

    public DetalleCobro calcularDetalle(TiqueteParqueo t) {
        long minutos = calcularMinCobro(t);
        int tarifa = obtenerTarifa(t);
        long unidades = getUnidadCobro(minutos, t.getModalidad());
        int subtotal = (int) (unidades * tarifa);
        int descuento = calcularDescuento(t.getModalidad(), unidades, subtotal);
        int total = subtotal - descuento;
        return new DetalleCobro(minutos, tarifa, unidades, subtotal, descuento, total);
    }

    // Obtiene la tarifa segun tipo (1=Auto, 2=Moto, 3=Camion)
    private int obtenerTarifa(TiqueteParqueo t) {

        TiqueteParqueo.TipoServicio modalidad = t.getModalidad();
        int tipo = t.getVehiculo().getTipo();

        if (modalidad == TiqueteParqueo.TipoServicio.POR_HORA) {
            if (tipo == 2) {
                return 500;
            } else if (tipo == 1 || tipo == 3) {
                return 600;
            }
        }

        if (modalidad == TiqueteParqueo.TipoServicio.POR_DIA) {
            if (tipo == 2) {
                return 3000;
            } else if (tipo == 1 || tipo == 3) {
                return 5000;
            }
        }

        throw new IllegalArgumentException("Tipo de vehículo o modalidad inválidos.");
    }

    private long calcularMinCobro(TiqueteParqueo t) {
        LocalDateTime horaEntrada = t.getHoraEntrada();
        LocalDateTime horaSalida = t.getHoraSalida();

        if (horaSalida.isBefore(horaEntrada)) { //excepción recomendada por codex
            throw new IllegalArgumentException("La hora de salida no puede ser anterior a la hora de entrada.");
        }

        long minutos = Duration.between(horaEntrada, horaSalida).toMinutes();
        if (minutos == 0) {
            return 1;
        }
        return minutos;
    }

    private long getUnidadCobro(long minutos, TiqueteParqueo.TipoServicio modalidad) {
        if (modalidad == TiqueteParqueo.TipoServicio.POR_HORA) {
            return (minutos + 59) / 60;
        }
        return (minutos + 1439) / 1440;
    }

    private int calcularDescuento(TiqueteParqueo.TipoServicio modalidad, long unidades, int subtotal) {
        if (modalidad == TiqueteParqueo.TipoServicio.POR_HORA && unidades > 8) {
            return subtotal * 10 / 100;
        }
        return 0;
    }

}
