import SwiftUI
import PoseCore

struct LeanReviewView: View {
    @ObservedObject var model: ReviewerModel
    private var annotation: LeanAnnotation? { model.frame.flatMap { model.lean($0.id) } }
    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 12) {
                Text("\(model.frame?.riderDisplayName ?? "Rider") · wheel lean").font(.headline)
                Text("Yellow: wheel axis\nCyan: reference / proxy horizon").font(.caption)
                Toggle("Show lean overlay", isOn: Binding(get: { model.showLean }, set: { model.cancelInteraction(); model.showLean = $0 }))
                Text("Drag either line’s endpoints on the photo. Arrow keys move the selected endpoint; Shift moves 10 pixels.").font(.caption)
                Picker("Endpoint", selection: $model.selectedLeanHandle) {
                    ForEach(LeanHandle.allCases, id: \.self) { Text($0.label).tag($0) }
                }
                HStack {
                    Button("←") { model.nudgeLean(dx: -1, dy: 0) }.accessibilityLabel("Move lean endpoint left")
                    Button("↑") { model.nudgeLean(dx: 0, dy: -1) }.accessibilityLabel("Move lean endpoint up")
                    Button("↓") { model.nudgeLean(dx: 0, dy: 1) }.accessibilityLabel("Move lean endpoint down")
                    Button("→") { model.nudgeLean(dx: 1, dy: 0) }.accessibilityLabel("Move lean endpoint right")
                }
                Button("Place / replace wheel axis") { model.beginLeanPlacement(reference: false) }
                if model.leanPlacement != nil {
                    Text(model.leanPlacementStart == nil ? "Click the first endpoint, then the second." : "Click the second endpoint. Escape cancels.").foregroundStyle(.orange).font(.caption)
                    Button("Cancel placement") { model.cancelInteraction() }
                }
                Picker("Reference basis", selection: Binding(get: { annotation?.basis ?? .imageVertical }, set: { basis in
                    model.cancelInteraction()
                    model.changeLean { $0.basis = basis; $0.state = .draft; $0.referenceReviewed = false }
                })) {
                    ForEach(LeanBasis.allCases, id: \.self) { Text($0.label).tag($0) }
                }
                Button("Place / replace reference line") { model.beginLeanPlacement(reference: true) }
                if let a = annotation {
                    if a.basis == .sharedFeature {
                        TextField("Same feature ID in both photos", text: Binding(get: { a.featureID }, set: { text in
                            model.changeLean { $0.featureID = text; $0.state = .draft; $0.referenceReviewed = false }
                        }))
                        Text("Mark the same two stationary points in both photos. The feature need not be level. Curved edges need the same local segment.").font(.caption)
                    }
                    if a.basis != .imageVertical {
                        Toggle("Reference evidence reviewed", isOn: Binding(get: { a.referenceReviewed }, set: { value in
                            model.changeLean { $0.referenceReviewed = value; $0.state = .draft }
                        })).disabled(a.reference == nil)
                        Text(a.basis == .assumedLevel ? "This line is only assumed level. It does not establish physical motorcycle lean." : "Review correspondence and perspective; watermarks and moving objects are not references.").font(.caption)
                    }
                    if let wheel = a.wheel {
                        Stepper("Wheel uncertainty: ±\(wheel.uncertainty, specifier: "%.0f") px", value: Binding(get: { wheel.uncertainty }, set: { value in
                            model.changeLean { $0.wheel?.uncertainty = value; $0.state = .draft }
                        }), in: 1...100)
                    }
                    if let reference = a.reference {
                        Stepper("Reference uncertainty: ±\(reference.uncertainty, specifier: "%.0f") px", value: Binding(get: { reference.uncertainty }, set: { value in
                            model.changeLean { $0.reference?.uncertainty = value; $0.state = .draft; $0.referenceReviewed = false }
                        }), in: 1...100)
                    }
                    Text(a.cue).font(.caption)
                    Text(a.provenance).font(.caption2).foregroundStyle(.secondary)
                    Button("Confirm visible wheel axis") { model.changeLean { $0.state = .reviewed } }
                        .disabled(LeanAnalysis.measure(a) == nil || (a.basis != .imageVertical && !a.referenceReviewed) || (a.basis == .sharedFeature && a.featureID.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty))
                    Button("Mark unobservable") { model.changeLean { $0.state = .unavailable } }
                    Button("Clear wheel axis") { model.changeLean { $0.wheel = nil; $0.state = .draft } }
                    Button("Clear reference line") { model.changeLean { $0.reference = nil; $0.referenceReviewed = false; $0.state = .draft } }
                }
                Text("Edits save on release and can be undone. Draft guesses are not reviewed measurements.").font(.caption).foregroundStyle(.secondary)
            }.font(.callout).padding()
        }
    }
}

struct LeanEvidenceView: View {
    @ObservedObject var model: ReviewerModel
    var body: some View {
        VStack(alignment: .leading, spacing: 6) {
            HStack {
                Text("Wheel lean evidence").font(.headline)
                Spacer()
                Text(model.hasPreview ? "Preview pending · release to save" : "Revision \(model.document?.revision ?? 0) · \(model.isUnsaved ? "Unsaved" : "Saved locally")").font(.caption)
            }
            ForEach(model.visibleIDs, id: \.self) { id in
                if let frame = model.frame(id) {
                    if let a = model.lean(id), let value = LeanAnalysis.measure(a) {
                        Text("\(frame.riderDisplayName): \(value.angle, specifier: "%.0f")° · \(a.basis == .sharedFeature ? "wheel-to-feature orientation" : "2D wheel lean") · \(a.basis.label) · \(a.state == .reviewed ? "Reviewed" : "Draft")")
                        Text("Annotation sensitivity \(value.lower, specifier: "%.0f")° to \(value.upper, specifier: "%.0f")°").font(.caption)
                    } else { Text("\(frame.riderDisplayName): wheel angle unavailable; place or review the lines.") }
                }
            }
            if let pair = model.pair, pair.referenceID != nil, let doc = model.document {
                let context = doc.leanContexts[pair.id] ?? LeanPairContext()
                let comparison = try? LeanAnalysis.compare(doc, pair: pair)
                Text(comparison?.summary ?? "Comparison unavailable.").font(.callout)
                if let delta = comparison?.measurement {
                    Text("Rider − Reference rider: \(delta.angle, specifier: "%+.0f")° [\(delta.lower, specifier: "%+.0f")°, \(delta.upper, specifier: "%+.0f")°] annotation sensitivity").font(.caption)
                }
                DisclosureGroup("Review comparison evidence") {
                    check("Same wheel cue", \.commonCue, context)
                    check("Camera views comparable", \.comparableView, context)
                    check("Wheel headings comparable", \.comparableHeading, context)
                    check("Reference basis / correspondence comparable", \.comparableReference, context)
                    check("Camera roll comparable (image vertical)", \.comparableCameraRoll, context)
                    Button("Approve this comparison") { model.updateLeanContext(context, approve: true) }
                        .disabled(!context.checksComplete || !pair.frameIDs.allSatisfy { doc.leanAnnotations[$0]?.state == .reviewed } || (doc.leanAnnotations[pair.subjectID]?.basis == .imageVertical && !context.comparableCameraRoll))
                    check("Similar speed — user reported", \.similarSpeedReported, context)
                    Text("Similar speed does not establish matched radius, turn phase, banking, or a body-position explanation.").font(.caption)
                }
                if context.similarSpeedReported { Text("Similar speed: user reported. Discuss the observation with separately reviewed posture and turn context.").font(.caption) }
            }
            Text(LeanAnalysis.limitations).font(.caption).foregroundStyle(.secondary)
        }.textSelection(.enabled)
    }
    private func check(_ title: String, _ key: WritableKeyPath<LeanPairContext, Bool>, _ context: LeanPairContext) -> some View {
        Toggle(title, isOn: Binding(get: { context[keyPath: key] }, set: { value in
            var next = context; next[keyPath: key] = value; model.updateLeanContext(next)
        }))
    }
}
