//
//  MacOSControlBar.swift
//  Yattee
//
//  Condensed QuickTime-style control bar for macOS player.
//

#if os(macOS)

import SwiftUI

/// Condensed QuickTime-style control bar with transport, timeline, and action controls.
struct MacOSControlBar: View {
    @Bindable var playerState: PlayerState

    // MARK: - Callbacks

    let onPlayPause: () -> Void
    let onSeek: (TimeInterval) async -> Void
    let onSeekForward: (TimeInterval) async -> Void
    let onSeekBackward: (TimeInterval) async -> Void
    var onToggleFullscreen: (() -> Void)? = nil
    var isFullscreen: Bool = false
    var onTogglePiP: (() -> Void)? = nil
    var onPlayNext: (() async -> Void)? = nil
    var onVolumeChanged: ((Float) -> Void)? = nil
    var onMuteToggled: (() -> Void)? = nil
    var onShowSettings: (() -> Void)? = nil
    /// Whether to show chapter markers on the progress bar (default: true)
    var showChapters: Bool = true
    /// SponsorBlock segments to display on the progress bar.
    var sponsorSegments: [SponsorBlockSegment] = []
    /// Settings for SponsorBlock segment display.
    var sponsorBlockSettings: SponsorBlockSegmentSettings = .default
    /// Color for the played portion of the progress bar.
    var playedColor: Color = .red

    /// Called when user starts interacting (scrubbing, adjusting volume)
    var onInteractionStarted: (() -> Void)? = nil
    /// Called when user stops interacting
    var onInteractionEnded: (() -> Void)? = nil

    // MARK: - State

    @State private var isDragging = false
    @State private var dragProgress: Double = 0
    @State private var isHoveringProgress = false
    @State private var hoverProgress: Double = 0
    @State private var playNextTapCount = 0
    @State private var seekBackwardTrigger = 0
    @State private var seekForwardTrigger = 0

    // MARK: - Computed Properties

    /// Whether transport controls should be disabled
    private var isTransportDisabled: Bool {
        playerState.playbackState == .loading ||
        playerState.playbackState == .buffering ||
        !playerState.isFirstFrameReady ||
        !playerState.isBufferReady
    }

    private var playPauseIcon: String {
        switch playerState.playbackState {
        case .playing:
            return "pause.fill"
        default:
            return "play.fill"
        }
    }

    private var displayProgress: Double {
        isDragging ? dragProgress : playerState.progress
    }

    private var bufferedProgress: Double {
        guard playerState.duration > 0 else { return 0 }
        return playerState.bufferedTime / playerState.duration
    }

    // MARK: - Body

    var body: some View {
        VStack(spacing: 8) {
            // Top row: volume | transport (centered) | actions
            topRowControls

            // Bottom row: timeline (expanded width)
            timelineControls
        }
        .padding(.horizontal, 16)
        .padding(.vertical, 10)
        .frame(maxWidth: 500)
        .glassBackground(.regular, in: .rect(cornerRadius: 16))
        .shadow(color: .black.opacity(0.3), radius: 8, y: 4)
        // Seek preview overlay - positioned above the control bar
        .overlay(alignment: .bottom) {
            if let storyboard = playerState.preferredStoryboard,
               (isDragging || isHoveringProgress),
               !playerState.isLive {
                GeometryReader { geometry in
                    let previewProgress = isDragging ? dragProgress : hoverProgress
                    // Progress bar spans full width minus padding and time labels
                    // Time labels ~50px each, spacing ~16px = ~116px total for labels
                    let horizontalPadding: CGFloat = 16
                    let timeLabelWidth: CGFloat = 50
                    let spacing: CGFloat = 8
                    let progressBarOffset: CGFloat = horizontalPadding + timeLabelWidth + spacing
                    let progressBarWidth: CGFloat = geometry.size.width - (2 * horizontalPadding) - (2 * timeLabelWidth) - (2 * spacing)
                    let previewWidth: CGFloat = 176 // 160 + 16 padding
                    let xOffset = progressBarOffset + (progressBarWidth * previewProgress) - (previewWidth / 2)
                    let clampedX = max(0, min(geometry.size.width - previewWidth, xOffset))

                    seekPreviewView(storyboard: storyboard)
                        .offset(x: clampedX, y: -150)
                }
            }
        }
    }

    // MARK: - Top Row Controls

    private var topRowControls: some View {
        HStack(spacing: 0) {
            // Left: Volume controls
            volumeControls

            Spacer()

            // Center: Transport controls
            transportControls

            Spacer()

            // Right: Action buttons (settings, PiP, fullscreen)
            trailingActionControls
        }
    }

    // MARK: - Transport Controls

    private var transportControls: some View {
        HStack(spacing: 4) {
            // Skip backward
            Button {
                seekBackwardTrigger += 1
                Task { await onSeekBackward(10) }
            } label: {
                Image(systemName: "10.arrow.trianglehead.counterclockwise")
                    .font(.system(size: 14, weight: .medium))
                    .frame(width: 28, height: 28)
                    .contentShape(Rectangle())
                    .symbolEffect(.rotate.byLayer, options: .speed(2).nonRepeating, value: seekBackwardTrigger)
            }
            .buttonStyle(MacOSControlButtonStyle())
            .disabled(isTransportDisabled)

            // Play/Pause
            if !isTransportDisabled {
                Button {
                    onPlayPause()
                } label: {
                    Image(systemName: playPauseIcon)
                        .font(.system(size: 16, weight: .medium))
                        .frame(width: 32, height: 32)
                        .contentShape(Rectangle())
                        .contentTransition(.symbolEffect(.replace, options: .speed(2)))
                }
                .buttonStyle(MacOSControlButtonStyle())
            } else {
                // Spacer to maintain layout
                Color.clear
                    .frame(width: 32, height: 32)
            }

            // Skip forward
            Button {
                seekForwardTrigger += 1
                Task { await onSeekForward(10) }
            } label: {
                Image(systemName: "10.arrow.trianglehead.clockwise")
                    .font(.system(size: 14, weight: .medium))
                    .frame(width: 28, height: 28)
                    .contentShape(Rectangle())
                    .symbolEffect(.rotate.byLayer, options: .speed(2).nonRepeating, value: seekForwardTrigger)
            }
            .buttonStyle(MacOSControlButtonStyle())
            .disabled(isTransportDisabled)

            // Play next (if queue has items)
            if let onPlayNext, playerState.hasNext {
                Button {
                    playNextTapCount += 1
                    Task { await onPlayNext() }
                } label: {
                    Image(systemName: "forward.fill")
                        .font(.system(size: 12, weight: .medium))
                        .frame(width: 28, height: 28)
                        .contentShape(Rectangle())
                        .symbolEffect(.bounce.down.byLayer, options: .nonRepeating, value: playNextTapCount)
                }
                .buttonStyle(MacOSControlButtonStyle())
            }
        }
    }

    // MARK: - Timeline Controls

    private var timelineControls: some View {
        HStack(spacing: 8) {
            if playerState.isLive {
                // Live indicator
                HStack(spacing: 4) {
                    Circle()
                        .fill(.red)
                        .frame(width: 6, height: 6)
                    Text(String(localized: "player.live"))
                        .font(.system(size: 11, weight: .semibold))
                        .foregroundStyle(.red)
                }
            } else {
                // Current time
                Text(playerState.formattedCurrentTime)
                    .font(.system(size: 11, weight: .medium, design: .monospaced))
                    .foregroundStyle(.primary)
                    .lineLimit(1)
                    .fixedSize()

                // Progress bar (expands to fill available width)
                progressBar

                // Duration
                Text(playerState.formattedDuration)
                    .font(.system(size: 11, weight: .medium, design: .monospaced))
                    .foregroundStyle(.secondary)
                    .lineLimit(1)
                    .fixedSize()
            }
        }
    }

    private var progressBar: some View {
        GeometryReader { geometry in
            ZStack(alignment: .leading) {
                // Progress bar with chapter segments
                SegmentedProgressBar(
                    chapters: showChapters ? playerState.chapters : [],
                    duration: playerState.duration,
                    currentTime: isDragging ? dragProgress * playerState.duration : playerState.currentTime,
                    bufferedTime: playerState.bufferedTime,
                    height: 4,
                    gapWidth: 2,
                    playedColor: playedColor,
                    bufferedColor: .primary.opacity(0.3),
                    backgroundColor: .primary.opacity(0.2),
                    sponsorSegments: sponsorSegments,
                    sponsorBlockSettings: sponsorBlockSettings
                )

                // Scrubber handle
                Circle()
                    .fill(.white)
                    .frame(width: 12, height: 12)
                    .shadow(color: .black.opacity(0.3), radius: 2, y: 1)
                    .offset(x: geometry.size.width * displayProgress - 6)
                    .opacity(isDragging || isHoveringProgress ? 1 : 0)
            }
            .frame(height: 20)
            .contentShape(Rectangle())
            .gesture(
                DragGesture(minimumDistance: 0)
                    .onChanged { value in
                        if !isDragging {
                            isDragging = true
                            onInteractionStarted?()
                        }
                        let progress = max(0, min(1, value.location.x / geometry.size.width))
                        dragProgress = progress
                    }
                    .onEnded { value in
                        isDragging = false
                        let progress = max(0, min(1, value.location.x / geometry.size.width))
                        let seekTime = progress * playerState.duration
                        Task { await onSeek(seekTime) }
                        onInteractionEnded?()
                    }
            )
            .onContinuousHover { phase in
                switch phase {
                case .active(let location):
                    isHoveringProgress = true
                    hoverProgress = max(0, min(1, location.x / geometry.size.width))
                case .ended:
                    isHoveringProgress = false
                }
            }
        }
        .frame(height: 20)
    }

    @ViewBuilder
    private func seekPreviewView(storyboard: Storyboard) -> some View {
        let previewProgress = isDragging ? dragProgress : hoverProgress
        let seekTime = previewProgress * playerState.duration

        SeekPreviewView(
            storyboard: storyboard,
            seekTime: seekTime,
            storyboardService: StoryboardService.shared,
            buttonBackground: .none,
            theme: .dark,
            chapters: showChapters ? playerState.chapters : []
        )
        .transition(.opacity.combined(with: .scale(scale: 0.9)))
        .animation(.easeInOut(duration: 0.15), value: isDragging || isHoveringProgress)
    }

    // MARK: - Trailing Action Controls

    private var trailingActionControls: some View {
        HStack(spacing: 4) {
            // Settings
            if let onShowSettings {
                Button {
                    onShowSettings()
                } label: {
                    Image(systemName: "gearshape")
                        .font(.system(size: 13, weight: .medium))
                        .frame(width: 28, height: 28)
                        .contentShape(Rectangle())
                }
                .buttonStyle(MacOSControlButtonStyle())
            }

            // PiP
            if let onTogglePiP, playerState.isPiPPossible {
                Button {
                    onTogglePiP()
                } label: {
                    Image(systemName: playerState.pipState == .active ? "pip.exit" : "pip.enter")
                        .font(.system(size: 13, weight: .medium))
                        .frame(width: 28, height: 28)
                        .contentShape(Rectangle())
                }
                .buttonStyle(MacOSControlButtonStyle())
            }

            // Fullscreen
            if let onToggleFullscreen {
                Button {
                    onToggleFullscreen()
                } label: {
                    Image(systemName: isFullscreen ? "arrow.down.right.and.arrow.up.left" : "arrow.up.left.and.arrow.down.right")
                        .font(.system(size: 13, weight: .medium))
                        .frame(width: 28, height: 28)
                        .contentShape(Rectangle())
                }
                .buttonStyle(MacOSControlButtonStyle())
            }
        }
    }

    private var volumeControls: some View {
        HStack(spacing: 2) {
            // Mute/unmute button
            Button {
                onMuteToggled?()
            } label: {
                Image(systemName: volumeIcon)
                    .font(.system(size: 12, weight: .medium))
                    .frame(width: 24, height: 28)
                    .contentShape(Rectangle())
            }
            .buttonStyle(MacOSControlButtonStyle())

            // Volume slider
            Slider(
                value: Binding(
                    get: { Double(playerState.volume) },
                    set: { newValue in
                        playerState.volume = Float(newValue)
                        onVolumeChanged?(Float(newValue))
                    }
                ),
                in: 0...1,
                onEditingChanged: { editing in
                    if editing {
                        onInteractionStarted?()
                    } else {
                        onInteractionEnded?()
                    }
                }
            )
            .frame(width: 70)
            .controlSize(.mini)
            .disabled(playerState.isMuted)
            .opacity(playerState.isMuted ? 0.5 : 1.0)
        }
    }

    private var volumeIcon: String {
        if playerState.isMuted || playerState.volume == 0 {
            return "speaker.slash.fill"
        } else if playerState.volume < 0.33 {
            return "speaker.wave.1.fill"
        } else if playerState.volume < 0.66 {
            return "speaker.wave.2.fill"
        } else {
            return "speaker.wave.3.fill"
        }
    }
}

// MARK: - Button Style

/// Subtle button style for macOS control bar buttons.
struct MacOSControlButtonStyle: ButtonStyle {
    @Environment(\.isEnabled) private var isEnabled

    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .foregroundStyle(isEnabled ? .primary : .secondary)
            .opacity(configuration.isPressed ? 0.6 : 1.0)
            .scaleEffect(configuration.isPressed ? 0.95 : 1.0)
            .animation(.easeInOut(duration: 0.1), value: configuration.isPressed)
    }
}

// MARK: - Preview

#Preview {
    ZStack {
        Color.gray.opacity(0.3)

        MacOSControlBar(
            playerState: PlayerState(),
            onPlayPause: {},
            onSeek: { _ in },
            onSeekForward: { _ in },
            onSeekBackward: { _ in }
        )
        .frame(width: 650)
    }
    .frame(width: 800, height: 200)
}

#endif
