import SwiftUI

/// Firmware picker for a single ONU. Lists images compatible with the ONU's
/// model (with a "show all" escape hatch), and gates the actual push behind a
/// service-affecting confirmation. The push stages the image in the ONU's
/// **standby** bank, so the running image is untouched until the next reboot.
struct FirmwareUpdateSheet: View {
    let vm: ONUDetailViewModel
    let state: ONUStateDoc

    @Environment(\.dismiss) private var dismiss
    @State private var showAll = false
    @State private var pending: FirmwareFile?

    private var compatible: [FirmwareFile] {
        vm.firmwareFiles.filter { $0.isCompatible(vendor: state.vendor, equipmentId: state.equipmentId) }
    }
    private var visible: [FirmwareFile] { showAll ? vm.firmwareFiles : compatible }

    var body: some View {
        NavigationStack {
            List {
                Section {
                    LabeledContent("Current", value: state.fwVersion ?? "—")
                    if let eq = state.equipmentId { LabeledContent("Model", value: eq) }
                }

                if let error = vm.firmwareLoadError {
                    Section { Text(error).foregroundStyle(.red).font(.footnote) }
                } else if vm.firmwareFiles.isEmpty {
                    Section {
                        HStack(spacing: 10) { ProgressView(); Text("Loading firmware…").foregroundStyle(.secondary) }
                    }
                } else {
                    Section {
                        ForEach(visible) { file in
                            Button { pending = file } label: { fileRow(file) }
                                .disabled(vm.isPerformingAction)
                        }
                    } header: {
                        Text(showAll ? "All firmware" : "Compatible firmware")
                    } footer: {
                        if !showAll && compatible.isEmpty {
                            Text("No image matches this ONU's model. Turn on “Show all” to choose one manually — make sure it's compatible.")
                        }
                    }
                    if vm.firmwareFiles.count > compatible.count {
                        Section { Toggle("Show all firmware", isOn: $showAll) }
                    }
                }
            }
            .navigationTitle("Update firmware")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) { Button("Cancel") { dismiss() } }
            }
            .task { if vm.firmwareFiles.isEmpty { await vm.loadFirmware() } }
            .confirmationDialog(
                "Stage firmware?",
                isPresented: Binding(get: { pending != nil }, set: { if !$0 { pending = nil } }),
                titleVisibility: .visible,
                presenting: pending
            ) { file in
                Button("Download \(file.version ?? "firmware")", role: .destructive) {
                    let selected = file
                    dismiss()
                    Task { await vm.upgrade(to: selected) }
                }
                Button("Cancel", role: .cancel) { pending = nil }
            } message: { file in
                Text("Stage \(file.version ?? "this image") on \(state.id) in the standby bank. It becomes active after the ONU's next reboot — this is service-affecting.")
            }
        }
        .presentationDetents([.medium, .large])
    }

    private func fileRow(_ file: FirmwareFile) -> some View {
        VStack(alignment: .leading, spacing: 2) {
            Text(file.version ?? file.filename ?? "Unknown").font(.body.weight(.medium))
            Text(subtitle(file)).font(.caption).foregroundStyle(.secondary)
        }
    }

    private func subtitle(_ file: FirmwareFile) -> String {
        var parts: [String] = []
        if let model = file.models.first { parts.append(model) }
        if let size = file.sizeBytes { parts.append(Format.bytes(size)) }
        return parts.joined(separator: " · ")
    }
}
