//
//  QualitySelectorRowViews.swift
//  Yattee
//
//  Row views for stream selection in quality selector.
//

import SwiftUI

#if os(tvOS)
/// Padding used inside selection row buttons so the tvOS focus background
/// fills the whole row.
private let tvRowVerticalPadding: CGFloat = 14
private let tvRowHorizontalPadding: CGFloat = 20
#endif

// MARK: - Adaptive Stream Row

/// Row view for HLS/DASH adaptive streams.
struct AdaptiveStreamRowView: View {
    let stream: Stream
    let isSelected: Bool
    let onTap: () -> Void

    private var format: StreamFormat {
        StreamFormat.detect(from: stream)
    }

    /// Quality label from resolution/fps if available
    private var qualityLabel: String? {
        if let resolution = stream.resolution {
            var label = resolution.description
            if let fps = stream.fps, fps > 30 {
                label += " \(fps)fps"
            }
            return label
        }
        return nil
    }

    var body: some View {
        Button(action: onTap) {
            HStack {
                VStack(alignment: .leading, spacing: 2) {
                    HStack(spacing: 6) {
                        Text(String(localized: format == .hls ? "stream.format.hls" : "stream.format.dash"))
                            .font(.headline)

                        // Show quality badge when available
                        if let quality = qualityLabel {
                            Text(quality)
                                .font(.caption2)
                                .padding(.horizontal, 6)
                                .padding(.vertical, 2)
                                .background(Color.accentColor.opacity(0.15))
                                .clipShape(Capsule())
                        }
                    }
                    Text(String(localized: format == .hls ? "stream.format.appleHLS" : "stream.format.mpegDash"))
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }

                Spacer()

                if isSelected {
                    Image(systemName: "checkmark")
                        .foregroundStyle(.tint)
                }
            }
            #if os(tvOS)
            .padding(.vertical, tvRowVerticalPadding)
            .padding(.horizontal, tvRowHorizontalPadding)
            .frame(maxWidth: .infinity, alignment: .leading)
            #endif
            .contentShape(Rectangle())
        }
        #if os(tvOS)
        .buttonStyle(TVSettingsRowButtonStyle())
        #else
        .buttonStyle(.plain)
        #endif
    }
}

// MARK: - Video Stream Row

/// Row view for video streams (muxed or video-only).
struct VideoStreamRowView: View {
    let stream: Stream
    let isSelected: Bool
    let isPreferredQuality: Bool
    let isDownloaded: Bool
    let showAdvancedDetails: Bool
    let requiresSoftwareDecode: Bool
    let onTap: () -> Void

    var body: some View {
        Button(action: onTap) {
            HStack {
                VStack(alignment: .leading, spacing: 2) {
                    titleRow
                    if showAdvancedDetails {
                        detailsRow
                    }
                }

                Spacer()

                if isSelected {
                    Image(systemName: "checkmark")
                        .foregroundStyle(.tint)
                }
            }
            .frame(minHeight: showAdvancedDetails ? nil : 36)
            #if os(tvOS)
            .padding(.vertical, tvRowVerticalPadding)
            .padding(.horizontal, tvRowHorizontalPadding)
            .frame(maxWidth: .infinity, alignment: .leading)
            #endif
            .contentShape(Rectangle())
        }
        #if os(tvOS)
        .buttonStyle(TVSettingsRowButtonStyle())
        #else
        .buttonStyle(.plain)
        #endif
    }

    @ViewBuilder
    private var titleRow: some View {
        HStack(spacing: 6) {
            if isDownloaded {
                Image(systemName: "arrow.down.circle.fill")
                    .font(.caption)
                    .foregroundStyle(.green)
            } else if isPreferredQuality {
                Image(systemName: "star.fill")
                    .font(.caption2)
                    .foregroundStyle(.orange)
            }

            Text(stream.qualityLabel)
                .font(.headline)

            if !stream.isMuxed && requiresSoftwareDecode {
                Image(systemName: "exclamationmark.triangle.fill")
                    .font(.caption2)
                    .foregroundStyle(.yellow)
                    .help(String(localized: "player.quality.softwareDecode.warning"))
            }

            if showAdvancedDetails {
                codecBadge
            }
        }
    }

    @ViewBuilder
    private var codecBadge: some View {
        if stream.isMuxed {
            Text(String(localized: "stream.badge.stream"))
                .font(.caption2)
                .padding(.horizontal, 6)
                .padding(.vertical, 2)
                .background(Color.green.opacity(0.2))
                .foregroundStyle(.green)
                .clipShape(Capsule())
        } else if let codec = stream.videoCodec {
            let isSoftware = requiresSoftwareDecode
            Text(formatCodec(codec))
                .font(.caption2)
                .padding(.horizontal, 6)
                .padding(.vertical, 2)
                .background(isSoftware ? Color.yellow.opacity(0.2) : codecColor(codec).opacity(0.2))
                .foregroundStyle(isSoftware ? .yellow : codecColor(codec))
                .clipShape(Capsule())
        }
    }

    @ViewBuilder
    private var detailsRow: some View {
        let details = formatStreamDetails(bitrate: stream.bitrate, fileSize: stream.formattedFileSize)
        if stream.isMuxed || !details.isEmpty {
            HStack(spacing: 4) {
                if stream.isMuxed {
                    Image(systemName: "speaker.wave.2.fill")
                        .font(.caption2)
                        .foregroundStyle(.secondary)
                }
                if !details.isEmpty {
                    Text(details)
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }
            }
        }
    }

    // MARK: - Formatting Helpers

    private func formatCodec(_ codec: String) -> String {
        let lowercased = codec.lowercased()
        if lowercased.contains("avc") || lowercased.contains("h264") {
            return "H.264"
        } else if lowercased.contains("hev") || lowercased.contains("h265") || lowercased.contains("hevc") {
            return "HEVC"
        } else if lowercased.contains("vp9") || lowercased.contains("vp09") {
            return "VP9"
        } else if lowercased.contains("av1") || lowercased.contains("av01") {
            return "AV1"
        }
        return codec.uppercased()
    }

    private func codecColor(_ codec: String) -> Color {
        let lowercased = codec.lowercased()
        if lowercased.contains("av1") || lowercased.contains("av01") {
            return .blue
        } else if lowercased.contains("vp9") || lowercased.contains("vp09") {
            return .orange
        } else if lowercased.contains("avc") || lowercased.contains("h264") {
            return .red
        } else if lowercased.contains("hev") || lowercased.contains("h265") || lowercased.contains("hevc") {
            return .green
        }
        return .gray
    }

    private func formatStreamDetails(bitrate: Int?, fileSize: String?) -> String {
        var parts: [String] = []
        if let bitrate {
            parts.append(formatBitrate(bitrate))
        }
        if let fileSize {
            parts.append(fileSize)
        }
        return parts.joined(separator: " · ")
    }

    private func formatBitrate(_ bitrate: Int) -> String {
        if bitrate >= 1_000_000 {
            return String(format: "%.1f Mbps", Double(bitrate) / 1_000_000)
        } else {
            return "\(bitrate / 1000) kbps"
        }
    }
}

// MARK: - Audio Stream Row

/// Row view for audio-only streams.
struct AudioStreamRowView: View {
    let stream: Stream
    let isSelected: Bool
    let isPreferred: Bool
    let showAdvancedDetails: Bool
    let trackInfo: AudioTrackInfo
    let onTap: () -> Void

    var body: some View {
        Button(action: onTap) {
            HStack {
                VStack(alignment: .leading, spacing: 2) {
                    titleRow
                    if showAdvancedDetails {
                        detailsRow
                    }
                }

                Spacer()

                if isSelected {
                    Image(systemName: "checkmark")
                        .foregroundStyle(.tint)
                }
            }
            .frame(minHeight: showAdvancedDetails ? nil : 36)
            #if os(tvOS)
            .padding(.vertical, tvRowVerticalPadding)
            .padding(.horizontal, tvRowHorizontalPadding)
            .frame(maxWidth: .infinity, alignment: .leading)
            #endif
            .contentShape(Rectangle())
        }
        #if os(tvOS)
        .buttonStyle(TVSettingsRowButtonStyle())
        #else
        .buttonStyle(.plain)
        #endif
    }

    @ViewBuilder
    private var titleRow: some View {
        HStack(spacing: 6) {
            if isPreferred {
                Image(systemName: "star.fill")
                    .font(.caption2)
                    .foregroundStyle(.orange)
            }

            Text(trackInfo.language)
                .font(.headline)

            if showAdvancedDetails, let codec = stream.audioCodec {
                Text(codec.uppercased())
                    .font(.caption2)
                    .padding(.horizontal, 6)
                    .padding(.vertical, 2)
                    .background(Color.purple.opacity(0.2))
                    .foregroundStyle(.purple)
                    .clipShape(Capsule())
            }
        }
    }

    @ViewBuilder
    private var detailsRow: some View {
        let details = formatAudioDetails(
            trackType: trackInfo.trackType,
            bitrate: stream.bitrate,
            fileSize: stream.formattedFileSize
        )
        if !details.isEmpty {
            Text(details)
                .font(.caption)
                .foregroundStyle(.secondary)
        }
    }

    private func formatAudioDetails(trackType: String?, bitrate: Int?, fileSize: String?) -> String {
        var parts: [String] = []
        if let trackType {
            parts.append(trackType)
        }
        if let bitrate {
            parts.append(formatBitrate(bitrate))
        }
        if let fileSize {
            parts.append(fileSize)
        }
        return parts.joined(separator: " · ")
    }

    private func formatBitrate(_ bitrate: Int) -> String {
        if bitrate >= 1_000_000 {
            return String(format: "%.1f Mbps", Double(bitrate) / 1_000_000)
        } else {
            return "\(bitrate / 1000) kbps"
        }
    }
}

// MARK: - Caption Row

/// Row view for caption/subtitle selection.
struct CaptionRowView: View {
    let caption: Caption?
    let isSelected: Bool
    let isPreferred: Bool
    let onTap: () -> Void

    var body: some View {
        Button(action: onTap) {
            HStack {
                VStack(alignment: .leading, spacing: 2) {
                    titleRow
                }

                Spacer()

                if isSelected {
                    Image(systemName: "checkmark")
                        .foregroundStyle(.tint)
                }
            }
            .frame(minHeight: 36)
            #if os(tvOS)
            .padding(.vertical, tvRowVerticalPadding)
            .padding(.horizontal, tvRowHorizontalPadding)
            .frame(maxWidth: .infinity, alignment: .leading)
            #endif
            .contentShape(Rectangle())
        }
        #if os(tvOS)
        .buttonStyle(TVSettingsRowButtonStyle())
        #else
        .buttonStyle(.plain)
        #endif
    }

    @ViewBuilder
    private var titleRow: some View {
        HStack(spacing: 6) {
            if isPreferred {
                Image(systemName: "star.fill")
                    .font(.caption2)
                    .foregroundStyle(.orange)
            }

            Text(caption?.displayName ?? String(localized: "stream.subtitles.off"))
                .font(.headline)

            if let caption, caption.isAutoGenerated {
                Text(String(localized: "stream.subtitle.auto"))
                    .font(.caption2)
                    .padding(.horizontal, 6)
                    .padding(.vertical, 2)
                    .background(Color.gray.opacity(0.2))
                    .foregroundStyle(.secondary)
                    .clipShape(Capsule())
            }
        }
    }
}

// MARK: - Embedded Track Row

/// Row view for embedded (in-container) audio/subtitle tracks reported by mpv.
struct EmbeddedTrackRowView: View {
    let track: MPVTrack
    let isSelected: Bool
    let isPreferred: Bool
    let showAdvancedDetails: Bool
    let onTap: () -> Void

    var body: some View {
        Button(action: onTap) {
            HStack {
                VStack(alignment: .leading, spacing: 2) {
                    titleRow
                    if showAdvancedDetails, let detail = track.detailText {
                        Text(detail)
                            .font(.caption)
                            .foregroundStyle(.secondary)
                    }
                }

                Spacer()

                if isSelected {
                    Image(systemName: "checkmark")
                        .foregroundStyle(.tint)
                }
            }
            .frame(minHeight: showAdvancedDetails ? nil : 36)
            #if os(tvOS)
            .padding(.vertical, tvRowVerticalPadding)
            .padding(.horizontal, tvRowHorizontalPadding)
            .frame(maxWidth: .infinity, alignment: .leading)
            #endif
            .contentShape(Rectangle())
        }
        #if os(tvOS)
        .buttonStyle(TVSettingsRowButtonStyle())
        #else
        .buttonStyle(.plain)
        #endif
    }

    @ViewBuilder
    private var titleRow: some View {
        HStack(spacing: 6) {
            if isPreferred {
                Image(systemName: "star.fill")
                    .font(.caption2)
                    .foregroundStyle(.orange)
            }

            Text(track.displayName)
                .font(.headline)

            if track.isDefault {
                badge(String(localized: "player.track.default"))
            }

            if track.isForced {
                badge(String(localized: "player.track.forced"))
            }
        }
    }

    private func badge(_ text: String) -> some View {
        Text(text)
            .font(.caption2)
            .padding(.horizontal, 6)
            .padding(.vertical, 2)
            .background(Color.gray.opacity(0.2))
            .foregroundStyle(.secondary)
            .clipShape(Capsule())
    }
}

// MARK: - Previews

#Preview("Adaptive Stream Row") {
    VStack(spacing: 0) {
        AdaptiveStreamRowView(
            stream: .hlsPreview,
            isSelected: true,
            onTap: {}
        )
        .padding()

        Divider()

        AdaptiveStreamRowView(
            stream: .hlsNoQualityPreview,
            isSelected: false,
            onTap: {}
        )
        .padding()
    }
    .cardBackground()
    .padding()
}

#Preview("Video Stream Row") {
    VStack(spacing: 0) {
        VideoStreamRowView(
            stream: .preview,
            isSelected: true,
            isPreferredQuality: true,
            isDownloaded: false,
            showAdvancedDetails: true,
            requiresSoftwareDecode: false,
            onTap: {}
        )
        .padding()

        Divider()

        VideoStreamRowView(
            stream: .videoOnlyPreview,
            isSelected: false,
            isPreferredQuality: false,
            isDownloaded: false,
            showAdvancedDetails: true,
            requiresSoftwareDecode: true,
            onTap: {}
        )
        .padding()
    }
    .cardBackground()
    .padding()
}

#Preview("Audio Stream Row") {
    VStack(spacing: 0) {
        AudioStreamRowView(
            stream: .audioPreview,
            isSelected: true,
            isPreferred: true,
            showAdvancedDetails: true,
            trackInfo: AudioTrackInfo(language: "English", trackType: "ORIGINAL"),
            onTap: {}
        )
        .padding()
    }
    .cardBackground()
    .padding()
}

#Preview("Caption Row") {
    VStack(spacing: 0) {
        CaptionRowView(
            caption: nil,
            isSelected: true,
            isPreferred: false,
            onTap: {}
        )
        .padding()

        Divider()

        CaptionRowView(
            caption: .preview,
            isSelected: false,
            isPreferred: true,
            onTap: {}
        )
        .padding()

        Divider()

        CaptionRowView(
            caption: .autoGeneratedPreview,
            isSelected: false,
            isPreferred: false,
            onTap: {}
        )
        .padding()
    }
    .cardBackground()
    .padding()
}
