import SwiftUI
import AppKit
import PoseCore

@main
struct PoseReviewApp: App {
    @StateObject private var model = ReviewerModel()
    var body: some Scene {
        WindowGroup("Joint Review") {
            ReviewerView(model: model)
                .frame(minWidth: 1000, minHeight: 650)
                .onAppear {
                    NSApplication.shared.setActivationPolicy(.regular)
                    NSApplication.shared.activate(ignoringOtherApps: true)
                    guard model.document == nil else { return }
                    let args = Array(CommandLine.arguments.dropFirst())
                    if args.count >= 2 {
                        model.load(manifest: URL(fileURLWithPath: args[0]), results: URL(fileURLWithPath: args[1]))
                    } else {
                        model.loadPresets()
                        if let preset = model.presets.first { model.openPreset(preset) }
                        model.discoverSessionsOnLaunch()
                    }
                }
                .alert("Review needs attention", isPresented: Binding(get: { model.error != nil }, set: { if !$0 { model.error = nil } })) {
                    Button("OK") { model.error = nil }
                } message: { Text(model.error ?? "") }
        }
        .defaultSize(width: 1400, height: 900)
        .commands {
            CommandGroup(replacing: .newItem) { Button("Open Session…") { model.openSession() }.keyboardShortcut("o") }
            CommandGroup(replacing: .saveItem) { Button("Save Review") { model.save() }.keyboardShortcut("s") }
            CommandGroup(replacing: .undoRedo) { Button("Undo Review Edit") { model.undo() }.keyboardShortcut("z").disabled(model.undoStack.isEmpty) }
        }
    }
}

struct ReviewerView: View {
    @ObservedObject var model: ReviewerModel
    var body: some View {
        HStack(spacing: 0) {
            VStack(alignment: .leading) {
                Text("PHOTOS").font(.caption).foregroundStyle(.secondary).padding(.horizontal)
                if model.compare {
                    List(selection: Binding<String?>(get: { model.pair?.id }, set: { if let id = $0 { model.selectPair(id) } })) {
                        ForEach(model.pairs) { pair in
                            VStack(alignment: .leading) {
                                Text(pair.id)
                                Text(pair.referenceID == nil ? "No reference rider · Single" : "Rider + Reference rider").font(.caption)
                            }.tag(pair.id)
                        }
                    }
                } else {
                    List(selection: Binding<Int?>(get: { model.index }, set: { if let index = $0 { model.selectFrame(index) } })) {
                        ForEach(Array((model.document?.frames ?? []).enumerated()), id: \.element.id) { index, frame in
                            VStack(alignment: .leading, spacing: 4) {
                                Text("\(frame.pairID) · \(frame.riderDisplayName)")
                                Text("\(frame.edits.count) / 19 reviewed").font(.caption).foregroundStyle(.secondary)
                            }.padding(5).tag(index)
                        }
                    }
                }
                Menu("Sessions") {
                    ForEach(model.presets) { preset in
                        Button(preset.title) { model.openPreset(preset) }
                    }
                }.padding(.horizontal)
                Button(model.isDiscovering ? "Analyzing folders…" : "Check for new folders") { model.discoverSessions() }
                    .disabled(model.isDiscovering).padding(.horizontal)
                Button("Open Session…") { model.openSession() }.padding()

            }.frame(width: 180)
            Divider()
            VStack(alignment: .leading, spacing: 10) {
                HStack {
                    Picker("Review mode", selection: Binding(get: { model.compare }, set: { model.setCompare($0) })) {
                        Text("Single").tag(false); Text("Compare").tag(true)
                    }.pickerStyle(.segmented).frame(width: 190)
                    Picker("Edit", selection: Binding(get: { model.leanMode }, set: { model.setLeanMode($0) })) {
                        Text("Joints").tag(false); Text("Wheel lean").tag(true)
                    }.pickerStyle(.segmented).frame(width: 185)
                    Toggle("Show markers", isOn: $model.showMarkers)
                    Spacer()
                    Button("Inspector") { model.inspectorVisible.toggle() }
                    Button("Undo") { model.undo() }.disabled(model.undoStack.isEmpty)
                }
                if !model.discoveryStatus.isEmpty {
                    HStack {
                        if model.isDiscovering { ProgressView().controlSize(.small) }
                        Text(model.discoveryStatus).font(.caption)
                    }
                }
                if !model.discoveryFailures.isEmpty {
                    DisclosureGroup("Folders needing attention") {
                        ForEach(model.discoveryFailures, id: \.self) { Text($0).font(.caption).textSelection(.enabled) }
                    }
                }
                if model.frame?.rider == SessionDiscovery.unreviewedRiderName {
                    Text("Automatically imported photo · confirm the intended rider before relying on joint markers.")
                        .font(.caption).foregroundStyle(.orange)
                }
                if model.frame != nil {
                    if model.compare { PairComparisonView(model: model) }
                    else {
                        FramePane(model: model, frameID: model.frame!.id)
                        if model.frame?.role == "subject" {
                            ScrollView {
                                if model.report != nil { PairFeedbackView(model: model).padding(.vertical, 8) }
                                else { SinglePhotoFeedbackView(model: model).padding(.vertical, 8) }
                            }.frame(minHeight: 160, idealHeight: 240, maxHeight: 300)
                        }
                        if model.leanMode && (model.frame?.role != "subject" || model.report == nil) {
                            ScrollView { LeanEvidenceView(model: model) }.frame(maxHeight: 160)
                        }
                        if model.pair?.referenceID == nil {
                            Text("No reference rider exists for this photograph. Review it in Single mode.").font(.caption)
                        }
                    }
                    HStack {
                        Menu(model.isDetecting ? "Detecting…" : "Retry detection for active rider") {
                            Button("Original rider crop") { model.retryDetection(fullPhoto: false) }
                            Button("Full photo panel") { model.retryDetection(fullPhoto: true) }
                        }.disabled(model.isDetecting)
                        Text(model.leanMode ? "Drag yellow wheel or cyan reference handles. Release saves; Escape cancels." : model.placing ? "Click the active photo to place the selected joint. Escape cancels." : "Drag to correct; arrows move 1 source pixel, Shift moves 10.").font(.caption)
                    }
                    Text(model.message).font(.caption).foregroundStyle(.secondary)
                } else {
                    ContentUnavailableView("Open a photo session", systemImage: "person.crop.rectangle")
                }
            }.padding()
            if model.inspectorVisible {
                Divider()
                if model.leanMode { LeanReviewView(model: model).frame(width: 290) }
                else { jointInspector.frame(width: 250) }
            }
        }
    }
    private var jointInspector: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("\(model.frame?.riderDisplayName ?? "Joint") · active rider").font(.headline)
            Text("Cyan: unreviewed · green: reviewed\nOrange: uncertain or raw comparison").font(.caption).foregroundStyle(.secondary)
            List(InspectionRenderer.jointNames, id: \.self, selection: $model.selected) { name in
                VStack(alignment: .leading, spacing: 2) {
                    Text("\(InspectionRenderer.jointID(name)!)  \(name.replacingOccurrences(of: "_", with: " "))").font(.callout)
                    Text(model.frame?.edits[name]?.state.label ?? (model.frame?.seedPoint(name, kind: model.kind) == nil ? "No detection · place manually" : "Raw · unreviewed"))
                        .font(.caption2).foregroundStyle(.secondary)
                }.tag(name)
            }
            Text(model.selected.replacingOccurrences(of: "_", with: " ")).font(.headline)
            Button(model.placing ? "Cancel placement" : "Place selected joint") { model.placing.toggle() }
                .disabled(model.frame == nil)
            Button("Confirm visible location") { model.setState(.confirmed) }
                .disabled(model.frame?.displayPoint(model.selected, kind: model.kind) == nil)
            Button("Mark obscured / unobservable") { model.setState(.occluded) }.disabled(model.frame == nil)
            Button("Mark uncertain") { model.setState(.uncertain) }.disabled(model.frame == nil)
            Text("Obscured joints are excluded. Corrections affect 2D locations only; hidden depth remains unvalidated.")
                .font(.caption).foregroundStyle(.secondary)
        }.padding()
    }
}
