import SwiftUI

/// The bundled exercise-library browser: a Mac-native two-pane layout over the same
/// `ExerciseCatalog` sections and search the iOS Library tab uses
/// (`Workouts/Views/Exercises/ExerciseLibraryView.swift`), but browse-only — no
/// machine-settings editor, no weight-progression chart, no workout history. The left
/// pane is a searchable, section-grouped list with a single selection; the right pane
/// shows the selected exercise's animated figure and reference info, the same
/// components/entry points iOS uses (`ExerciseFigureSlot`, `ExerciseInfoContent`).
struct MacExercisesBrowserView: View {
    @State private var searchText = ""
    @State private var selection: String?

    private var sections: [ExerciseCatalogSection] {
        ExerciseCatalog.sections(matching: searchText)
    }

    var body: some View {
        HSplitView {
            list
                .frame(minWidth: 220, idealWidth: 260, maxWidth: 340)
            detail
                .frame(minWidth: 420, maxWidth: .infinity, maxHeight: .infinity)
        }
        .navigationTitle("Exercises")
        .searchable(text: $searchText, prompt: "Name, category, or muscle")
    }

    // MARK: - List

    @ViewBuilder
    private var list: some View {
        if sections.isEmpty {
            ContentUnavailableView.search(text: searchText)
        } else {
            List(selection: $selection) {
                ForEach(sections, id: \.title) { section in
                    Section(section.title) {
                        ForEach(section.names, id: \.self) { name in
                            Text(name)
                                .tag(name)
                        }
                    }
                }
            }
        }
    }

    // MARK: - Detail

    @ViewBuilder
    private var detail: some View {
        if let selection {
            MacExerciseDetailView(exerciseName: selection)
                // Reseed the detail's own state when the selection changes.
                .id(selection)
        } else {
            ContentUnavailableView(
                "Select an Exercise",
                systemImage: "figure.strengthtraining.traditional",
                description: Text("Choose an exercise from the list to see how it's performed.")
            )
        }
    }
}

/// One library exercise, browse-only: the animated form-guide figure (when a bundled
/// motion rig matches the name) over the authored reference copy (when a bundled
/// `info.md` matches). Either — or both — can be absent for a given exercise, so each
/// half degrades gracefully instead of leaving blank space, mirroring how the iOS
/// detail screen simply omits what it doesn't have (`ExerciseLibraryDetailView`).
private struct MacExerciseDetailView: View {
    let exerciseName: String

    /// Cheap presence check — a name-set lookup against the bundle enumeration
    /// `ExerciseMotionLibrary.exerciseNames` already did once, rather than
    /// `resources(for:)`'s two bundle reads + two JSON decodes just to answer a Bool.
    private var hasFigure: Bool {
        ExerciseMotionLibrary.exerciseNames.contains(exerciseName)
    }

    var body: some View {
        let info = ExerciseInfoLibrary.info(for: exerciseName)
        let hasFigure = hasFigure

        ScrollView {
            VStack(alignment: .leading, spacing: 20) {
                if hasFigure || info == nil {
                    figureArea(hasFigure: hasFigure)
                }
                if let info {
                    ExerciseInfoContent(info: info)
                } else if hasFigure {
                    Text("No reference guide written for this exercise yet.")
                        .font(.callout)
                        .foregroundStyle(.secondary)
                }
            }
            .padding(24)
            .frame(maxWidth: .infinity, alignment: .leading)
        }
        .navigationTitle(exerciseName)
    }

    /// The figure, sized generously for the Mac detail pane, or — when neither a
    /// motion rig nor reference info exists for this name — a single combined empty
    /// state rather than two stacked placeholders.
    @ViewBuilder
    private func figureArea(hasFigure: Bool) -> some View {
        if hasFigure {
            ExerciseFigureSlot(exerciseName: exerciseName)
                .frame(maxWidth: .infinity)
                .frame(height: 260)
        } else {
            ContentUnavailableView(
                exerciseName,
                systemImage: "figure.strengthtraining.traditional",
                description: Text("No animated guide or reference info is available for this exercise yet.")
            )
            .frame(maxWidth: .infinity)
        }
    }
}
