import SwiftUI
import NucleicProtocol

/// The phone's **Mesh Info** screen — the iOS analogue of the Mac's Covalence Mesh Viewer, reached
/// from Settings ▸ Mesh ▸ "Mesh info". A read-only diagnostics surface over the mesh as this phone
/// sees it: overall connection health, the Macs this phone is directly paired with (live status +
/// transport), the mesh's runner-presence cards (the Covalence dispatch candidate pool with capacity /
/// projects), and a live tail of fleet activity. Structural metadata only — never prompt/draft
/// content, matching the Mac viewer's redaction invariant.
///
/// The phone links only `NucleicProtocol`, not the Mac's mesh engine, so this renders from
/// `RemoteStore` projections (`connectivity`, `meshRunnerCards`, `activityFeed`) rather than the
/// Mac's `MeshDiagnosticsLog`. Two id namespaces are in play — directly-paired Macs are keyed by
/// `PairedHost.fingerprint`, presence cards by the full `deviceID` — so they're shown as separate
/// sections instead of being cross-matched.
struct MeshInfoView: View {
    @EnvironmentObject var store: RemoteStore

    private var runnerCards: [(hostID: String, presence: RunnerPresence)] { store.meshRunnerCards }

    var body: some View {
        Form {
            statusSection
            devicesSection
            runnerCardsSection
            activitySection
        }
        .navigationTitle("Mesh info")
        .navigationBarTitleDisplayMode(.inline)
    }

    // MARK: Status

    @ViewBuilder
    private var statusSection: some View {
        Section {
            LabeledContent("Status", value: store.meshStatusHeadline)
            LabeledContent("Devices", value: "\(store.meshDevices.filter { !$0.isSelf }.count)")
            if !runnerCards.isEmpty {
                LabeledContent("Runner cards", value: "\(runnerCards.count)")
            }
        } header: {
            Text("Mesh")
        } footer: {
            Text("The mesh as this device sees it — “connected” means it can reach any device on the "
                 + "mesh, a Mac or a cloud runner. Read-only; structural metadata only.")
        }
    }

    // MARK: Devices

    @ViewBuilder
    private var devicesSection: some View {
        Section {
            ForEach(store.meshDevices) { device in
                MeshDeviceRow(device: device)
            }
        } header: {
            Text("Devices")
        } footer: {
            Text("Each device on your mesh and how this device reaches it — the connection method "
                 + "(LAN / Tailnet / Relay / Direct), or the device it's reached by way of.")
        }
    }

    // MARK: Runner presence cards

    @ViewBuilder
    private var runnerCardsSection: some View {
        if !runnerCards.isEmpty {
            Section {
                ForEach(runnerCards, id: \.hostID) { card in
                    RunnerCardRow(presence: card.presence)
                }
            } header: {
                Text("Runner capacity")
            } footer: {
                Text("Hosts advertising capacity for Covalence-dispatched chats, and the projects "
                     + "they hold.")
            }
        }
    }

    // MARK: Recent activity

    @ViewBuilder
    private var activitySection: some View {
        Section("Recent mesh activity") {
            if store.activityFeed.isEmpty {
                Text("No mesh events yet.")
                    .font(.footnote).foregroundStyle(.secondary)
            } else {
                // Newest first, capped — this is a diagnostics tail, not the full feed.
                ForEach(Array(store.activityFeed.reversed().prefix(50))) { item in
                    MeshEventRow(item: item)
                }
            }
        }
    }

}

/// One row in the mesh device list: a status dot, the device's kind icon, its name, and how this
/// phone reaches it — the connection method (LAN / Tailnet / Relay / Direct (STUN)) for a direct
/// link, or "via <device>" when it's reached by way of another mesh device. Shared by Settings ▸
/// Connection and the Mesh Info screen.
struct MeshDeviceRow: View {
    let device: RemoteStore.MeshDevice

    private var dotColor: Color {
        switch device.reachability {
        case .connected: .green
        case .viaPeer: .blue
        case .connecting: .orange
        case .offline: Color.secondary.opacity(0.4)
        }
    }

    private var icon: String {
        switch device.kind {
        case .iphone: "iphone"
        case .cloud: "cloud"
        default: "desktopcomputer"
        }
    }

    /// Trailing text: "This device" for self, else the reachability detail (method or "via …").
    private var detail: String {
        device.isSelf ? "This device" : device.reachability.detail
    }

    var body: some View {
        HStack(spacing: 10) {
            Circle().fill(dotColor).frame(width: 8, height: 8)
            Image(systemName: icon)
                .foregroundStyle(.secondary)
                .frame(width: 22)
            VStack(alignment: .leading, spacing: 2) {
                Text(device.name).lineLimit(1)
                Text(detail).font(.footnote).foregroundStyle(.secondary)
            }
            Spacer(minLength: 8)
        }
    }
}

/// One runner-presence card: host name + kind, load (active / capacity), and its held projects.
private struct RunnerCardRow: View {
    let presence: RunnerPresence

    private var capacityLabel: String {
        let cap = presence.maxConcurrent.map(String.init) ?? "∞"
        return "\(presence.activeSessionCount)/\(cap)"
    }

    var body: some View {
        HStack(spacing: 10) {
            Image(systemName: presence.kind == .cloud ? "cloud" : "desktopcomputer")
                .foregroundStyle(.secondary)
            VStack(alignment: .leading, spacing: 2) {
                Text(presence.hostName.isEmpty ? "Host" : presence.hostName)
                Text("\(presence.projects.count) project(s)"
                     + (presence.acceptsMeshDispatch ? " · accepts dispatch" : " · dispatch off"))
                    .font(.footnote).foregroundStyle(.secondary)
            }
            Spacer()
            Text(capacityLabel)
                .font(.footnote.monospacedDigit())
                .foregroundStyle(.secondary)
        }
    }
}

/// One mesh event row (a fleet-activity `FeedEvent`) — the phone's equivalent of the Mac viewer's
/// event-log rows. Reuses the activity feed's icon/tint/headline vocabulary.
private struct MeshEventRow: View {
    let item: ActivityFeedItem
    private var event: FeedEvent { item.event }

    var body: some View {
        HStack(alignment: .top, spacing: 10) {
            Image(systemName: ActivityFeedIcon.icon(for: event.kind))
                .foregroundStyle(ActivityFeedIcon.tint(for: event.kind))
                .font(.subheadline)
                .frame(width: 20)
                .padding(.top, 2)
            VStack(alignment: .leading, spacing: 2) {
                HStack(spacing: 6) {
                    Text(event.sessionTitle.isEmpty ? "Untitled chat" : event.sessionTitle)
                        .font(.subheadline.weight(.medium))
                        .lineLimit(1)
                    Spacer(minLength: 4)
                    Text(event.at, format: .relative(presentation: .named))
                        .font(.caption2).foregroundStyle(.tertiary)
                }
                Text(subtitle)
                    .font(.caption).foregroundStyle(.secondary)
                    .lineLimit(2)
            }
        }
        .padding(.vertical, 2)
    }

    private var subtitle: String {
        var parts: [String] = [ActivityFeedIcon.headline(for: event)]
        if !event.projectName.isEmpty { parts.append(event.projectName) }
        if !event.hostName.isEmpty { parts.append(event.hostName) }
        return parts.joined(separator: " · ")
    }
}
