import Foundation
import SwiftData

/// Represents when a ritual is typically performed during the day.
/// Used for sorting and display purposes.
enum TimeOfDay: String, Codable, CaseIterable, Comparable {
    case morning    // Before 11am
    case midday     // 11am - 2pm
    case afternoon  // 2pm - 5pm
    case evening    // 5pm - 9pm
    case night      // After 9pm
    case anytime    // Flexible timing
    
    var displayName: String {
        switch self {
        case .morning: return String(localized: "Morning")
        case .midday: return String(localized: "Midday")
        case .afternoon: return String(localized: "Afternoon")
        case .evening: return String(localized: "Evening")
        case .night: return String(localized: "Night")
        case .anytime: return String(localized: "Anytime")
        }
    }
    
    /// Time range description for this time of day
    var timeRange: String {
        switch self {
        case .morning: return String(localized: "Before 11am")
        case .midday: return String(localized: "11am – 2pm")
        case .afternoon: return String(localized: "2pm – 5pm")
        case .evening: return String(localized: "5pm – 9pm")
        case .night: return String(localized: "After 9pm")
        case .anytime: return String(localized: "Always visible")
        }
    }
    
    /// Combined display name with time range
    var displayNameWithRange: String {
        "\(displayName) (\(timeRange))"
    }
    
    var symbolName: String {
        switch self {
        case .morning: return "sunrise.fill"
        case .midday: return "sun.max.fill"
        case .afternoon: return "sun.haze.fill"
        case .evening: return "sunset.fill"
        case .night: return "moon.stars.fill"
        case .anytime: return "clock.fill"
        }
    }
    
    /// Sort order for displaying rituals by time of day
    var sortOrder: Int {
        switch self {
        case .morning: return 0
        case .midday: return 1
        case .afternoon: return 2
        case .evening: return 3
        case .night: return 4
        case .anytime: return 5
        }
    }
    
    /// Comparable conformance for sorting
    static func < (lhs: TimeOfDay, rhs: TimeOfDay) -> Bool {
        lhs.sortOrder < rhs.sortOrder
    }
}

/// A ritual represents a persistent habit-building journey. It contains multiple
/// arcs, each representing a time-bound period with its own habits and completions.
/// This allows rituals to be renewed while preserving historical accuracy.
@Model
final class Ritual {
    var id: UUID = UUID()
    var title: String = ""
    var theme: String = ""
    var notes: String = ""
    
    // Default duration for new arcs
    var defaultDurationDays: Int = 28
    
    // Scheduling
    var timeOfDay: TimeOfDay = TimeOfDay.anytime
    
    // Organization
    var iconName: String = "sparkles"
    var category: String = ""
    
    // Arcs - each arc represents a time-bound period with its own habits
    @Relationship(deleteRule: .cascade)
    var arcs: [RitualArc]? = []

    init(
        id: UUID = UUID(),
        title: String,
        theme: String,
        defaultDurationDays: Int = 28,
        notes: String = "",
        timeOfDay: TimeOfDay = .anytime,
        iconName: String = "sparkles",
        category: String = "",
        arcs: [RitualArc] = []
    ) {
        self.id = id
        self.title = title
        self.theme = theme
        self.defaultDurationDays = defaultDurationDays
        self.notes = notes
        self.timeOfDay = timeOfDay
        self.iconName = iconName
        self.category = category
        self.arcs = arcs
    }
    
    // MARK: - Computed Properties
    
    /// The currently active arc, if any.
    var currentArc: RitualArc? {
        arcs?.first { $0.isActive }
    }
    
    /// Whether this ritual has an active arc in progress.
    var hasActiveArc: Bool {
        currentArc != nil
    }
    
    /// All arcs sorted by start date (newest first).
    var sortedArcs: [RitualArc] {
        (arcs ?? []).sorted { $0.startDate > $1.startDate }
    }
    
    /// The most recent arc (active or completed).
    var latestArc: RitualArc? {
        sortedArcs.first
    }
    
    /// Total number of completed arcs.
    var completedArcCount: Int {
        (arcs ?? []).filter { !$0.isActive }.count
    }
    
    /// The end date of the most recently completed arc, if any.
    var lastCompletedDate: Date? {
        (arcs ?? []).filter { !$0.isActive }
            .sorted { $0.endDate > $1.endDate }
            .first?.endDate
    }
    
    // MARK: - Convenience Accessors (for current arc)
    
    /// Habits from the current arc (empty if no active arc).
    var habits: [ArcHabit] {
        currentArc?.habits ?? []
    }
    
    /// Start date of the current arc.
    var startDate: Date {
        currentArc?.startDate ?? Date()
    }
    
    /// Duration of the current arc in days.
    var durationDays: Int {
        currentArc?.durationDays ?? defaultDurationDays
    }
    
    /// End date of the current arc.
    var endDate: Date {
        currentArc?.endDate ?? Date()
    }
    
    // MARK: - Arc Queries
    
    /// Returns the arc that was active on a specific date, if any.
    func arc(for date: Date) -> RitualArc? {
        (arcs ?? []).first { $0.contains(date: date) }
    }
    
    /// Returns all arcs that overlap with a date range.
    func arcs(in range: ClosedRange<Date>) -> [RitualArc] {
        (arcs ?? []).filter { arc in
            // Arc overlaps if its range intersects with the query range
            arc.endDate >= range.lowerBound && arc.startDate <= range.upperBound
        }
    }
}
