import SwiftUI
import RideFormCore

struct RecordingView: View {
    @EnvironmentObject private var watchTransfer: WatchSessionTransfer
    @ObservedObject var controller: RecordingController
    @State private var method = CalibrationController.SetupMethod.guided
    var body: some View {
        ScrollView {
            VStack(spacing: 16) {
                if controller.synthetic { Text("SYNTHETIC • UI TEST MOTION").bold().foregroundStyle(.orange).accessibilityIdentifier("syntheticLabel") }
                if controller.state == .recording {
                    Label("RECORDING", systemImage: "record.circle.fill").font(.title).bold().foregroundStyle(.red).accessibilityIdentifier("recordingIndicator")
                }
                Text(controller.status).font(.headline).accessibilityIdentifier("recordingStatus")
                Text("\(controller.elapsed, specifier: "%.1f") s · \(controller.counts[.motion, default: 0]) samples").monospacedDigit().accessibilityIdentifier("captureCounts")
                Text("Requested 100 Hz · measured \(controller.measuredHz.map { String(format: "%.1f Hz", $0) } ?? "unavailable")").font(.callout)
                ForEach([StreamKind.motion, .accelerometer, .gyroscope], id: \.rawValue) { kind in
                    Text("\(kind.rawValue): \(capability(controller.capabilities[kind])) · \(controller.counts[kind, default: 0])").font(.caption)
                }
                if let a = controller.angles {
                    Text("Relative lateral \(a.x * 180 / .pi, specifier: "%.1f")° · forward \(a.y * 180 / .pi, specifier: "%.1f")° · twist \(a.z * 180 / .pi, specifier: "%.1f")°").monospacedDigit()
                } else { Text("Relative angles unavailable until calibration.").foregroundStyle(.secondary) }
                switch controller.state {
                case .uncalibrated, .ready:
                    Picker("Capture streams", selection: Binding(get: { controller.captureMode }, set: { controller.changeCaptureMode($0) })) {
                        Text("Fused only").tag(CaptureMode.fusedOnly)
                        Text("Fused + raw").tag(CaptureMode.combined)
                    }.pickerStyle(.segmented)
                    Picker("Calibration method", selection: $method) {
                        Text("Guided").tag(CalibrationController.SetupMethod.guided)
                        Text("Standard mount").tag(CalibrationController.SetupMethod.standardMount)
                    }.pickerStyle(.segmented)
                    Toggle("Spoken, hands-free calibration", isOn: $controller.spokenCalibration).accessibilityIdentifier("spokenCalibration")
                    if controller.spokenCalibration {
                        Text("Mount the phone, set an audible volume, then tap Calibrate. Follow the spoken instructions; keep the app open.").font(.caption)
                        Toggle("Start recording when calibration finishes", isOn: $controller.recordAfterCalibration).accessibilityIdentifier("recordAfterCalibration")
                    }
                    largeButton("Calibrate", id: "calibrate") { controller.beginCalibration(method: method) }
                    if controller.state == .ready {
                        Toggle("Audible CENTER / LEFT / RIGHT drill", isOn: $controller.audibleDrill).accessibilityIdentifier("audibleDrill")
                        largeButton("Start recording", id: "startRecording") { controller.startRecording() }
                    }
                case .calibrating:
                    Text(controller.calibration.prompt).accessibilityIdentifier("calibrationPrompt")
                    Text("\(controller.calibration.sampleCount) calibration samples").font(.caption)
                    if controller.calibration.stage == .retry {
                        largeButton("Retry calibration", id: "retryCalibration") { controller.beginCalibration(method: method) }
                    } else if !controller.calibration.handsFree {
                        largeButton("Continue", id: "continueCalibration") { controller.advanceCalibration() }.disabled(!controller.calibration.canAdvance)
                    } else {
                        if controller.calibration.stage == .preparingNeutral {
                            Text("\(controller.calibration.countdown)").font(.largeTitle).monospacedDigit()
                        }
                        Text("Follow the voice prompts. No Continue taps needed.").font(.caption)
                    }
                    Button("Cancel calibration") { controller.cancelCalibration() }.accessibilityIdentifier("cancelCalibration")
                case .recording:
                    largeButton("Stop and save", id: "stopRecording") { controller.stopRecording() }.tint(.red)
                    LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 12) {
                        ForEach(["LEFT", "CENTER", "RIGHT", "GOOD", "BAD"], id: \.self) { label in
                            largeButton(label, id: "marker\(label)") { controller.marker(label) }
                        }
                    }
                    Text("GOOD and BAD are your annotations.").font(.caption)
                case .finalizing: ProgressView("Saving accepted samples…")
                case .saved:
                    if let url = controller.savedURL { SessionSavedView(url: url) }
                    largeButton("Another recording", id: "anotherRecording") { controller.acknowledgeSaved() }
                case .saveError:
                    Text("Saving failed. This recording blocks a new one until saved.").foregroundStyle(.red)
                    largeButton("Retry save", id: "retrySave") { controller.retrySave() }
                }
                if let error = controller.calibrationLogError { Text(error).foregroundStyle(.red) }
                if ([.uncalibrated, .ready].contains(controller.state) || (controller.state == .calibrating && controller.calibration.stage == .retry)), let url = controller.calibrationLogURL {
                    ShareLink("Share calibration log", item: url).accessibilityIdentifier("shareCalibrationLog")
                }
            }.padding()
        }
        .navigationTitle("RideForm")
        .toolbar {
            if ![.calibrating, .recording, .finalizing].contains(controller.state) {
                NavigationLink("Diagnostics") { DiagnosticsView(controller: controller) }.accessibilityIdentifier("diagnostics")
                NavigationLink("Sessions") { SessionListView(controller: controller) }.accessibilityIdentifier("sessions")
                NavigationLink("Watch") { WatchTransfersView(transfer: watchTransfer) }.accessibilityIdentifier("watchTransfers")
            }
        }
    }
    private func largeButton(_ label: String, id: String, action: @escaping () -> Void) -> some View {
        Button(action: action) { Text(label).font(.headline).frame(maxWidth: .infinity, minHeight: 52) }
            .buttonStyle(.borderedProminent).accessibilityIdentifier(id)
    }
    private func capability(_ value: CapabilityState?) -> String {
        switch value {
        case .available: return "available"
        case .unavailable(let reason): return "unavailable: \(reason)"
        case nil: return "not started"
        }
    }
}
