import SwiftUI
import AppKit
import NucleicCore

/// The three things the top region of the sidebar can show. "Recents" is the default
/// (recent chats across every project, with the project list beneath it); the other two
/// pull the cross-session Apple Intelligence queue and the Nucleic Control panel — previously
/// a floating panel and a sheet — inline so they're a flick of the switcher away. "Control"
/// gathers the whole Nucleic Control subsystem (shared container, autoship, file locks, and the
/// git-interceptor activity feed); its `atom` glyph matches the one Control projects carry in
/// the project tree.
enum SidebarMode: String, CaseIterable, Identifiable {
    case recents
    case intelligence
    case control

    var id: String { rawValue }

    var title: String {
        switch self {
        case .recents: "Recents"
        case .intelligence: "Queue"
        case .control: "Control"
        }
    }

    var icon: String {
        switch self {
        case .recents: "clock"
        case .intelligence: "sparkles"
        case .control: "atom"
        }
    }
}

/// A compact bordered segmented control that drives `SidebarMode`. Every segment shows its
/// icon *and* label at all times; the selected one gets a neutral rounded-rect fill that
/// slides between segments (`matchedGeometryEffect`). The two non-Recents segments keep the
/// glanceable signals their old toolbar buttons had — the AI icon glows and pulses while the
/// on-device model is busy and shows a waiting count, and the Control icon takes on an amber
/// alarm glow + tint on a genuine file-lock deadlock.
struct SidebarModeSwitcher: View {
    let mode: SidebarMode
    /// On-device model is running or has queued work — drives the AI glow/pulse.
    var afmActive: Bool
    /// How many soft-AI requests are queued behind the running one.
    var afmWaiting: Int
    /// The queue is frozen for inspection — swaps the AI sparkle for a snowflake and lights
    /// the segment with a steady (non-pulsing) glow.
    var afmFrozen: Bool
    /// A wait-for cycle the lock queue can't clear itself — lights the Control segment amber.
    var deadlocked: Bool
    var onSelect: (SidebarMode) -> Void

    @Namespace private var pill
    @Environment(\.appPalette) private var palette

    var body: some View {
        HStack(spacing: 2) {
            ForEach(SidebarMode.allCases) { segment($0) }
        }
        .frame(maxWidth: .infinity)
        .padding(3)
        .background(AppTheme.surface, in: .rect(cornerRadius: 9))
        .overlay(RoundedRectangle(cornerRadius: 9).strokeBorder(AppTheme.hairline, lineWidth: 1))
    }

    @ViewBuilder
    private func segment(_ m: SidebarMode) -> some View {
        let selected = mode == m
        Button { onSelect(m) } label: {
            HStack(spacing: 5) {
                icon(m, selected: selected)
                Text(m.title)
                    .font(.caption.weight(.semibold))
                    .lineLimit(1)
                    .fixedSize()
            }
            .padding(.vertical, 5)
            .padding(.horizontal, 10)
            // Each segment takes an equal share so the bar spans the column, lining its
            // edges up with the session-row members below it.
            .frame(maxWidth: .infinity)
            .foregroundStyle(selected ? .primary : tint(m))
            .background {
                if selected {
                    RoundedRectangle(cornerRadius: 6, style: .continuous)
                        .fill(Color.primary.opacity(0.12))
                        .matchedGeometryEffect(id: "switcherPill", in: pill)
                }
            }
            .contentShape(Rectangle())
        }
        .buttonStyle(.plain)
        .help(helpText(m))
    }

    private func icon(_ m: SidebarMode, selected: Bool) -> some View {
        // Frozen wins over the busy state for the AI segment: a snowflake in place of the
        // sparkle, lit by a cold blue bloom (vs. the white busy bloom) so the two read apart.
        let frozen = m == .intelligence && afmFrozen
        // A file-lock deadlock lights the Control segment with an amber bloom (the atom has no
        // alert variant, so the glow + tint carry the signal in place of a filled glyph).
        let alarm = m == .control && deadlocked
        let name = frozen ? "snowflake" : m.icon
        let busy = m == .intelligence && afmActive && !frozen
        let glowing = busy || frozen || alarm
        // White bloom while the model is busy; a bright icy blue while frozen; amber on a Control
        // deadlock. The bloom is kept lighter than the (night-softened) `palette.frozen` used for
        // the button/tint — that resolved blue is too dim to read as a glow on the dark sidebar,
        // same reason the busy bloom is pure white.
        let glowColor: Color = frozen ? Color(red: 0.45, green: 0.78, blue: 1.0)
            : alarm ? palette.attention : .white
        return Image(systemName: name)
            .font(.system(size: 12, weight: .semibold))
            // Swap the symbol (sparkle ↔ snowflake) instantly rather than cross-fading: the
            // default content transition blends the two glyphs, which — caught between the glow
            // fade and the phase animator — stalls mid-blend on a sparkle/snowflake composite.
            .contentTransition(.identity)
            // The icon itself never dims: a faint bloom breathes on top of it, from nothing up
            // to a subtle peak and back, so its lowest state is exactly its normal (un-glowing)
            // brightness — the glow only ever adds light. Slow cycle so it's a calm sheen, not a
            // throb. (A symbol `.pulse` would instead fade the icon below its normal brightness.)
            .phaseAnimator([false, true]) { view, lit in
                view.shadow(color: glowing ? glowColor.opacity(lit ? 0.5 : 0) : .clear,
                            radius: glowing ? 1 : 0)
            } animation: { _ in .easeInOut(duration: 1.6) }
            .animation(.easeInOut(duration: 0.35), value: glowing)
    }

    /// Idle-segment tint: amber on a lock deadlock, a light icy blue on a frozen AI queue,
    /// otherwise a calm secondary.
    private func tint(_ m: SidebarMode) -> Color {
        if m == .control, deadlocked { return palette.attention }
        if m == .intelligence, afmFrozen { return frozenTint }
        return .secondary
    }

    /// The inactive AI segment's snowflake + label color while frozen. A light icy blue that
    /// keeps strong contrast on the dark sidebar — the night-softened `palette.frozen` resolved
    /// too dim — while dropping to a deeper blue in light mode so it stays legible there.
    private var frozenTint: Color {
        Color(nsColor: NSColor(name: nil) { appearance in
            appearance.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua
                ? NSColor(srgbRed: 0.66, green: 0.86, blue: 1.0, alpha: 1)
                : NSColor(srgbRed: 0.13, green: 0.46, blue: 0.84, alpha: 1)
        })
    }

    private func helpText(_ m: SidebarMode) -> String {
        switch m {
        case .recents:
            return "Recent chats across every project"
        case .intelligence:
            if afmFrozen {
                let held = afmWaiting > 0 ? " — \(afmWaiting) held" : ""
                return "Apple Intelligence — queue frozen\(held)"
            }
            if afmWaiting > 0 { return "Apple Intelligence queue — \(afmWaiting) waiting" }
            return afmActive ? "Apple Intelligence — model is busy" : "Apple Intelligence queue"
        case .control:
            return deadlocked
                ? "Nucleic Control — file-lock deadlock detected; release one holder to break it"
                : "Nucleic Control — container, autoship, file locks, and git activity"
        }
    }
}
