import SwiftUI

/// How this copy of Nucleic was built. Selected at build time by the
/// `NUCLEIC_CHANNEL` make/env setting (see Package.swift), which also sets the
/// executable's process name. Drives the warning header that keeps a non-release
/// build from being mistaken for a shipping release.
enum BuildChannel {
    /// The `dev` channel — process `nucleic-local`, red "Local Development Build" banner.
    case local
    /// The `beta` channel — process `nucleic-beta`, blue "Beta" banner.
    case beta
    /// The `rc` channel — process `nucleic-rc`, gold "Release Candidate" banner.
    case releaseCandidate
    /// The `stable` channel — process `nucleic`, no banner.
    case release
}

/// Build identity for the running app: which channel it came from and the commit it
/// was built from. The commit is embedded at build time by the `EmbedGitCommit`
/// prebuild plugin (`GitCommit.hash`), so it's baked into the binary and stays
/// correct even on a packaged beta / rc / stable archive where git isn't present.
struct BuildInfo {
    let channel: BuildChannel
    /// The short git commit the binary was built from (e.g. "a1b2c3d", "+" suffix when
    /// the tree was dirty). Falls back to `CFBundleVersion` / "local" if the plugin
    /// couldn't resolve a hash.
    let buildLabel: String
    /// `CFBundleShortVersionString` when present, else `nil`.
    let version: String?

    /// Resolved once — none of this changes while the app is running.
    static let current = BuildInfo()

    init() {
        let info = Bundle.main.infoDictionary
        version = info?["CFBundleShortVersionString"] as? String
        let commit = GitCommit.hash
        buildLabel = (commit == "unknown" ? nil : commit)
            ?? (info?["CFBundleVersion"] as? String)
            ?? "local"
        channel = Self.detectChannel()
    }

    /// The channel is fixed at build time by the `NUCLEIC_CHANNEL` setting, which
    /// Package.swift turns into one of these defines. Defaults to `.local` (the `dev`
    /// channel) when nothing is set.
    private static func detectChannel() -> BuildChannel {
        #if NUCLEIC_STABLE
        return .release
        #elseif NUCLEIC_RC
        return .releaseCandidate
        #elseif NUCLEIC_BETA
        return .beta
        #else
        return .local
        #endif
    }
}

/// Header strip warning that the window is a non-release build: a red tint for
/// locally-built / pre-prod copies, blue for beta, gold for a release candidate. The
/// leading edge names the channel; the commit hash and an all-caps "EXPERIMENTAL"
/// badge sit on the trailing
/// edge. The tint is kept translucent so it reads as a quiet marker rather than
/// fighting the window background. Renders nothing for a shipping App Store release.
struct BuildBanner: View {
    var info: BuildInfo = .current

    var body: some View {
        if let style = Style(channel: info.channel) {
            HStack(spacing: 8) {
                Image(systemName: style.icon)
                    .font(.system(size: 17, weight: .heavy))
                Text(style.label)
                    .font(.body.weight(.semibold))
                Spacer(minLength: 12)
                Text(info.buildLabel)
                    .font(.caption.monospaced())
                    .opacity(0.85)
                Text("EXPERIMENTAL")
                    .font(.caption2.weight(.heavy))
                    .tracking(0.9)
                    .padding(.horizontal, 6)
                    .padding(.vertical, 2)
                    .background(.white.opacity(0.16), in: .capsule)
            }
            .foregroundStyle(.white.opacity(0.92))
            .padding(.horizontal, 12)
            .padding(.vertical, 5)
            .frame(maxWidth: .infinity)
            // A plain translucent tint, not its own glass: this strip sits directly
            // under the window's unified toolbar, whose Liquid Glass samples and blurs it
            // — so the *toolbar* is the glassy header and this is just its colored
            // backdrop. Giving the strip its own `glassEffect` drew a bright glass edge on
            // it; the toolbar's own glass is pinned visible in `RootView` instead.
            .background(style.tint.opacity(0.5))
            .help(style.tooltip(version: info.version, build: info.buildLabel))
        }
    }

    /// Per-channel appearance. `nil` for `.release` so the banner disappears entirely.
    private struct Style {
        var tint: Color
        var label: String
        var icon: String

        init?(channel: BuildChannel) {
            switch channel {
            case .local:
                tint = Color(red: 0.78, green: 0.18, blue: 0.18)   // red
                label = "Local Development Build"
                icon = "hammer.fill"
            case .beta:
                tint = Color(red: 0.13, green: 0.40, blue: 0.86)   // blue
                label = "Engineering Beta"
                icon = "person.2.badge.gearshape.fill"
            case .releaseCandidate:
                tint = Color(red: 0.83, green: 0.65, blue: 0.12)   // gold
                label = "Release Candidate"
                icon = "checkmark.seal.fill"
            case .release:
                return nil
            }
        }

        func tooltip(version: String?, build: String) -> String {
            let v = version.map { "\($0) " } ?? ""
            return "\(label) — \(v)commit \(build). Not a release build."
        }
    }
}
