import SwiftUI

struct RecordingWaveformView: View {
    let samples: [TimeInterval: CGFloat]
    let isRecording: Bool
    let currentDuration: TimeInterval
    let maxRecordTime: TimeInterval

    private let resolution: CGFloat = 200.0 // 200 points = 1 second of audio

    private let barWidth: CGFloat = 2.0
    private let barSpacing: CGFloat = 8.0

    // Pre-processed samples
    private var preprocessedSamples: [Int: CGFloat] {
        var processed: [Int: CGFloat] = [:]
        let bucketSize: TimeInterval = 0.05 // 50ms buckets

        for (sampleTime, value) in samples {
            let bucketIndex = Int(sampleTime / bucketSize)
            if let existing = processed[bucketIndex] {
                processed[bucketIndex] = max(existing, value)
            } else {
                processed[bucketIndex] = value
            }
        }
        return processed
    }

    var body: some View {
        GeometryReader { geometry in
            let screenWidth = geometry.size.width
            let screenTimeWidth = screenWidth / resolution // How many seconds fit on screen

            // Viewport follows recording: show from (currentDuration - screenTimeWidth) to currentDuration
            // Waveform moves right to left: newest data on the right, oldest on the left
            let viewportStartTime = max(0, currentDuration - screenTimeWidth)
            let viewportEndTime = currentDuration

            // Calculate how many bars we need to render
            // Each bar represents a time position, spaced by (barWidth + barSpacing)
            let barTimeStep = (barWidth + barSpacing) / resolution
            let startBarIndex = Int(viewportStartTime / barTimeStep)
            let endBarIndex = Int(viewportEndTime / barTimeStep) + 1

            ZStack {
                // Empty state
                if samples.isEmpty && !isRecording {
                    HStack(spacing: barSpacing) {
                        ForEach(0..<Int(screenWidth / (barWidth + barSpacing)), id: \.self) { _ in
                            Circle()
                                .fill(Color(hex: "#D9D9D9"))
                                .frame(width: barWidth, height: barWidth)
                        }
                    }
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                } else {

                    ForEach(startBarIndex..<endBarIndex, id: \.self) { barIndex in
                        let barTime = Double(barIndex) * barTimeStep

                        // Only render bars within the viewport
                        if barTime >= viewportStartTime && barTime <= viewportEndTime {
                            let barHeight = waveformHeight(for: barTime)

                            // Position bar: newest time (right side) = screenWidth, oldest (left side) = 0
                            // Reverse the calculation so currentDuration maps to right edge
                            let barX = screenWidth - ((viewportEndTime - barTime) * resolution)

                            RoundedRectangle(cornerRadius: 100)
                                .fill(Color(hex: "#D9D9D9"))
                                .frame(width: barWidth, height: barHeight)
                                .position(x: barX, y: geometry.size.height / 2)
                        }
                    }
                }
            }
            .clipped()
        }
    }

    private func waveformHeight(for time: TimeInterval) -> CGFloat {
        let baseHeight: CGFloat = 5
        let maxHeight: CGFloat = 80
        let bucketSize: TimeInterval = 0.05 // Match preprocessing bucket size

        let bucketIndex = Int(time / bucketSize)

        var closestValue: CGFloat?
        var minDistance: TimeInterval = 0.15 // Max search distance

        for offset in -1...1 {
            let checkIndex = bucketIndex + offset
            if let value = preprocessedSamples[checkIndex] {
                let bucketTime = Double(checkIndex) * bucketSize
                let distance = abs(bucketTime - time)
                if distance < minDistance {
                    minDistance = distance
                    closestValue = value
                }
            }
        }

        if let value = closestValue {
            // Use actual sample value to determine height
            // Sample value is already normalized (0.01 to ~1.0 based on power levels)
            let height = value * (maxHeight - baseHeight) + baseHeight
            return min(max(height, baseHeight), maxHeight)
        }

        // Fallback: Show minimal height for bars without samples
        return baseHeight
    }
}
