import AVFoundation
import NitroModules

/// Track-selection surface of ``HybridPlaybackEngine``, split out of the main
/// bridge file to keep that type focused. Selections are stored on the engine
/// (see the `_videoTrackSelection` / `_subtitleTrackSelection` /
/// `_audioTrackSelection` fields) so they persist across item changes;
/// `reapplyTrackSelections()` — called after each new item reaches
/// readyToPlay — re-applies the stored values to the new `AVPlayerItem`.
extension HybridPlaybackEngine {
    func selectVideoTrack(selection: VideoTrackSelection) throws {
        _videoTrackSelection = selection
        applyVideoTrackToCurrentItem()
    }

    func selectSubtitleTrack(selection: SubtitleTrackSelection) throws {
        _subtitleTrackSelection = selection
        applySubtitleTrackToCurrentItem()
    }

    func selectAudioTrack(selection: AudioTrackSelection) throws {
        _audioTrackSelection = selection
        applyAudioTrackToCurrentItem()
    }

    /// Called after each new item reaches readyToPlay (from onTracksDiscovered path).
    func reapplyTrackSelections() {
        applyVideoTrackToCurrentItem()
        applySubtitleTrackToCurrentItem()
        applyAudioTrackToCurrentItem()
    }

    private func applyVideoTrackToCurrentItem() {
        guard let item = avDecoder?.avPlayer?.currentItem else { return }
        switch _videoTrackSelection.type {
        case .auto:
            item.preferredMaximumResolution = .zero
        case .disabled:
            item.preferredMaximumResolution = CGSize(width: 1, height: 1)
        case .resolution:
            let height = _videoTrackSelection.value.flatMap { Int($0) } ?? 0
            item.preferredMaximumResolution = CGSize(width: Int.max, height: height)
        case .index:
            break // Not supported on iOS HLS
        }
    }

    private func applySubtitleTrackToCurrentItem() {
        guard let item = avDecoder?.avPlayer?.currentItem,
              item.status == .readyToPlay,
              let group = item.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else { return }
        switch _subtitleTrackSelection.type {
        case .auto:
            item.selectMediaOptionAutomatically(in: group)
        case .disabled:
            item.select(nil, in: group)
        case .language:
            guard let lang = _subtitleTrackSelection.value else { return }
            let options = AVMediaSelectionGroup.mediaSelectionOptions(from: group.options, with: Locale(identifier: lang))
            if let match = options.first { item.select(match, in: group) }
        case .index:
            guard let indexStr = _subtitleTrackSelection.value, let index = Int(indexStr),
                  index >= 0, index < group.options.count else { return }
            item.select(group.options[index], in: group)
        }
    }

    private func applyAudioTrackToCurrentItem() {
        guard let item = avDecoder?.avPlayer?.currentItem,
              item.status == .readyToPlay,
              let group = item.asset.mediaSelectionGroup(forMediaCharacteristic: .audible) else { return }
        switch _audioTrackSelection.type {
        case .auto:
            item.selectMediaOptionAutomatically(in: group)
        case .language:
            guard let lang = _audioTrackSelection.value else { return }
            let options = AVMediaSelectionGroup.mediaSelectionOptions(from: group.options, with: Locale(identifier: lang))
            if let match = options.first { item.select(match, in: group) }
        case .index:
            guard let indexStr = _audioTrackSelection.value, let index = Int(indexStr),
                  index >= 0, index < group.options.count else { return }
            item.select(group.options[index], in: group)
        }
    }
}
