import AppKit
import SiliconPulseCore
import SwiftUI

struct GaugeView: View {
    let model: GaugeModel
    var showsValue: Bool

    var body: some View {
        GeometryReader { proxy in
            let side = min(proxy.size.width, proxy.size.height)
            let lineWidth = max(side * 0.13, 2)
            ZStack {
                Circle()
                    .stroke(Color.primary.opacity(0.16), lineWidth: lineWidth)

                if let fillFraction = model.fillFraction {
                    Circle()
                        .trim(from: 0, to: fillFraction)
                        .stroke(
                            bucketColor,
                            style: StrokeStyle(lineWidth: lineWidth, lineCap: .round))
                        .rotationEffect(.degrees(-90))
                } else {
                    Circle()
                        .trim(from: 0.08, to: 0.92)
                        .stroke(
                            Color.secondary.opacity(0.55),
                            style: StrokeStyle(
                                lineWidth: lineWidth,
                                lineCap: .round,
                                dash: [lineWidth * 0.85, lineWidth * 0.9]))
                        .rotationEffect(.degrees(-90))
                }

                Circle()
                    .stroke(bucketColor.opacity(0.22), lineWidth: max(lineWidth * 0.35, 1))
                    .blur(radius: 0.7)

                if showsValue {
                    Text(model.displayValue)
                        .font(.system(size: max(side * 0.18, 10), weight: .semibold, design: .rounded))
                        .monospacedDigit()
                        .lineLimit(1)
                        .minimumScaleFactor(0.45)
                        .foregroundStyle(.primary)
                        .padding(side * 0.16)
                }
            }
            .frame(width: side, height: side)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
        .aspectRatio(1, contentMode: .fit)
    }

    private var bucketColor: Color {
        switch model.bucket {
        case .white:
            Color.white
        case .yellow:
            Color(red: 1.0, green: 0.82, blue: 0.18)
        case .red:
            Color(red: 0.92, green: 0.18, blue: 0.22)
        }
    }
}

@MainActor
enum GaugeImageRenderer {
    static let menuBarPointSize = CGSize(width: 22, height: 22)

    static func renderMenuBarImage(for model: GaugeModel, scale: CGFloat = NSScreen.main?.backingScaleFactor ?? 2) -> NSImage? {
        let view = VerticalPressureMeterView(model: model)
            .frame(width: Self.menuBarPointSize.width, height: Self.menuBarPointSize.height)
        let renderer = ImageRenderer(content: view)
        renderer.scale = scale
        renderer.isOpaque = false

        guard let image = renderer.nsImage else { return nil }
        image.isTemplate = false
        image.size = Self.menuBarPointSize
        return image
    }
}

private struct VerticalPressureMeterView: View {
    let model: GaugeModel

    var body: some View {
        GeometryReader { proxy in
            let height = proxy.size.height
            let columnHeight = height * 0.82
            let columnWidth = max(proxy.size.width * 0.34, 7)
            let fill = model.fillFraction ?? 0

            ZStack(alignment: .bottom) {
                Capsule()
                    .stroke(outlineColor, lineWidth: 1.4)
                    .background(
                        Capsule()
                            .fill(Color.white.opacity(0.08)))
                    .frame(width: columnWidth, height: columnHeight)

                Capsule()
                    .fill(fillGradient)
                    .frame(width: columnWidth - 3, height: max(columnHeight * fill - 3, fill > 0 ? 2 : 0))
                    .padding(.bottom, 1.5)

                if model.fillFraction == nil {
                    Capsule()
                        .stroke(
                            Color.white.opacity(0.5),
                            style: StrokeStyle(lineWidth: 1.2, lineCap: .round, dash: [2, 2]))
                        .frame(width: columnWidth - 2, height: columnHeight - 2)
                }
            }
            .frame(width: proxy.size.width, height: proxy.size.height, alignment: .center)
        }
    }

    private var outlineColor: Color {
        switch model.bucket {
        case .white:
            Color.white.opacity(0.78)
        case .yellow:
            Color(red: 1.0, green: 0.82, blue: 0.18).opacity(0.88)
        case .red:
            Color(red: 0.92, green: 0.18, blue: 0.22).opacity(0.92)
        }
    }

    private var fillGradient: LinearGradient {
        switch model.bucket {
        case .white:
            LinearGradient(
                colors: [Color.white.opacity(0.76), Color.white.opacity(0.94)],
                startPoint: .bottom,
                endPoint: .top)
        case .yellow:
            LinearGradient(
                colors: [
                    Color.white.opacity(0.82),
                    Color(red: 1.0, green: 0.82, blue: 0.18),
                ],
                startPoint: .bottom,
                endPoint: .top)
        case .red:
            LinearGradient(
                colors: [
                    Color(red: 1.0, green: 0.78, blue: 0.18),
                    Color(red: 0.92, green: 0.18, blue: 0.22),
                ],
                startPoint: .bottom,
                endPoint: .top)
        }
    }
}
