import SwiftUI
import RideFormCore

struct WatchRecordingView: View {
    @ObservedObject var controller: RecordingController
    @ObservedObject var transfer: WatchSessionTransfer
    var runtimeCheck: (() -> Void)? = nil
    var body: some View {
        ScrollView {
            VStack(spacing: 10) {
                if controller.synthetic { Text("SYNTHETIC TEST").foregroundStyle(.orange) }

                switch controller.state {
                case .uncalibrated, .ready:
                    Button("Calibrate") { controller.beginCalibration() }.accessibilityIdentifier("watchCalibrate")
                    if controller.state == .ready { Button("Record") { controller.startRecording() }.accessibilityIdentifier("watchRecord") }
                    Button("Test audio") { controller.testCalibrationAudio() }.disabled(!controller.canTestCalibrationAudio).accessibilityIdentifier("watchTestAudio")
                    if let runtimeCheck {
                        Button("10-minute runtime check", action: runtimeCheck).accessibilityIdentifier("watchRuntimeCheck")
                        Text("Leave the Watch still. This check stops and saves automatically.").font(.caption)
                    }
                    if !controller.audioTestStatus.isEmpty { Text(controller.audioTestStatus).font(.caption) }
                    Text("Start while RideForm is visible. The runtime check tests recording after the display dims.").font(.caption)
                    NavigationLink("Capture settings") {
                        Form {
                            Text("For longer trials, set Watch Settings → General → Return to Clock → RideForm → Custom → After 1 hour. This allows a longer frontmost session; continuous sensor delivery still needs verification.").font(.caption)
                            Picker("Sensors", selection: Binding(get: { controller.captureMode }, set: controller.changeCaptureMode)) {
                                Text("Fused").tag(CaptureMode.fusedOnly)
                                Text("Fused + raw").tag(CaptureMode.combined)
                            }
                            Toggle("Start after calibration", isOn: $controller.recordAfterCalibration)
                        }
                    }
                    Button("Sensor diagnostics") { controller.startDiagnostics(mode: controller.captureMode) }
                    NavigationLink("Saved sessions") { savedSessions }
                case .calibrating:
                    Text(stageTitle).font(.title2.bold()).accessibilityIdentifier("watchCalibrationStage")
                    Text(controller.calibration.prompt.replacingOccurrences(of: "phone", with: "Watch")).font(.body)
                    if controller.calibration.stage == .retry { Button("Retry") { controller.beginCalibration() } }
                    Button("Cancel") { controller.cancelCalibration() }
                case .recording:
                    Text("\(controller.elapsed, specifier: "%.0f") seconds").font(.headline)
                    Button("Stop & save") { controller.stopRecording() }.tint(.red).accessibilityIdentifier("watchStop")
                    if controller.diagnosticsActive {
                        Text(controller.diagnosticInstruction)
                        if controller.diagnosticMovementReady { Button("Next drill") { controller.nextDiagnosticDrill() } }
                    } else {
                        ForEach(["LEFT", "CENTER", "RIGHT", "GOOD", "BAD"], id: \.self) { label in Button(label) { controller.marker(label) } }
                    }
                case .finalizing: ProgressView("Saving")
                case .saved:
                    if let url = controller.savedURL { WatchSavedView(url: url, transfer: transfer) }
                    Button("Another recording") { controller.acknowledgeSaved() }
                case .saveError:
                    Button("Retry save") { controller.retrySave() }
                }
                if controller.state != .calibrating {
                    Text(controller.status).font(.caption).accessibilityIdentifier("watchStatus")
                    Text(transfer.status).font(.caption)
                }
            }.buttonStyle(.bordered).padding(.horizontal, 4)
        }.id(controller.state).navigationTitle("RideForm")
    }
    private var stageTitle: String {
        switch controller.calibration.stage {
        case .idle, .preparingNeutral: return "Get centered"
        case .neutral: return "Hold center"
        case .left: return "Lean LEFT"
        case .forward: return "Lean FORWARD"
        case .returnToRestart, .returnToNeutral, .returnToFinish: return "Return to center"
        case .awaitingConvention: return "Checking"
        case .ready: return "Ready"
        case .retry: return "Paused"
        }
    }
    private var savedSessions: some View {
        List(controller.sessions, id: \.self) { url in
            NavigationLink(url.deletingPathExtension().lastPathComponent.prefix(8).description) { WatchSavedView(url: url, transfer: transfer) }
        }.onAppear { controller.refreshSessions() }.navigationTitle("Sessions")
    }
}

struct WatchSavedView: View {
    let url: URL
    @ObservedObject var transfer: WatchSessionTransfer
    @State private var summary = "Reading session…"
    var body: some View {
        VStack {
            Text(summary).font(.caption).accessibilityIdentifier("watchSavedSummary")
            Button("Send to iPhone") { transfer.send(bundle: url) }.disabled(transfer.preparing)
        }.task {
            let text = await Task.detached {
                do {
                    // The recorder needs a small receipt, not a full motion analysis.
                    let manifest = try SessionCodec.decodeManifest(Data(contentsOf: url.appendingPathComponent("manifest.json")))
                    let motion = manifest.streams.first { $0.kind == .motion }
                    let count = motion?.writtenCount ?? 0
                    let label = manifest.boundaries.status == "incomplete" ? "checkpointed samples" : "samples"
                    let duration = motion?.statistics.durationSeconds.map { String(format: " · %.1f seconds", $0) } ?? ""
                    return "\(manifest.boundaries.status) · \(count) \(label)\(duration)"
                } catch { return "Review unavailable: \(error.localizedDescription)" }
            }.value
            guard !Task.isCancelled else { return }; summary = text
        }
    }
}
