import Foundation
import SwiftData

/// Represents a time-bound period of a ritual. Each arc has its own habits and
/// completion tracking. When a ritual is renewed, a new arc is created while
/// the old arc's data remains frozen for historical accuracy.
@Model
final class RitualArc {
    var id: UUID = UUID()
    var startDate: Date = Date()
    var endDate: Date = Date()
    var arcNumber: Int = 1
    var isActive: Bool = true
    
    @Relationship(deleteRule: .cascade)
    var habits: [ArcHabit]? = []
    
    @Relationship(inverse: \Ritual.arcs)
    var ritual: Ritual?

    init(
        id: UUID = UUID(),
        startDate: Date = Date(),
        endDate: Date,
        arcNumber: Int = 1,
        isActive: Bool = true,
        habits: [ArcHabit] = []
    ) {
        self.id = id
        self.startDate = startDate
        self.endDate = endDate
        self.arcNumber = arcNumber
        self.isActive = isActive
        self.habits = habits
    }
    
    /// Convenience initializer using duration in days.
    convenience init(
        startDate: Date = Date(),
        durationDays: Int,
        arcNumber: Int = 1,
        isActive: Bool = true,
        habits: [ArcHabit] = []
    ) {
        let calendar = Calendar.current
        let start = calendar.startOfDay(for: startDate)
        let end = calendar.date(byAdding: .day, value: durationDays - 1, to: start) ?? start
        
        self.init(
            startDate: start,
            endDate: end,
            arcNumber: arcNumber,
            isActive: isActive,
            habits: habits
        )
    }
    
    /// The number of days in this arc.
    var durationDays: Int {
        let calendar = Calendar.current
        let days = calendar.dateComponents([.day], from: startDate, to: endDate).day ?? 0
        return days + 1
    }
    
    /// Checks if a specific date falls within this arc's date range.
    func contains(date: Date) -> Bool {
        let calendar = Calendar.current
        let checkDate = calendar.startOfDay(for: date)
        let start = calendar.startOfDay(for: startDate)
        let end = calendar.startOfDay(for: endDate)
        return checkDate >= start && checkDate <= end
    }
    
    /// Returns the day index (1-based) for a given date within this arc.
    func dayIndex(for date: Date) -> Int {
        let calendar = Calendar.current
        let checkDate = calendar.startOfDay(for: date)
        let start = calendar.startOfDay(for: startDate)
        let days = calendar.dateComponents([.day], from: start, to: checkDate).day ?? 0
        return max(1, min(days + 1, durationDays))
    }
    
    /// Creates a new arc that continues from this one with the same habits.
    /// - Parameter durationDays: The duration for the new arc (defaults to same as this arc)
    /// - Returns: A new arc with copied habits and incremented arc number
    func createRenewalArc(durationDays: Int? = nil) -> RitualArc {
        let calendar = Calendar.current
        let newStartDate = calendar.date(byAdding: .day, value: 1, to: endDate) ?? Date()
        let newDuration = durationDays ?? self.durationDays
        
        let copiedHabits = (habits ?? []).map { $0.copyForNewArc() }
        
        return RitualArc(
            startDate: newStartDate,
            durationDays: newDuration,
            arcNumber: arcNumber + 1,
            isActive: true,
            habits: copiedHabits
        )
    }
}
