import IndieSync
import SwiftUI
import SwiftData

/// Create or edit a routine's identity: name, icon, color, and activity type. Mac-
/// native sheet (grouped Form, fixed width, Cancel/Save). The workout-run settings
/// the iOS editor also carries (rest, auto-advance, target heart rate) are omitted —
/// the Mac never runs a workout — but any values already set on the routine are
/// preserved on save, since we rebuild from `RoutineDocument(from:)` and touch only
/// these four fields.
struct MacRoutineEditorSheet: View {
    @Environment(SyncEngine.self) private var syncEngine
    @Environment(\.modelContext) private var modelContext
    @Environment(\.dismiss) private var dismiss

    // Resolve by id, not a captured entity: a clone-on-edit swaps a seed's identity
    // mid-edit. `routineID` is nil in create mode. Mirrors iOS `RoutineAddEditView`.
    @State private var routineID: String?
    @Query private var routines: [Routine]

    @State private var name: String
    @State private var color: String
    @State private var systemImage: String
    @State private var activityType: WorkoutActivityType

    var isEditing: Bool { routineID != nil }

    init(routine: Routine?) {
        _routineID = State(initialValue: routine?.id)
        _name = State(initialValue: routine?.name ?? "")
        _color = State(initialValue: routine?.color ?? "indigo")
        _systemImage = State(initialValue: routine?.systemImage ?? "dumbbell.fill")
        _activityType = State(initialValue: routine?.activityTypeEnum ?? .traditionalStrength)
    }

    private var routine: Routine? {
        guard let routineID else { return nil }
        let id = syncEngine.currentRoutineID(for: routineID)
        return routines.first { $0.id == id }
    }

    var body: some View {
        NavigationStack {
            Form {
                Section("Name") {
                    TextField("Name", text: $name)
                    if let routineID, SeedLibrary.isSeed(id: routineID) {
                        Text("Saving changes to a starter routine creates your own copy; the starter stays available in the gallery.")
                            .font(.caption)
                            .foregroundStyle(.secondary)
                    }
                }

                Section("Icon") {
                    IconGridPicker(selection: $systemImage, tint: Color.color(from: color))
                }

                Section("Color") {
                    ColorSwatchPicker(selection: $color)
                }

                Section {
                    Picker("Activity Type", selection: $activityType) {
                        ForEach(WorkoutActivityType.allCases, id: \.self) { type in
                            Label(type.displayName, systemImage: type.systemImage).tag(type)
                        }
                    }
                } header: {
                    Text("Activity Type")
                } footer: {
                    Text("Determines how this workout is categorized in Apple Health and how it credits your Activity rings.")
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }
            }
            .formStyle(.grouped)
            .navigationTitle(isEditing ? "Edit Routine" : "New Routine")
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Cancel") { dismiss() }
                }
                ToolbarItem(placement: .confirmationAction) {
                    Button("Save") { save(); dismiss() }
                        .disabled(name.trimmingCharacters(in: .whitespaces).isEmpty)
                }
            }
        }
        .frame(width: 460, height: 520)
    }

    private func save() {
        if isEditing {
            guard let routine else { return }
            var doc = RoutineDocument(from: routine)
            doc.name = name
            doc.color = color
            doc.systemImage = systemImage
            doc.activityType = activityType.rawValue
            doc.updatedAt = Date()
            Task { await syncEngine.save(routine: doc) }
        } else {
            let existing = (try? modelContext.fetch(FetchDescriptor<Routine>())) ?? []
            let now = Date()
            let doc = RoutineDocument(
                schemaVersion: RoutineDocument.currentSchemaVersion,
                id: ULID.make(),
                name: name,
                color: color,
                systemImage: systemImage,
                order: existing.count,
                createdAt: now,
                updatedAt: now,
                exercises: [],
                activityType: activityType.rawValue
            )
            Task { await syncEngine.save(routine: doc) }
        }
    }
}

/// A grid of the curated `availableIcons`, single-select, with the chosen one ringed.
private struct IconGridPicker: View {
    @Binding var selection: String
    let tint: Color

    private let columns = [GridItem(.adaptive(minimum: 44), spacing: 8)]

    var body: some View {
        LazyVGrid(columns: columns, spacing: 8) {
            ForEach(availableIcons, id: \.self) { icon in
                Button {
                    selection = icon
                } label: {
                    Image(systemName: icon)
                        .font(.title3)
                        .foregroundStyle(icon == selection ? tint : .secondary)
                        .frame(width: 40, height: 40)
                        .background(
                            (icon == selection ? tint.opacity(0.15) : Color.secondary.opacity(0.08)),
                            in: RoundedRectangle(cornerRadius: 8)
                        )
                        .overlay(
                            RoundedRectangle(cornerRadius: 8)
                                .strokeBorder(tint, lineWidth: icon == selection ? 2 : 0)
                        )
                }
                .buttonStyle(.plain)
            }
        }
        .padding(.vertical, 4)
    }
}

/// A row of the canonical `availableColors` as tappable swatches, single-select.
private struct ColorSwatchPicker: View {
    @Binding var selection: String

    private let columns = [GridItem(.adaptive(minimum: 36), spacing: 10)]

    var body: some View {
        LazyVGrid(columns: columns, spacing: 10) {
            ForEach(availableColors, id: \.self) { name in
                Button {
                    selection = name
                } label: {
                    Circle()
                        .fill(Color.color(from: name))
                        .frame(width: 28, height: 28)
                        .overlay(
                            Circle()
                                .strokeBorder(.primary, lineWidth: name == selection ? 2 : 0)
                                .padding(-2)
                        )
                }
                .buttonStyle(.plain)
                .help(name.capitalized)
            }
        }
        .padding(.vertical, 4)
    }
}
