import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public class Location {
// ── Attributs privés ──
private int id;
private Vehicule voiture;
private Client client;
private LocalDate dateDebut;
private LocalDate dateFin; // date de fin prévue
private LocalDate dateRetour; // date réelle de retour (null si pas encore rendu)
private double prixTotal;
private StatutLocation statut;
// ── Compteur statique pour les IDs ──
private static int compteur = 0;
// ── Constructeur ──
public Location(Vehicule voiture, Client client, LocalDate dateDebut, LocalDate dateFin) {
this.id = ++compteur;
this.voiture = voiture;
this.client = client;
this.dateDebut = dateDebut;
this.dateFin = dateFin;
this.dateRetour = null;
this.statut = StatutLocation.EN_COURS;
this.prixTotal = calculerPrix();
voiture.louer();
}
// ── Méthodes métier ──
// Retourne le nombre de jours prévus (dateDebut -> dateFin)
public long getDuree() {
return ChronoUnit.DAYS.between(dateDebut, dateFin);
}
// Calcule le prix total : durée × prix par jour du véhicule
public double calculerPrix() {
return getDuree() * voiture.getPrixJour();
}
// Vérifie si la location est en retard
public boolean isEnRetard() {
if (dateRetour != null) {
return dateRetour.isAfter(dateFin);
}
return LocalDate.now().isAfter(dateFin);
}
// Retourne la pénalité de retard : jours de retard × prixJour × 1.5
public double getPenaliteRetard() {
if (!isEnRetard()) return 0;
LocalDate reference = (dateRetour != null) ? dateRetour : LocalDate.now();
long joursRetard = ChronoUnit.DAYS.between(dateFin, reference);
return joursRetard * voiture.getPrixJour() * 1.5;
}
// Termine la location : enregistre la date de retour réelle et met à jour le statut
public void terminerLocation() {
this.dateRetour = LocalDate.now();
voiture.retourner();
if (isEnRetard()) {
this.statut = StatutLocation.EN_RETARD;
} else {
this.statut = StatutLocation.TERMINEE;
}
this.prixTotal = calculerPrix() + getPenaliteRetard();
}
// Annule la location (si elle est encore en cours)
public void annulerLocation() {
if (this.statut == StatutLocation.EN_COURS) {
this.statut = StatutLocation.ANNULEE;
voiture.retourner();
}
}
// Affichage formaté
public void afficherLocation() {
System.out.println("──────────────────────────────────");
System.out.println(" Location N° : " + id);
System.out.println(" Client : " + client.getPrenom() + " " + client.getNom());
System.out.println(" Date début : " + dateDebut);
System.out.println(" Date fin prévue : " + dateFin);
System.out.println(" Date retour : " + (dateRetour != null ? dateRetour : "En cours"));
System.out.println(" Durée prévue : " + getDuree() + " jour(s)");
System.out.println(" Prix total : " + prixTotal + " €");
if (isEnRetard()) {
System.out.println(" Pénalité retard : " + getPenaliteRetard() + " €");
}
System.out.println(" Statut : " + statut);
System.out.println("──────────────────────────────────");
}
// ── Getters ──
public int getId() { return id; }
public Vehicule getVoiture() { return voiture; }
public Client getClient() { return client; }
public LocalDate getDateDebut() { return dateDebut; }
public LocalDate getDateFin() { return dateFin; }
public LocalDate getDateRetour() { return dateRetour; }
public double getPrixTotal() { return prixTotal; }
public StatutLocation getStatut() { return statut; }
// ── Setter statut (utile pour forcer un état depuis AgenceLocation) ──
public void setStatut(StatutLocation statut) { this.statut = statut; }
// ── toString ──
@Override
public String toString() {
return "Location #" + id + " | " + client.getNom() + " | " + voiture.toString()
+ " | " + dateDebut + " → " + dateFin + " | " + statut;
}
}