import SwiftUI

/// Live intonation gauge shown while recording: needle position = cents off
/// the score's current target note, ±50 cents full scale.
struct PitchNeedle: View {
    @Bindable var model: ProjectModel

    var body: some View {
        TimelineView(.periodic(from: .now, by: 0.1)) { _ in
            let cents = model.currentPitchCents()
            HStack(spacing: 10) {
                Image(systemName: "tuningfork")
                    .font(.caption)
                    .foregroundStyle(.secondary)
                GeometryReader { geo in
                    ZStack {
                        // Track with green center zone (±10¢).
                        Capsule()
                            .fill(Color(.systemGray5))
                        Capsule()
                            .fill(Color.green.opacity(0.35))
                            .frame(width: geo.size.width * 0.2)
                        Rectangle()
                            .fill(Color(.systemGray3))
                            .frame(width: 1)

                        if let cents {
                            let clamped: CGFloat = CGFloat(max(-50, min(50, cents)))
                            let halfWidth: CGFloat = geo.size.width / 2 - 4
                            let x: CGFloat = geo.size.width / 2 + (clamped / 50) * halfWidth
                            Circle()
                                .fill(abs(cents) <= 10 ? Color.green :
                                      (abs(cents) <= 25 ? Color.yellow : Color.red))
                                .frame(width: 12, height: 12)
                                .position(x: x, y: geo.size.height / 2)
                                .animation(.linear(duration: 0.1), value: clamped)
                        }
                    }
                }
                .frame(height: 14)
                Text(label(for: cents))
                    .font(.caption2.monospacedDigit())
                    .foregroundStyle(.secondary)
                    .frame(width: 44, alignment: .trailing)
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 6)
            .background(Color(.systemGray6))
        }
    }

    private func label(for cents: Double?) -> String {
        guard let cents else { return "–" }
        if abs(cents) <= 10 { return "in tune" }
        return String(format: "%+.0f¢", cents)
    }
}
