import SwiftUI
import AVFoundation

struct PlayerControlsView: View {
    let currentTrack: Track?
    let isPlaying: Bool
    let currentTime: Double
    let duration: Double
    let volume: Float
    let isShuffled: Bool
    let onPlayPause: () -> Void
    let onNext: () -> Void
    let onPrevious: () -> Void
    let onSeek: (Double) -> Void
    let onScrubStart: () -> Void
    let onScrub: (Double) -> Void
    let onScrubEnd: (Double) -> Void
    let onVolumeChange: (Float) -> Void
    let onShuffleToggle: () -> Void
    let onNowPlayingTap: () -> Void

    @State private var isDragging = false
    @State private var dragValue: Double = 0
    @State private var artworkImage: NSImage?

    var body: some View {
        VStack(spacing: 0) {
            progressTrack
            HStack(spacing: 0) {
                nowPlayingSection
                    .frame(maxWidth: .infinity, alignment: .leading)

                transportSection
                    .frame(maxWidth: .infinity)

                volumeSection
                    .frame(maxWidth: .infinity, alignment: .trailing)
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 8)
        }
        .background(.bar)
        .onChange(of: currentTrack?.id) {
            loadArtwork()
        }
        .onAppear {
            loadArtwork()
        }
    }

    private func loadArtwork() {
        guard let urlString = currentTrack?.fileURL,
              let url = URL(string: urlString) else {
            artworkImage = nil
            return
        }
        Task.detached {
            let asset = AVURLAsset(url: url)
            let metadata = try? await asset.load(.metadata)
            let data = try? await metadata?
                .first { $0.commonKey == .commonKeyArtwork }?
                .load(.dataValue)
            let image = data.flatMap { NSImage(data: $0) }
            await MainActor.run { artworkImage = image }
        }
    }

    private var nowPlayingSection: some View {
        HStack(spacing: 12) {
            RoundedRectangle(cornerRadius: 6)
                .fill(.quaternary)
                .frame(width: 44, height: 44)
                .overlay {
                    if let artworkImage {
                        Image(nsImage: artworkImage)
                            .resizable()
                            .aspectRatio(contentMode: .fill)
                    } else {
                        Image(systemName: "music.note")
                            .foregroundStyle(.secondary)
                    }
                }
                .clipShape(RoundedRectangle(cornerRadius: 6))

            if let track = currentTrack {
                VStack(alignment: .leading, spacing: 2) {
                    Text(track.title)
                        .font(.system(size: 13, weight: .medium))
                        .lineLimit(1)
                    Text("\(track.artist) — \(track.album)")
                        .font(.system(size: 11))
                        .foregroundStyle(.secondary)
                        .lineLimit(1)
                }
            }
        }
        .contentShape(Rectangle())
        .onTapGesture {
            if currentTrack != nil {
                onNowPlayingTap()
            }
        }
    }

    private var progressTrack: some View {
        let trackHeight: CGFloat = 4
        let thumbWidth: CGFloat = 4
        let thumbHeight: CGFloat = 12
        let displayedTime = isDragging ? dragValue : currentTime
        let maxDuration = max(duration, 1)
        let fraction = displayedTime / maxDuration

        return VStack(spacing: 2) {
            GeometryReader { geo in
                let trackWidth = geo.size.width
                ZStack(alignment: .leading) {
                    Rectangle()
                        .fill(.quaternary)
                        .frame(height: trackHeight)

                    Rectangle()
                        .fill(.blue)
                        .frame(width: trackWidth * fraction, height: trackHeight)

                    RoundedRectangle(cornerRadius: 1)
                        .fill(.blue)
                        .frame(width: thumbWidth, height: thumbHeight)
                        .offset(x: trackWidth * fraction - thumbWidth / 2)
                }
                .frame(maxHeight: .infinity)
                .contentShape(Rectangle())
                .gesture(
                    DragGesture(minimumDistance: 0)
                        .onChanged { value in
                            let newValue = min(max(Double(value.location.x / trackWidth) * maxDuration, 0), maxDuration)
                            if !isDragging {
                                isDragging = true
                                dragValue = currentTime
                                onScrubStart()
                            }
                            dragValue = newValue
                            onScrub(newValue)
                        }
                        .onEnded { value in
                            let newValue = min(max(Double(value.location.x / trackWidth) * maxDuration, 0), maxDuration)
                            onScrubEnd(newValue)
                            isDragging = false
                        }
                )
            }
            .frame(height: thumbHeight)

            HStack {
                Text(Self.formatTime(displayedTime))
                    .font(.system(size: 10).monospacedDigit())
                    .foregroundStyle(.secondary)
                Spacer()
                Text(Self.formatTime(duration))
                    .font(.system(size: 10).monospacedDigit())
                    .foregroundStyle(.secondary)
            }
            .padding(.horizontal, 8)
        }
    }

    private var transportSection: some View {
        HStack(spacing: 20) {
            Button(action: onShuffleToggle) {
                Image(systemName: "shuffle")
                    .font(.system(size: 12))
                    .foregroundStyle(isShuffled ? .blue : .secondary)
            }
            .buttonStyle(.plain)

            Button(action: onPrevious) {
                Image(systemName: "backward.fill")
                    .font(.system(size: 14))
            }
            .buttonStyle(.plain)

            Button(action: onPlayPause) {
                Image(systemName: isPlaying ? "pause.fill" : "play.fill")
                    .font(.system(size: 22))
                    .frame(width: 24, height: 24)
            }
            .buttonStyle(.plain)

            Button(action: onNext) {
                Image(systemName: "forward.fill")
                    .font(.system(size: 14))
            }
            .buttonStyle(.plain)
        }
        .frame(maxWidth: 400)
    }

    private var volumeSection: some View {
        HStack(spacing: 8) {
            Image(systemName: volumeIconName)
                .font(.system(size: 12))
                .foregroundStyle(.secondary)
                .frame(width: 16)

            Slider(
                value: Binding(
                    get: { Double(volume) },
                    set: { onVolumeChange(Float($0)) }
                ),
                in: 0...1
            )
            .controlSize(.small)
            .frame(width: 80)
        }
    }

    private var volumeIconName: String {
        if volume == 0 { return "speaker.slash.fill" }
        if volume < 0.33 { return "speaker.wave.1.fill" }
        if volume < 0.66 { return "speaker.wave.2.fill" }
        return "speaker.wave.3.fill"
    }

    static func formatTime(_ seconds: Double) -> String {
        guard seconds.isFinite, seconds >= 0 else { return "0:00" }
        let mins = Int(seconds) / 60
        let secs = Int(seconds) % 60
        return "\(mins):\(String(format: "%02d", secs))"
    }
}
