package dev.lions.unionflow.server.api.dto.dashboard;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;

/**
 * DTO pour les événements à venir du dashboard
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UpcomingEventResponse {

    @JsonProperty("id")
    private String id;

    @JsonProperty("title")
    private String title;

    @JsonProperty("description")
    private String description;

    @JsonProperty("startDate")
    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
    private LocalDateTime startDate;

    @JsonProperty("endDate")
    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
    private LocalDateTime endDate;

    @JsonProperty("location")
    private String location;

    @JsonProperty("maxParticipants")
    private Integer maxParticipants;

    @JsonProperty("currentParticipants")
    private Integer currentParticipants;

    @JsonProperty("status")
    private String status;

    @JsonProperty("imageUrl")
    private String imageUrl;

    @JsonProperty("tags")
    private List<String> tags;

    // Méthodes utilitaires
    public String getDaysUntilEvent() {
        return getDaysUntilEvent(LocalDateTime.now());
    }

    /**
     * Version testable avec une date de référence fixe (même package).
     */
    String getDaysUntilEvent(LocalDateTime now) {
        if (startDate == null) {
            return "";
        }
        long days = ChronoUnit.DAYS.between(now.toLocalDate(), startDate.toLocalDate());
        long hours = ChronoUnit.HOURS.between(now, startDate);

        if (days < 0) {
            return "En cours";
        }
        if (days == 0) {
            // Vérifier si l'événement est déjà passé (même si moins d'1h)
            if (startDate.isBefore(now)) {
                return "En cours";
            } else if (hours < 2) {
                return "Bientôt";
            } else {
                return "Aujourd'hui";
            }
        } else if (days == 1) {
            return "Demain";
        } else if (days < 7) {
            return "Dans " + days + " jours";
        } else {
            long weeks = days / 7;
            return "Dans " + weeks + " semaine" + (weeks > 1 ? "s" : "");
        }
    }

    public Double getFillPercentage() {
        if (maxParticipants == null || currentParticipants == null || maxParticipants == 0) {
            return 0.0;
        }
        return (double) currentParticipants / maxParticipants * 100;
    }

    public Boolean getIsFull() {
        if (maxParticipants == null || currentParticipants == null) {
            return false;
        }
        return currentParticipants >= maxParticipants;
    }

    public Boolean getIsAlmostFull() {
        Double fillPercentage = getFillPercentage();
        return fillPercentage >= 80.0 && fillPercentage < 100.0;
    }

    public Boolean getIsToday() {
        if (startDate == null) {
            return false;
        }
        
        LocalDateTime now = LocalDateTime.now();
        return startDate.toLocalDate().equals(now.toLocalDate());
    }

    public Boolean getIsTomorrow() {
        if (startDate == null) {
            return false;
        }
        
        LocalDateTime now = LocalDateTime.now();
        return startDate.toLocalDate().equals(now.toLocalDate().plusDays(1));
    }

    public String getStatusColor() {
        if (status == null) {
            return "#6B7280"; // grey
        }

        switch (status.toLowerCase()) {
            case "confirmed":
                return "#10B981"; // success
            case "open":
                return "#3B82F6"; // info
            case "cancelled":
                return "#EF4444"; // error
            case "postponed":
                return "#F59E0B"; // warning
            default:
                return "#6B7280"; // grey
        }
    }

    public String getStatusLabel() {
        if (status == null) {
            return "Inconnu";
        }

        switch (status.toLowerCase()) {
            case "confirmed":
                return "Confirmé";
            case "open":
                return "Ouvert";
            case "cancelled":
                return "Annulé";
            case "postponed":
                return "Reporté";
            default:
                return status;
        }
    }

    public Integer getAvailableSpots() {
        if (maxParticipants == null || currentParticipants == null) {
            return 0;
        }
        return Math.max(0, maxParticipants - currentParticipants);
    }

    public String getParticipationSummary() {
        if (maxParticipants == null || currentParticipants == null) {
            return "0/0 participants";
        }
        return currentParticipants + "/" + maxParticipants + " participants";
    }
}
