import IndieSync
import SwiftUI
import SwiftData

/// Add or edit a schedule: pick a routine, choose a recurrence (once / daily / fixed
/// days), tag it with a goal, and optionally set a reminder time. Mac-native sheet
/// (grouped Form, fixed width, Cancel/Save) — mirrors iOS `ScheduleAddEditView` minus
/// the "Now" start-immediately choice (the Mac never runs a workout) and the
/// notification-permission footer (the Mac never schedules a notification; the
/// iPhone's `ReminderScheduler` resyncs once it observes this document). Fields are
/// snapshotted in `init` so the sheet never holds the live entity.
struct MacScheduleEditorSheet: View {
    @Environment(SyncEngine.self) private var syncEngine
    @Environment(\.modelContext) private var modelContext
    @Environment(\.dismiss) private var dismiss

    @Query(sort: [SortDescriptor(\Routine.order), SortDescriptor(\Routine.name)])
    private var routines: [Routine]

    /// nil id → add mode; a value → edit mode (id / order / createdAt preserved).
    @State private var scheduleID: String?
    @State private var order: Int
    @State private var createdAt: Date
    @State private var routineID: String
    /// The schedule's routine name when it was created — surfaced when that routine
    /// has since been deleted so the user knows what they're reassigning. Mirrors iOS.
    @State private var originalRoutineName: String
    @State private var goal: GoalKind?
    @State private var recurrence: ScheduleRecurrence
    @State private var weekdays: Set<Int>
    @State private var date: Date
    @State private var reminderEnabled: Bool
    @State private var reminderTime: Date

    init(schedule: Schedule?) {
        _scheduleID = State(initialValue: schedule?.id)
        _order = State(initialValue: schedule?.order ?? 0)
        _createdAt = State(initialValue: schedule?.createdAt ?? Date())
        _routineID = State(initialValue: schedule?.routineID ?? "")
        _originalRoutineName = State(initialValue: schedule?.routineName ?? "")
        _goal = State(initialValue: schedule?.goalKind)
        _recurrence = State(initialValue: schedule?.recurrenceEnum ?? .once)
        _weekdays = State(initialValue: Set(schedule?.weekdays ?? []))
        _date = State(initialValue: schedule?.date ?? Date())
        _reminderEnabled = State(initialValue: schedule?.reminderMinutes != nil)
        _reminderTime = State(initialValue: ScheduleEditing.time(fromMinutes: schedule?.reminderMinutes))
    }

    private var isEditing: Bool { scheduleID != nil }

    /// The live routine currently selected, following the seed clone-on-edit redirect
    /// (a schedule made against a starter seed keeps the retired seed id after the
    /// routine is edited); nil when the routine has been deleted. Mirrors iOS
    /// `ScheduleAddEditView.selectedRoutine`.
    private var selectedRoutine: Routine? {
        guard !routineID.isEmpty else { return nil }
        let liveID = syncEngine.currentRoutineID(for: routineID)
        return routines.first { $0.id == liveID }
    }

    private var canSave: Bool {
        guard selectedRoutine != nil else { return false }
        if recurrence == .fixedDays { return !weekdays.isEmpty }
        return true
    }

    var body: some View {
        NavigationStack {
            Form {
                routineSection
                recurrenceSection
                goalSection
                reminderSection
            }
            .formStyle(.grouped)
            .navigationTitle(isEditing ? "Edit Schedule" : "New Schedule")
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Cancel") { dismiss() }
                }
                ToolbarItem(placement: .confirmationAction) {
                    Button("Save", action: save)
                        .disabled(!canSave)
                }
            }
            .onAppear {
                // Default to the first routine when adding (the @Query isn't populated at init).
                if routineID.isEmpty { routineID = routines.first?.id ?? "" }
            }
        }
        .frame(width: 460, height: 560)
    }

    // MARK: - Sections

    private var routineSection: some View {
        Section {
            Picker("Routine", selection: routineSelectionBinding) {
                if selectedRoutine == nil {
                    Text("Please select").tag("")
                }
                ForEach(routines) { routine in
                    Label(routine.name, systemImage: routine.systemImage)
                        .tag(routine.id)
                }
            }
            .labelsHidden()
        } header: {
            Text("Routine")
        } footer: {
            if selectedRoutine == nil, !originalRoutineName.isEmpty {
                Text("\"\(originalRoutineName)\" is no longer available. Choose a routine.")
                    .font(.caption)
                    .foregroundStyle(.secondary)
            }
        }
    }

    /// The Picker always shows the *resolved* current selection (following a
    /// clone-on-edit redirect), but writes back the raw id the user picked — save()
    /// re-resolves through `selectedRoutine` regardless.
    private var routineSelectionBinding: Binding<String> {
        Binding(
            get: { selectedRoutine?.id ?? "" },
            set: { routineID = $0 }
        )
    }

    @ViewBuilder
    private var recurrenceSection: some View {
        Section {
            Picker("When", selection: $recurrence) {
                ForEach(ScheduleRecurrence.allCases, id: \.self) { r in
                    Text(r.displayName).tag(r)
                }
            }
            .pickerStyle(.segmented)
            .labelsHidden()

            switch recurrence {
            case .daily:
                EmptyView()
            case .once:
                DatePicker("Date", selection: $date, displayedComponents: .date)
                    .datePickerStyle(.field)
            case .fixedDays:
                weekdayPicker
            }
        } header: {
            Text("When")
        }
    }

    private var goalSection: some View {
        Section {
            Picker("Goal", selection: $goal) {
                Text("None").tag(GoalKind?.none)
                ForEach(GoalKind.orderedCases()) { kind in
                    Label(kind.displayName, systemImage: kind.systemImage)
                        .foregroundStyle(Color.color(from: kind.colorName))
                        .tag(GoalKind?.some(kind))
                }
            }
        } header: {
            Text("Goal")
        }
    }

    private var reminderSection: some View {
        Section {
            Toggle("Remind Me", isOn: $reminderEnabled)
            if reminderEnabled {
                DatePicker("Time", selection: $reminderTime, displayedComponents: .hourAndMinute)
                    .datePickerStyle(.field)
            }
        } header: {
            Text("Reminder")
        } footer: {
            Text("The Mac doesn't send reminders itself — your iPhone schedules the notification once it syncs this schedule.")
                .font(.caption)
                .foregroundStyle(.secondary)
        }
    }

    /// A row of toggleable weekday chips, Monday-first. Mirrors iOS
    /// `ScheduleAddEditView.weekdayPicker`.
    private var weekdayPicker: some View {
        HStack(spacing: 6) {
            ForEach(ScheduleEditing.weekdayOrder, id: \.self) { n in
                let on = weekdays.contains(n)
                Button {
                    if on { weekdays.remove(n) } else { weekdays.insert(n) }
                } label: {
                    Text(ScheduleEditing.weekdaySymbols[n - 1])
                        .font(.caption.weight(.semibold))
                        .frame(maxWidth: .infinity)
                        .padding(.vertical, 6)
                        .background(on ? Color.accentColor : Color.secondary.opacity(0.15), in: Capsule())
                        .foregroundStyle(on ? Color.white : Color.primary)
                }
                .buttonStyle(.plain)
            }
        }
        .padding(.vertical, 4)
    }

    // MARK: - Save

    private func save() {
        guard let routine = selectedRoutine else { return }

        let doc = ScheduleDocument(
            schemaVersion: ScheduleDocument.currentSchemaVersion,
            id: scheduleID ?? ULID.make(),
            routineID: routine.id,
            routineName: routine.name,
            goal: goal?.rawValue,
            recurrence: recurrence.rawValue,
            weekdays: recurrence == .fixedDays ? weekdays.sorted() : nil,
            date: recurrence == .once ? date : nil,
            reminderMinutes: reminderEnabled ? ScheduleEditing.minutesFromMidnight(of: reminderTime) : nil,
            order: isEditing ? order : ScheduleEditing.nextOrder(in: modelContext),
            createdAt: createdAt,
            updatedAt: Date()
        )
        Task { await syncEngine.save(schedule: doc) }
        dismiss()
    }
}
