import SwiftUI

/// An unobtrusive, click-to-update strip pinned at the very top of the sidebar, above the mode
/// switcher — the *only* place a background-discovered update is surfaced. Tapping it downloads the
/// update and relaunches into the new version with no extra windows. Manual "Check for Updates…"
/// (Settings ▸ General) never routes here. Renders nothing unless `AppUpdater` has a pending or
/// in-progress sidebar update, so it's invisible in the common case.
struct UpdateSidebarBanner: View {
    @EnvironmentObject private var updater: AppUpdater
    @Environment(\.appPalette) private var palette

    var body: some View {
        content
            .animation(.easeInOut(duration: 0.2), value: updater.sidebar)
    }

    @ViewBuilder
    private var content: some View {
        switch updater.sidebar {
        case .none:
            EmptyView()
        case .available(let version):
            available(version: version)
        case .downloading(let fraction):
            progress(fraction: fraction)
        case .relaunching:
            status(icon: "arrow.triangle.2.circlepath", text: "Restarting…")
        }
    }

    /// The actionable state: the whole strip is one button that starts the update.
    private func available(version: String) -> some View {
        Button { updater.installSidebarUpdate() } label: {
            HStack(spacing: 8) {
                Image(systemName: "arrow.down.circle.fill")
                    .foregroundStyle(palette.accent)
                VStack(alignment: .leading, spacing: 1) {
                    Text("Update available")
                        .font(.caption.weight(.semibold))
                    Text("Version \(version) — click to update")
                        .font(.caption2)
                        .foregroundStyle(.secondary)
                        .lineLimit(1)
                }
                Spacer(minLength: 0)
                Image(systemName: "chevron.right")
                    .font(.caption2.weight(.semibold))
                    .foregroundStyle(.secondary)
            }
            .modifier(BannerChrome(tint: palette.accent))
        }
        .buttonStyle(.plain)
        .padding(.horizontal, 8)
        .padding(.top, 8)
        .transition(.move(edge: .top).combined(with: .opacity))
    }

    private func progress(fraction: Double) -> some View {
        status(
            icon: nil,
            text: fraction > 0 ? "Updating… \(Int((fraction * 100).rounded()))%" : "Updating…",
            spinning: true)
    }

    private func status(icon: String?, text: String, spinning: Bool = false) -> some View {
        HStack(spacing: 8) {
            if spinning {
                ProgressView().controlSize(.small)
            } else if let icon {
                Image(systemName: icon).foregroundStyle(palette.accent)
            }
            Text(text).font(.caption.weight(.medium))
            Spacer(minLength: 0)
        }
        .modifier(BannerChrome(tint: palette.accent))
        .padding(.horizontal, 8)
        .padding(.top, 8)
        .transition(.move(edge: .top).combined(with: .opacity))
    }
}

/// Shared strip chrome: matches the sidebar mode switcher's tinted, hairline-bordered rounded card
/// (corner radius 9) so the banner reads as part of the same control stack.
private struct BannerChrome: ViewModifier {
    let tint: Color
    func body(content: Content) -> some View {
        content
            .padding(.horizontal, 10)
            .padding(.vertical, 7)
            .frame(maxWidth: .infinity, alignment: .leading)
            .background(tint.opacity(0.10), in: .rect(cornerRadius: 9))
            .overlay(RoundedRectangle(cornerRadius: 9).strokeBorder(tint.opacity(0.30), lineWidth: 1))
            .contentShape(Rectangle())
    }
}
