import SwiftUI

struct DashboardView: View {
    private let connection: MCMSConnection
    @State private var vm: DashboardViewModel
    @AppStorage("dashboard.extraStats") private var extraStats = false
    @AppStorage("dashboard.autoRefresh") private var autoRefresh = false

    init(connection: MCMSConnection) {
        self.connection = connection
        _vm = State(initialValue: DashboardViewModel(connection: connection))
    }

    private let columns = [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())]

    var body: some View {
        Group {
            switch vm.phase {
            case .idle:
                LoadingView(label: "Loading network…")
            case .loading where vm.onuTotal == 0:
                LoadingView(label: "Loading network…")
            case .failed(let msg):
                ErrorStateView(message: msg) { Task { await vm.load(extraStats: extraStats) } }
            default:
                content
            }
        }
        .navigationTitle("Dashboard")
        .toolbar {
            ToolbarItem(placement: .topBarTrailing) {
                Menu {
                    Toggle("Detailed stats (Rx scan)", isOn: $extraStats)
                    Toggle("Auto-refresh · 30s", isOn: $autoRefresh)
                } label: {
                    Image(systemName: autoRefresh ? "arrow.clockwise.circle.fill" : "ellipsis.circle")
                }
            }
        }
        // Reloads on appear, and whenever a toggle flips; keeps refreshing every
        // 30s while auto-refresh is on. Cancelled when the view goes away.
        .task(id: "\(extraStats)-\(autoRefresh)") {
            while !Task.isCancelled {
                await vm.load(extraStats: extraStats)
                guard autoRefresh else { break }
                try? await Task.sleep(for: .seconds(30))
            }
        }
        .refreshable { await vm.load(extraStats: extraStats) }
    }

    private var content: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 20) {
                LazyVGrid(columns: columns, spacing: 12) {
                    CountTile(title: "ONUs", value: vm.onuTotal,
                              systemImage: "point.3.connected.trianglepath.dotted", tint: .blue)
                    CountTile(title: "OLTs", value: vm.oltCount,
                              systemImage: "antenna.radiowaves.left.and.right", tint: .teal)
                    CountTile(title: "Controllers", value: vm.controllerCount,
                              systemImage: "cpu", tint: .indigo)
                }

                if vm.totalDownstreamBps > 0 || vm.totalUpstreamBps > 0 {
                    section(title: "Traffic · all OLTs") {
                        HStack {
                            trafficStat("Downstream", systemImage: "arrow.down", bps: vm.totalDownstreamBps, tint: .blue)
                            Spacer()
                            trafficStat("Upstream", systemImage: "arrow.up", bps: vm.totalUpstreamBps, tint: .teal)
                        }
                    }
                }

                if vm.opticalAvailable || vm.lasersOffCount > 0 {
                    section(title: "Health") {
                        if vm.opticalAvailable {
                            healthLink(title: "ONUs with abnormal Rx", detail: "< −28 or > −10 dBm", count: vm.abnormalRxCount) {
                                AbnormalRxListView(connection: connection, onus: vm.abnormalRxONUs)
                            }
                        }
                        healthLink(title: "OLTs with laser off", detail: nil, count: vm.lasersOffCount) {
                            LaserOffListView(connection: connection, olts: vm.lasersOffOLTs)
                        }
                    }
                }

                if !vm.onuCounts.isEmpty {
                    section(title: "ONU states") {
                        ForEach(vm.onuCounts, id: \.state) { row in
                            NavigationLink {
                                ONUListView(connection: connection,
                                            stateFilter: row.state,
                                            title: row.state.label)
                            } label: {
                                HStack {
                                    StateBadge(text: row.state.label, color: row.state.color)
                                    Spacer()
                                    Text("\(row.count)").font(.body.monospacedDigit())
                                    Image(systemName: "chevron.right")
                                        .font(.caption2.weight(.semibold))
                                        .foregroundStyle(.tertiary)
                                }
                                .padding(.vertical, 4)
                                .contentShape(Rectangle())
                            }
                            .buttonStyle(.plain)
                        }
                    }
                }

                if !vm.severityCounts.isEmpty {
                    section(title: "ONU alarms by severity") {
                        ForEach(vm.severityCounts, id: \.severity) { row in
                            HStack {
                                SeverityBadge(severity: row.severity)
                                Spacer()
                                Text("\(row.count)").font(.body.monospacedDigit())
                            }
                            .padding(.vertical, 4)
                        }
                    }
                }
            }
            .padding()
        }
    }

    @ViewBuilder
    private func section<Content: View>(title: String, @ViewBuilder content: () -> Content) -> some View {
        VStack(alignment: .leading, spacing: 8) {
            Text(title).font(.headline)
            VStack(spacing: 0) { content() }
                .padding()
                .background(Color(.secondarySystemBackground))
                .clipShape(RoundedRectangle(cornerRadius: 14, style: .continuous))
        }
    }

    private func trafficStat(_ title: String, systemImage: String, bps: Double, tint: Color) -> some View {
        VStack(alignment: .leading, spacing: 4) {
            Label(title, systemImage: systemImage).font(.caption).foregroundStyle(.secondary)
            Text(Format.bps(bps))
                .font(.system(.title3, design: .rounded).weight(.semibold))
                .foregroundStyle(tint)
                .monospacedDigit()
        }
    }

    /// A health row that becomes a navigation link into the affected devices
    /// when the count is non-zero.
    @ViewBuilder
    private func healthLink<Destination: View>(
        title: String, detail: String?, count: Int,
        @ViewBuilder destination: () -> Destination
    ) -> some View {
        if count > 0 {
            NavigationLink(destination: destination()) {
                healthRow(title, detail: detail, count: count, tappable: true)
            }
            .buttonStyle(.plain)
        } else {
            healthRow(title, detail: detail, count: count, tappable: false)
        }
    }

    private func healthRow(_ title: String, detail: String?, count: Int, tappable: Bool) -> some View {
        HStack {
            VStack(alignment: .leading, spacing: 2) {
                Text(title)
                if let detail { Text(detail).font(.caption).foregroundStyle(.secondary) }
            }
            Spacer()
            Text("\(count)")
                .font(.body.monospacedDigit().weight(.semibold))
                .foregroundStyle(count > 0 ? .orange : .green)
            if tappable {
                Image(systemName: "chevron.right")
                    .font(.caption2.weight(.semibold))
                    .foregroundStyle(.tertiary)
            }
        }
        .padding(.vertical, 4)
        .contentShape(Rectangle())
    }
}
