// Bottom-sheet wybór jakości po resolve. Sortuje malejąco po pikselach (4K > 1080 > 720 > ...).
// Single quality → caller pomija modal i odpala od razu.
import React from 'react';
import {
  Modal,
  Pressable,
  ScrollView,
  StyleSheet,
  Text,
  View,
} from 'react-native';
import { theme } from '../theme';
import type { DefaultQuality } from '../storage';
import type { StreamLink } from '../types';

export function qualityToInt(q: string | null | undefined): number {
  if (!q) return 0;
  const s = q.toLowerCase();
  if (s.includes('4k') || s.includes('uhd')) return 2160;
  if (s.includes('2k') || s.includes('qhd')) return 1440;
  const m = s.match(/\d+/);
  if (m) return parseInt(m[0], 10);
  if (s.includes('fhd')) return 1080;
  if (s.includes('hd')) return 720;
  if (s.includes('sd')) return 480;
  return 0;
}

export function sortByQualityDesc(links: StreamLink[]): StreamLink[] {
  return [...links].sort((a, b) => qualityToInt(b.quality) - qualityToInt(a.quality));
}

/**
 * Wybierz link pasujący do domyślnej jakości usera; `null` → pokaż picker (auto, brak
 * dopasowania, albo same nieznane jakości). Reguła: największa wysokość <= target;
 * gdy nic <= target (wszystkie wyższe) → najbliższa. 'lowest' → najmniejsza dodatnia.
 * Linki o nieznanej wysokości (qualityToInt=0) pomijamy gdy jest jakikolwiek znany, żeby
 * nieopisany link nie udawał wybranej jakości. NIE dotyczy movie parts (tam preserveOrder).
 */
export function pickByDefaultQuality(
  links: StreamLink[],
  pref: DefaultQuality,
): StreamLink | null {
  if (pref === 'auto' || links.length === 0) return null;
  const known = links
    .map((l) => ({ l, px: qualityToInt(l.quality) }))
    .filter((x) => x.px > 0);
  if (known.length === 0) return null;
  if (pref === 'lowest') {
    return known.reduce((a, b) => (b.px < a.px ? b : a)).l;
  }
  const target = pref;
  const atOrBelow = known.filter((x) => x.px <= target);
  if (atOrBelow.length > 0) {
    return atOrBelow.reduce((a, b) => (b.px > a.px ? b : a)).l; // największa <= target
  }
  return known.reduce((a, b) =>
    Math.abs(b.px - target) < Math.abs(a.px - target) ? b : a,
  ).l; // wszystkie wyższe → najbliższa
}

export function PlaybackQualityModal({
  visible,
  links,
  onSelect,
  onCancel,
  title = 'Select quality',
  /**
   * preserveOrder=true → nie sortuj (zachowaj kolejność z `links`). Używane dla
   * paradisehill multipart picker gdzie chcemy Part 1..N rosnąco, nie po "quality"
   * (qualityToInt("Part 35")=35 sortowałby części od końca).
   */
  preserveOrder = false,
}: {
  visible: boolean;
  links: StreamLink[];
  onSelect: (link: StreamLink) => void;
  onCancel: () => void;
  title?: string;
  preserveOrder?: boolean;
}) {
  const sorted = React.useMemo(
    () => (preserveOrder ? links : sortByQualityDesc(links)),
    [links, preserveOrder],
  );

  return (
    <Modal
      visible={visible}
      transparent
      animationType="fade"
      onRequestClose={onCancel}
    >
      <Pressable style={styles.backdrop} onPress={onCancel}>
        <Pressable style={styles.sheet} onPress={(e) => e.stopPropagation()}>
          <Text style={styles.title}>{title}</Text>
          {/* ScrollView: paradisehill movie może mieć 35+ parts — bez scrolla sheet
              przekraczał ekran i część była nieosiągalna. (Android Alert.alert capował
              do 3 buttonów — bug-report 2ebd0690 2026-06-07 "35 parts, 3 w popup".) */}
          <ScrollView style={styles.list} contentContainerStyle={styles.listContent}>
            {sorted.map((link, i) => {
              const px = qualityToInt(link.quality);
              return (
                <Pressable
                  key={`${link.stream_url || link.embed_url}-${i}`}
                  style={styles.row}
                  onPress={() => onSelect(link)}
                >
                  <Text style={styles.rowQuality}>
                    {link.quality || 'unknown'}
                  </Text>
                  <Text style={styles.rowMeta}>
                    {px >= 144 ? `${px}p` : ''}
                    {link.type ? ` · ${shortType(link.type)}` : ''}
                  </Text>
                </Pressable>
              );
            })}
          </ScrollView>
          <Pressable style={styles.cancel} onPress={onCancel}>
            <Text style={styles.cancelText}>Cancel</Text>
          </Pressable>
        </Pressable>
      </Pressable>
    </Modal>
  );
}

function shortType(t: string): string {
  const low = t.toLowerCase();
  if (low.includes('mp4') || low === 'direct') return 'mp4';
  if (low.includes('mpegurl') || low.includes('m3u8')) return 'hls';
  if (low.includes('dash')) return 'dash';
  if (low.includes('webm')) return 'webm';
  return t;
}

const styles = StyleSheet.create({
  backdrop: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.6)',
    justifyContent: 'flex-end',
  },
  sheet: {
    backgroundColor: theme.bg,
    borderTopLeftRadius: 16,
    borderTopRightRadius: 16,
    paddingHorizontal: 16,
    paddingTop: 14,
    paddingBottom: 24,
    borderTopColor: theme.border,
    borderTopWidth: 1,
  },
  list: { maxHeight: 380 },
  listContent: { paddingBottom: 2 },
  title: {
    color: theme.muted,
    fontSize: 12,
    textTransform: 'uppercase',
    letterSpacing: 0.5,
    marginBottom: 10,
  },
  row: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    backgroundColor: theme.card,
    borderColor: theme.border,
    borderWidth: 1,
    borderRadius: 8,
    padding: 14,
    marginBottom: 8,
  },
  rowQuality: { color: theme.fg, fontSize: 16, fontWeight: '600' },
  rowMeta: { color: theme.muted, fontSize: 13 },
  cancel: {
    marginTop: 6,
    padding: 12,
    alignItems: 'center',
  },
  cancelText: { color: theme.muted, fontSize: 14 },
});
