import React, { useMemo, useRef, useState } from "react";
import {
  StyleSheet,
  Text,
  View,
  TextInput,
  TouchableOpacity,
  FlatList,
  Modal,
  ActivityIndicator,
  Alert,
  Image,
  SectionList,
  Linking,
  Animated,
  Easing,
} from "react-native";
import * as Sharing from "expo-sharing";
import {
  useMedia,
  resolveMediaUri,
  type MediaItem,
} from "../../context/MediaContext";
import { Ionicons } from "@expo/vector-icons";
import { router } from "expo-router";
import PlaylistPickerModal from "../../components/PlaylistPickerModal";
import { API_BASE_URL } from "../../config";
import { authFetch } from "../../lib/apiFetch";
import type {
  VideoMetadata,
  PlaylistVideo,
  PlaylistData,
} from "../../types/download";
import { formatBytes, dateSectionLabel, dayStart } from "../../utils/format";
import { useViewMode } from "../../hooks/useViewMode";
import { useMiniPlayerInset } from "../../hooks/useMiniPlayerInset";
import { useServiceStatus } from "../../context/ServiceStatusContext";
import ServiceStatusBanner from "../../components/ServiceStatusBanner";

function formatDuration(seconds?: number | null) {
  if (!seconds && seconds !== 0) return null;
  const m = Math.floor(seconds / 60);
  const s = Math.floor(seconds % 60);
  return `${m}:${s.toString().padStart(2, "0")}`;
}

function formatDownloadedAt(ms: number) {
  return new Date(ms).toLocaleString(undefined, {
    month: "short",
    day: "numeric",
    hour: "numeric",
    minute: "2-digit",
  });
}

type SortMode = "date-desc" | "date-asc" | "name-asc" | "name-desc" | "size-desc" | "size-asc";

const SORT_OPTIONS: { mode: SortMode; label: string; icon: keyof typeof Ionicons.glyphMap }[] = [
  { mode: "date-desc", label: "Newest first", icon: "time-outline" },
  { mode: "date-asc", label: "Oldest first", icon: "time-outline" },
  { mode: "name-asc", label: "Name (A–Z)", icon: "text-outline" },
  { mode: "name-desc", label: "Name (Z–A)", icon: "text-outline" },
  { mode: "size-desc", label: "Largest first", icon: "swap-vertical-outline" },
  { mode: "size-asc", label: "Smallest first", icon: "swap-vertical-outline" },
];

type DateSection = {
  key: string;
  dayKey: number;
  title: string;
  totalSize: number;
  data: MediaItem[];
};

/** Groups items by local calendar day, newest/oldest section first per `sortMode`. Items without a `downloadedAt` (pre-existing items from before that field existed) land in one "Unknown date" section at the end. */
function groupByDate(items: MediaItem[], sortMode: "date-desc" | "date-asc"): DateSection[] {
  const groups = new Map<number, MediaItem[]>();
  const UNKNOWN = -1;
  for (const item of items) {
    const key = item.downloadedAt != null ? dayStart(item.downloadedAt) : UNKNOWN;
    if (!groups.has(key)) groups.set(key, []);
    groups.get(key)!.push(item);
  }
  const sections: DateSection[] = Array.from(groups.entries()).map(([dayKey, data]) => ({
    key: String(dayKey),
    dayKey,
    title: dayKey === UNKNOWN ? "Unknown date" : dateSectionLabel(dayKey),
    totalSize: data.reduce((sum, i) => sum + (i.fileSize ?? 0), 0),
    data: [...data].sort((a, b) => (b.downloadedAt ?? 0) - (a.downloadedAt ?? 0)),
  }));
  sections.sort((a, b) => {
    if (a.dayKey === UNKNOWN) return 1;
    if (b.dayKey === UNKNOWN) return -1;
    return sortMode === "date-desc" ? b.dayKey - a.dayKey : a.dayKey - b.dayKey;
  });
  return sections;
}

function sortFlat(items: MediaItem[], sortMode: SortMode): MediaItem[] {
  const sorted = [...items];
  switch (sortMode) {
    case "name-asc":
      return sorted.sort((a, b) => a.title.localeCompare(b.title));
    case "name-desc":
      return sorted.sort((a, b) => b.title.localeCompare(a.title));
    case "size-desc":
      return sorted.sort((a, b) => (b.fileSize ?? 0) - (a.fileSize ?? 0));
    case "size-asc":
      return sorted.sort((a, b) => (a.fileSize ?? 0) - (b.fileSize ?? 0));
    default:
      return sorted;
  }
}

export default function DownloadsScreen() {
  const [url, setUrl] = useState("");
  const [loadingFormats, setLoadingFormats] = useState(false);
  const [mediaData, setMediaData] = useState<VideoMetadata | null>(null);
  const [showBottomSheet, setShowBottomSheet] = useState(false);
  const [playlistTarget, setPlaylistTarget] = useState<MediaItem | null>(null);
  const [typeFilter, setTypeFilter] = useState<"all" | "video" | "audio">(
    "all",
  );

  // Playlist bulk-download state
  const [playlistData, setPlaylistData] = useState<PlaylistData | null>(null);
  const [showPlaylistSheet, setShowPlaylistSheet] = useState(false);
  const [selectedVideoIds, setSelectedVideoIds] = useState<Set<string>>(
    new Set(),
  );
  const [bulkFormat, setBulkFormat] = useState<"video" | "audio">("video");
  const [bulkQueuing, setBulkQueuing] = useState(false);

  const [sortMode, setSortMode] = useState<SortMode>("date-desc");
  const [showSortSheet, setShowSortSheet] = useState(false);
  const [viewMode, setViewMode] = useViewMode("@downloads_view_mode");
  const miniPlayerInset = useMiniPlayerInset();
  const [searchOpen, setSearchOpen] = useState(false);
  const [searchQuery, setSearchQuery] = useState("");
  // useState (not useRef) so this Animated.Value is created once but never
  // read via `.current` — the react-hooks/refs lint rule (part of the React
  // Compiler's stricter checks) flags any ref read during render, which the
  // Animated API's style-prop pattern below otherwise requires.
  const [searchWidth] = useState(() => new Animated.Value(0));
  const searchInputRef = useRef<TextInput>(null);

  const { searchAndDownload, downloads, pendingDownloads, playMedia, deleteMedia } =
    useMedia();
  const { refreshServiceStatus } = useServiceStatus();

  const toggleSearch = () => {
    const opening = !searchOpen;
    setSearchOpen(opening);
    if (!opening) setSearchQuery("");
    Animated.timing(searchWidth, {
      toValue: opening ? 1 : 0,
      duration: 220,
      easing: Easing.out(Easing.cubic),
      useNativeDriver: false, // animating a layout property (width/flex), not transform/opacity
    }).start();
    // `autoFocus` only fires on mount, and this TextInput stays mounted the
    // whole time (just animated between height 0 and 44) — so it never
    // fires again on subsequent opens. Focus explicitly instead, after the
    // expand animation has had a moment to give it real layout to focus into.
    if (opening) setTimeout(() => searchInputRef.current?.focus(), 250);
    else searchInputRef.current?.blur();
  };

  const shareFile = async (item: MediaItem) => {
    try {
      const available = await Sharing.isAvailableAsync();
      if (!available) {
        Alert.alert("Not available", "Sharing isn't available on this device.");
        return;
      }
      await Sharing.shareAsync(resolveMediaUri(item.uri));
    } catch (e: any) {
      Alert.alert("Couldn't share file", e?.message || "Unknown error");
    }
  };

  const fetchFormats = async () => {
    if (!url.trim())
      return Alert.alert("Error", "Please enter a valid YouTube URL");

    setLoadingFormats(true);
    try {
      const res = await authFetch(`${API_BASE_URL}/info`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ url: url.trim() }),
      });

      const rawText = await res.text();

      if (!res.ok) {
        console.error(`[API Error ${res.status}]:`, rawText);
        throw new Error(`Server returned status ${res.status}`);
      }

      const data = JSON.parse(rawText);

      if (data.type === "video") {
        setMediaData(data.video);
        setShowBottomSheet(true);
      } else if (data.type === "playlist") {
        setPlaylistData(data);
        setSelectedVideoIds(
          new Set(data.videos.map((v: PlaylistVideo) => v.id)),
        );
        setShowPlaylistSheet(true);
      }
    } catch (err: any) {
      refreshServiceStatus();
      Alert.alert("API Error", err.message || "Failed to fetch formats");
    } finally {
      setLoadingFormats(false);
    }
  };

  const handleSelectFormat = (formatId: string) => {
    setShowBottomSheet(false);
    if (mediaData) {
      searchAndDownload(url, formatId, {
        title: mediaData.title,
        thumbnail: mediaData.thumbnail,
        channel: mediaData.uploader,
        webpageUrl: mediaData.webpageUrl,
        durationSeconds: mediaData.durationSeconds,
      });
    }
    setUrl("");
  };

  const toggleVideoSelected = (id: string) => {
    setSelectedVideoIds((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  const handleBulkDownload = async () => {
    if (!playlistData || selectedVideoIds.size === 0) return;
    const selected = playlistData.videos.filter((v) =>
      selectedVideoIds.has(v.id),
    );
    const formatId = bulkFormat === "video" ? "video-720p" : "audio-192";

    setBulkQueuing(true);
    setShowPlaylistSheet(false);
    // Stagger requests slightly so the local server/yt-dlp isn't hit with a
    // burst of N simultaneous downloads all at once.
    for (const video of selected) {
      searchAndDownload(video.webpageUrl, formatId, {
        title: video.title,
        thumbnail: video.thumbnail,
        webpageUrl: video.webpageUrl,
        durationSeconds: video.durationSeconds,
      });
      await new Promise((resolve) => setTimeout(resolve, 300));
    }
    setBulkQueuing(false);
    setUrl("");
  };

  const sections = mediaData
    ? [
        { title: "Video Options", data: mediaData.videoOptions },
        { title: "Audio Options", data: mediaData.audioOptions },
      ]
    : [];

  const filteredDownloads = useMemo(() => {
    let list = downloads;
    if (typeFilter !== "all") list = list.filter((d) => d.type === typeFilter);
    const q = searchQuery.trim().toLowerCase();
    if (q) {
      list = list.filter(
        (d) =>
          d.title.toLowerCase().includes(q) ||
          (d.channel && d.channel.toLowerCase().includes(q)),
      );
    }
    return list;
  }, [downloads, typeFilter, searchQuery]);

  const filteredPending = useMemo(() => {
    if (typeFilter === "all") return pendingDownloads;
    return pendingDownloads.filter((p) => p.type === typeFilter);
  }, [pendingDownloads, typeFilter]);

  const totalSize = useMemo(
    () => filteredDownloads.reduce((sum, d) => sum + (d.fileSize ?? 0), 0),
    [filteredDownloads],
  );

  const isDateSort = sortMode === "date-desc" || sortMode === "date-asc";

  // Date-grouped sections (used for list view when sorting by date) vs a
  // flat sorted array (used for name/size sorts, and always for grid view —
  // date dividers don't read well in a thumbnail grid).
  const dateSections = useMemo(
    () => (isDateSort ? groupByDate(filteredDownloads, sortMode) : []),
    [filteredDownloads, sortMode, isDateSort],
  );
  const flatSorted = useMemo(
    () => sortFlat(filteredDownloads, sortMode),
    [filteredDownloads, sortMode],
  );

  const openInYouTube = (item: MediaItem) => {
    if (item.webpageUrl) Linking.openURL(item.webpageUrl);
  };

  const renderMediaRow = (item: MediaItem) => (
    <View style={styles.mediaRow}>
      <TouchableOpacity
        style={styles.mediaInfo}
        onPress={() => playMedia(item, filteredDownloads)}
      >
        {item.thumbnail ? (
          <Image source={{ uri: item.thumbnail }} style={styles.rowThumb} />
        ) : (
          <View style={[styles.rowThumb, styles.rowThumbFallback]}>
            <Ionicons
              name={item.type === "video" ? "film-outline" : "musical-notes-outline"}
              size={22}
              color="#1DB954"
            />
          </View>
        )}
        <View style={{ marginLeft: 10, flex: 1 }}>
          <Text style={styles.mediaTitle} numberOfLines={1}>
            {item.title}
          </Text>
          <Text style={styles.mediaSubtitle} numberOfLines={1}>
            {[
              item.channel,
              formatDuration(item.durationSeconds),
              item.fileSize ? formatBytes(item.fileSize) : null,
            ]
              .filter(Boolean)
              .join(" • ")}
          </Text>
          {item.downloadedAt != null && (
            <Text style={styles.mediaTimestamp} numberOfLines={1}>
              Downloaded {formatDownloadedAt(item.downloadedAt)}
            </Text>
          )}
        </View>
      </TouchableOpacity>

      <TouchableOpacity style={styles.rowAction} onPress={() => setPlaylistTarget(item)}>
        <Ionicons name="add-circle-outline" size={19} color="#888" />
      </TouchableOpacity>
      <TouchableOpacity style={styles.rowAction} onPress={() => shareFile(item)}>
        <Ionicons name="share-outline" size={19} color="#888" />
      </TouchableOpacity>
      {item.webpageUrl && (
        <TouchableOpacity style={styles.rowAction} onPress={() => openInYouTube(item)}>
          <Ionicons name="logo-youtube" size={19} color="#FF0000" />
        </TouchableOpacity>
      )}
      <TouchableOpacity style={styles.rowAction} onPress={() => deleteMedia(item.id)}>
        <Ionicons name="trash-outline" size={19} color="#FF5252" />
      </TouchableOpacity>
    </View>
  );

  const renderGridCard = (item: MediaItem) => (
    <TouchableOpacity
      style={styles.gridCard}
      onPress={() => playMedia(item, filteredDownloads)}
      onLongPress={() => setPlaylistTarget(item)}
    >
      {item.thumbnail ? (
        <Image source={{ uri: item.thumbnail }} style={styles.gridThumb} />
      ) : (
        <View style={[styles.gridThumb, styles.rowThumbFallback]}>
          <Ionicons
            name={item.type === "video" ? "film-outline" : "musical-notes-outline"}
            size={28}
            color="#1DB954"
          />
        </View>
      )}
      <Text style={styles.gridTitle} numberOfLines={2}>
        {item.title}
      </Text>
      <Text style={styles.gridSub} numberOfLines={1}>
        {[formatDuration(item.durationSeconds), item.fileSize ? formatBytes(item.fileSize) : null]
          .filter(Boolean)
          .join(" • ")}
      </Text>
    </TouchableOpacity>
  );

  const listEmpty = (
    <Text style={styles.emptyText}>
      {searchQuery ? "No matches." : "No downloads yet."}
    </Text>
  );

  return (
    <View style={styles.container}>
      <ServiceStatusBanner />
      {/* Downloader Input Section */}
      <View style={styles.inputCard}>
        <TextInput
          style={styles.input}
          placeholder="Paste YouTube Video / Playlist URL..."
          placeholderTextColor="#666"
          value={url}
          onChangeText={setUrl}
          autoCapitalize="none"
          autoCorrect={false}
          keyboardType="url"
          clearButtonMode="while-editing"
        />
        <TouchableOpacity
          style={styles.downloadBtn}
          onPress={fetchFormats}
          disabled={loadingFormats || bulkQueuing}
        >
          {loadingFormats || bulkQueuing ? (
            <ActivityIndicator color="#FFF" size="small" />
          ) : (
            <>
              <Ionicons name="search" size={18} color="#FFF" />
              <Text style={styles.btnText}>Get Formats</Text>
            </>
          )}
        </TouchableOpacity>
        <TouchableOpacity
          style={styles.browseBtn}
          onPress={() => router.push("/browse")}
        >
          <Ionicons name="logo-youtube" size={16} color="#888" />
          <Text style={styles.browseBtnText}>
            Or browse YouTube to find something
          </Text>
        </TouchableOpacity>
      </View>

      <View style={styles.sectionHeaderRow}>
        <Text style={styles.sectionHeader}>Downloaded Media</Text>
        {filteredDownloads.length > 0 && (
          <Text style={styles.totalSizeText}>
            {filteredDownloads.length} item{filteredDownloads.length === 1 ? "" : "s"} ·{" "}
            {formatBytes(totalSize)}
          </Text>
        )}
      </View>

      {/* Video / Audio filter + sort/view/search toolbar */}
      <View style={styles.toolbarRow}>
        <View style={styles.filterRow}>
          {(["all", "video", "audio"] as const).map((f) => (
            <TouchableOpacity
              key={f}
              style={[
                styles.filterChip,
                typeFilter === f && styles.filterChipActive,
              ]}
              onPress={() => setTypeFilter(f)}
            >
              <Text style={styles.filterChipText}>
                {f === "all" ? "All" : f === "video" ? "Video" : "Audio"}
              </Text>
            </TouchableOpacity>
          ))}
        </View>
        <View style={styles.toolbarIcons}>
          <TouchableOpacity onPress={toggleSearch} style={styles.toolbarIconBtn}>
            <Ionicons name={searchOpen ? "close" : "search-outline"} size={19} color="#FFF" />
          </TouchableOpacity>
          <TouchableOpacity onPress={() => setShowSortSheet(true)} style={styles.toolbarIconBtn}>
            <Ionicons name="funnel-outline" size={18} color="#FFF" />
          </TouchableOpacity>
          <TouchableOpacity
            onPress={() => setViewMode(viewMode === "list" ? "grid" : "list")}
            style={styles.toolbarIconBtn}
          >
            <Ionicons name={viewMode === "list" ? "grid-outline" : "list-outline"} size={19} color="#FFF" />
          </TouchableOpacity>
        </View>
      </View>

      <Animated.View
        style={{
          height: searchWidth.interpolate({ inputRange: [0, 1], outputRange: [0, 44] }),
          opacity: searchWidth,
          overflow: "hidden",
        }}
      >
        <TextInput
          ref={searchInputRef}
          style={styles.searchInput}
          placeholder="Search title or channel..."
          placeholderTextColor="#666"
          value={searchQuery}
          onChangeText={setSearchQuery}
        />
      </Animated.View>

      {filteredPending.length > 0 && (
        <View>
          {filteredPending.map((item) => (
            <View key={item.jobId} style={[styles.mediaRow, styles.mediaRowPending]}>
              {item.thumbnail ? (
                <Image
                  source={{ uri: item.thumbnail }}
                  style={[styles.rowThumb, styles.rowThumbDim]}
                />
              ) : (
                <View style={[styles.rowThumb, styles.rowThumbFallback]}>
                  <Ionicons
                    name={item.type === "video" ? "film-outline" : "musical-notes-outline"}
                    size={22}
                    color="#555"
                  />
                </View>
              )}
              <View style={{ marginLeft: 10, flex: 1 }}>
                <Text style={styles.mediaTitle} numberOfLines={1}>
                  {item.title}
                </Text>
                <Text style={styles.mediaSubtitlePending}>
                  {item.status === "processing" ? "Downloading…" : "Queued…"}
                </Text>
              </View>
              <ActivityIndicator color="#1DB954" size="small" />
            </View>
          ))}
        </View>
      )}

      {viewMode === "grid" ? (
        <FlatList
          // FlatList doesn't support changing numColumns on an
          // already-mounted instance ("Changing numColumns on the fly is
          // not supported" — confirmed live) — the key forces a fresh
          // instance whenever list/grid toggles, instead of trying to
          // update the existing one (or the flat-sort FlatList below, same
          // component type at the same tree position) in place.
          key="grid"
          data={flatSorted}
          keyExtractor={(item) => item.id}
          numColumns={2}
          columnWrapperStyle={styles.gridRow}
          renderItem={({ item }) => renderGridCard(item)}
          ListEmptyComponent={listEmpty}
          contentContainerStyle={{ paddingBottom: miniPlayerInset }}
        />
      ) : isDateSort ? (
        <SectionList
          key="date-sections"
          sections={dateSections}
          keyExtractor={(item) => item.id}
          renderSectionHeader={({ section }) => (
            <View style={styles.dateSectionHeader}>
              <Text style={styles.dateSectionTitle}>{section.title}</Text>
              <Text style={styles.dateSectionSize}>{formatBytes(section.totalSize)}</Text>
            </View>
          )}
          renderItem={({ item }) => renderMediaRow(item)}
          ListEmptyComponent={listEmpty}
          contentContainerStyle={{ paddingBottom: miniPlayerInset }}
        />
      ) : (
        <FlatList
          key="list"
          data={flatSorted}
          keyExtractor={(item) => item.id}
          renderItem={({ item }) => renderMediaRow(item)}
          ListEmptyComponent={listEmpty}
          contentContainerStyle={{ paddingBottom: miniPlayerInset }}
        />
      )}

      {/* Sort bottom sheet */}
      <Modal
        visible={showSortSheet}
        transparent
        animationType="slide"
        onRequestClose={() => setShowSortSheet(false)}
      >
        <TouchableOpacity
          style={styles.modalOverlay}
          activeOpacity={1}
          onPress={() => setShowSortSheet(false)}
        >
          <View style={styles.bottomSheet} onStartShouldSetResponder={() => true}>
            <View style={styles.sheetHeader}>
              <Text style={styles.sheetTitle}>Sort by</Text>
              <TouchableOpacity onPress={() => setShowSortSheet(false)}>
                <Ionicons name="close" size={24} color="#FFF" />
              </TouchableOpacity>
            </View>
            {SORT_OPTIONS.map((opt) => (
              <TouchableOpacity
                key={opt.mode}
                style={styles.sortOptionRow}
                onPress={() => {
                  setSortMode(opt.mode);
                  setShowSortSheet(false);
                }}
              >
                <Ionicons name={opt.icon} size={18} color="#1DB954" />
                <Text style={styles.sortOptionText}>{opt.label}</Text>
                {sortMode === opt.mode && (
                  <Ionicons name="checkmark" size={18} color="#1DB954" style={{ marginLeft: "auto" }} />
                )}
              </TouchableOpacity>
            ))}
          </View>
        </TouchableOpacity>
      </Modal>

      <PlaylistPickerModal
        visible={!!playlistTarget}
        item={playlistTarget}
        onClose={() => setPlaylistTarget(null)}
      />

      {/* Format Selection Bottom Sheet Modal (single video) */}
      <Modal
        visible={showBottomSheet}
        transparent
        animationType="slide"
        onRequestClose={() => setShowBottomSheet(false)}
      >
        <TouchableOpacity
          style={styles.modalOverlay}
          activeOpacity={1}
          onPress={() => setShowBottomSheet(false)}
        >
          <View
            style={styles.bottomSheet}
            onStartShouldSetResponder={() => true}
          >
            <View style={styles.sheetHeader}>
              <Text style={styles.sheetTitle}>Select Quality & Format</Text>
              <TouchableOpacity onPress={() => setShowBottomSheet(false)}>
                <Ionicons name="close" size={24} color="#FFF" />
              </TouchableOpacity>
            </View>

            {mediaData && (
              <View style={styles.previewCard}>
                <Image
                  source={{ uri: mediaData.thumbnail }}
                  style={styles.thumbnail}
                />
                <View style={{ flex: 1, marginLeft: 12 }}>
                  <Text style={styles.previewTitle} numberOfLines={2}>
                    {mediaData.title}
                  </Text>
                  <Text style={styles.previewSub}>
                    {mediaData.uploader} •{" "}
                    {Math.floor(mediaData.durationSeconds / 60)}m{" "}
                    {mediaData.durationSeconds % 60}s
                  </Text>
                </View>
              </View>
            )}

            <SectionList
              sections={sections}
              keyExtractor={(item) => item.formatId}
              renderSectionHeader={({ section: { title } }) => (
                <Text style={styles.categoryHeader}>{title}</Text>
              )}
              renderItem={({ item }) => (
                <TouchableOpacity
                  style={[styles.formatItem, item.disabled && styles.formatItemDisabled]}
                  onPress={() => !item.disabled && handleSelectFormat(item.formatId)}
                  disabled={item.disabled}
                >
                  <Ionicons
                    name={
                      item.type === "video"
                        ? "videocam-outline"
                        : "musical-note-outline"
                    }
                    size={20}
                    color={item.disabled ? "#666" : "#1DB954"}
                  />
                  <View style={{ flex: 1, marginLeft: 10 }}>
                    <Text style={[styles.formatText, item.disabled && styles.formatTextDisabled]}>
                      {item.label}
                    </Text>
                    <Text style={styles.formatSub}>
                      {item.ext.toUpperCase()}{" "}
                      {item.approxFileSize ? `• ${item.approxFileSize}` : ""}
                    </Text>
                    {item.disabled && item.disabledReason && (
                      <Text style={styles.formatDisabledReason}>{item.disabledReason}</Text>
                    )}
                  </View>
                  {!item.disabled && (
                    <Ionicons name="cloud-download-outline" size={20} color="#1DB954" />
                  )}
                </TouchableOpacity>
              )}
            />
          </View>
        </TouchableOpacity>
      </Modal>

      {/* Playlist Multi-Select Bottom Sheet Modal */}
      <Modal
        visible={showPlaylistSheet}
        transparent
        animationType="slide"
        onRequestClose={() => setShowPlaylistSheet(false)}
      >
        <TouchableOpacity
          style={styles.modalOverlay}
          activeOpacity={1}
          onPress={() => setShowPlaylistSheet(false)}
        >
          <View
            style={styles.bottomSheet}
            onStartShouldSetResponder={() => true}
          >
            <View style={styles.sheetHeader}>
              <Text style={styles.sheetTitle} numberOfLines={1}>
                {playlistData?.playlistTitle || "Playlist"} ·{" "}
                {playlistData?.videoCount} videos
              </Text>
              <TouchableOpacity onPress={() => setShowPlaylistSheet(false)}>
                <Ionicons name="close" size={24} color="#FFF" />
              </TouchableOpacity>
            </View>

            <View style={styles.bulkFormatRow}>
              <TouchableOpacity
                style={[
                  styles.bulkFormatChip,
                  bulkFormat === "video" && styles.filterChipActive,
                ]}
                onPress={() => setBulkFormat("video")}
              >
                <Text style={styles.filterChipText}>Video 720p</Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={[
                  styles.bulkFormatChip,
                  bulkFormat === "audio" && styles.filterChipActive,
                ]}
                onPress={() => setBulkFormat("audio")}
              >
                <Text style={styles.filterChipText}>Audio 192kbps</Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={styles.bulkDownloadBtn}
                onPress={handleBulkDownload}
                disabled={selectedVideoIds.size === 0}
              >
                <Text style={styles.btnText}>
                  Download {selectedVideoIds.size}
                </Text>
              </TouchableOpacity>
            </View>

            <FlatList
              data={playlistData?.videos || []}
              keyExtractor={(v) => v.id}
              renderItem={({ item }) => {
                const selected = selectedVideoIds.has(item.id);
                return (
                  <TouchableOpacity
                    style={styles.playlistRow}
                    onPress={() => toggleVideoSelected(item.id)}
                  >
                    <Ionicons
                      name={selected ? "checkbox" : "square-outline"}
                      size={20}
                      color={selected ? "#1DB954" : "#888"}
                    />
                    {item.thumbnail ? (
                      <Image
                        source={{ uri: item.thumbnail }}
                        style={styles.playlistThumb}
                      />
                    ) : (
                      <View
                        style={[styles.playlistThumb, styles.rowThumbFallback]}
                      />
                    )}
                    <Text style={styles.playlistRowTitle} numberOfLines={2}>
                      {item.title}
                    </Text>
                  </TouchableOpacity>
                );
              }}
            />
          </View>
        </TouchableOpacity>
      </Modal>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, backgroundColor: "#121212", padding: 16 },
  inputCard: {
    backgroundColor: "#1E1E1E",
    padding: 12,
    borderRadius: 8,
    marginBottom: 16,
  },
  input: {
    backgroundColor: "#2A2A2A",
    color: "#FFF",
    padding: 12,
    borderRadius: 6,
    marginBottom: 10,
  },
  downloadBtn: {
    backgroundColor: "#1DB954",
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
    padding: 10,
    borderRadius: 6,
  },
  btnText: { color: "#FFF", fontWeight: "bold", marginLeft: 4 },
  browseBtn: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
    marginTop: 10,
  },
  browseBtnText: { color: "#888", fontSize: 12, marginLeft: 6 },
  sectionHeaderRow: {
    flexDirection: "row",
    alignItems: "baseline",
    justifyContent: "space-between",
    marginBottom: 10,
  },
  sectionHeader: {
    color: "#FFF",
    fontSize: 18,
    fontWeight: "bold",
  },
  totalSizeText: { color: "#888", fontSize: 12 },
  toolbarRow: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "space-between",
    marginBottom: 8,
  },
  toolbarIcons: { flexDirection: "row" },
  toolbarIconBtn: { marginLeft: 14 },
  searchInput: {
    backgroundColor: "#1E1E1E",
    color: "#FFF",
    borderRadius: 8,
    paddingHorizontal: 12,
    height: 40,
    marginBottom: 4,
  },
  dateSectionHeader: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "baseline",
    marginTop: 8,
    marginBottom: 6,
  },
  dateSectionTitle: { color: "#1DB954", fontSize: 13, fontWeight: "bold" },
  dateSectionSize: { color: "#666", fontSize: 11 },
  sortOptionRow: {
    flexDirection: "row",
    alignItems: "center",
    paddingVertical: 12,
    borderBottomWidth: 1,
    borderBottomColor: "#2A2A2A",
  },
  sortOptionText: { color: "#FFF", fontSize: 14, marginLeft: 10 },
  gridRow: { justifyContent: "space-between" },
  gridCard: {
    width: "48%",
    backgroundColor: "#1E1E1E",
    borderRadius: 8,
    padding: 8,
    marginBottom: 12,
  },
  gridThumb: {
    width: "100%",
    aspectRatio: 16 / 9,
    borderRadius: 6,
    backgroundColor: "#2A2A2A",
  },
  gridTitle: { color: "#FFF", fontSize: 12, fontWeight: "600", marginTop: 6 },
  gridSub: { color: "#888", fontSize: 10, marginTop: 2 },
  emptyText: { color: "#666", fontSize: 13, textAlign: "center", marginTop: 40 },
  filterRow: { flexDirection: "row" },
  filterChip: {
    backgroundColor: "#1E1E1E",
    paddingHorizontal: 16,
    paddingVertical: 7,
    borderRadius: 16,
    marginRight: 8,
  },
  filterChipActive: { backgroundColor: "#1DB954" },
  filterChipText: { color: "#FFF", fontSize: 12, fontWeight: "600" },
  mediaRow: {
    flexDirection: "row",
    alignItems: "center",
    backgroundColor: "#1E1E1E",
    padding: 10,
    borderRadius: 6,
    marginBottom: 8,
  },
  mediaRowPending: { opacity: 0.85 },
  mediaInfo: { flexDirection: "row", alignItems: "center", flex: 1 },
  rowThumb: {
    width: 52,
    height: 52,
    borderRadius: 6,
    backgroundColor: "#2A2A2A",
  },
  rowThumbDim: { opacity: 0.5 },
  rowThumbFallback: { alignItems: "center", justifyContent: "center" },
  rowAction: { marginLeft: 12 },
  mediaTitle: { color: "#FFF", fontSize: 14, fontWeight: "600" },
  mediaSubtitle: { color: "#888", fontSize: 12, marginTop: 2 },
  mediaSubtitlePending: { color: "#1DB954", fontSize: 12, marginTop: 2 },
  mediaTimestamp: { color: "#666", fontSize: 11, marginTop: 2 },
  mediaTags: { color: "#1DB954", fontSize: 11, marginTop: 2 },

  modalOverlay: {
    flex: 1,
    backgroundColor: "rgba(0,0,0,0.6)",
    justifyContent: "flex-end",
  },
  bottomSheet: {
    backgroundColor: "#1E1E1E",
    borderTopLeftRadius: 16,
    borderTopRightRadius: 16,
    padding: 16,
    maxHeight: "80%",
  },
  sheetHeader: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "center",
    marginBottom: 12,
  },
  sheetTitle: {
    color: "#FFF",
    fontSize: 16,
    fontWeight: "bold",
    flex: 1,
    marginRight: 12,
  },

  previewCard: {
    flexDirection: "row",
    backgroundColor: "#2A2A2A",
    padding: 10,
    borderRadius: 8,
    marginBottom: 16,
  },
  thumbnail: { width: 80, height: 45, borderRadius: 4 },
  previewTitle: { color: "#FFF", fontSize: 13, fontWeight: "bold" },
  previewSub: { color: "#AAA", fontSize: 11, marginTop: 4 },

  categoryHeader: {
    color: "#1DB954",
    fontSize: 14,
    fontWeight: "bold",
    marginTop: 12,
    marginBottom: 6,
  },
  formatItem: {
    flexDirection: "row",
    alignItems: "center",
    backgroundColor: "#2A2A2A",
    padding: 12,
    borderRadius: 8,
    marginBottom: 8,
  },
  formatText: { color: "#FFF", fontSize: 14, fontWeight: "600" },
  formatSub: { color: "#888", fontSize: 12, marginTop: 2 },
  formatItemDisabled: { opacity: 0.5 },
  formatTextDisabled: { color: "#999" },
  formatDisabledReason: { color: "#FF8A65", fontSize: 11, marginTop: 2 },

  bulkFormatRow: {
    flexDirection: "row",
    alignItems: "center",
    marginBottom: 12,
  },
  bulkFormatChip: {
    backgroundColor: "#2A2A2A",
    paddingHorizontal: 12,
    paddingVertical: 8,
    borderRadius: 16,
    marginRight: 8,
  },
  bulkDownloadBtn: {
    backgroundColor: "#1DB954",
    paddingHorizontal: 14,
    paddingVertical: 8,
    borderRadius: 16,
    marginLeft: "auto",
  },
  playlistRow: {
    flexDirection: "row",
    alignItems: "center",
    paddingVertical: 8,
    borderBottomWidth: 1,
    borderBottomColor: "#2A2A2A",
  },
  playlistThumb: { width: 60, height: 34, borderRadius: 4, marginLeft: 10 },
  playlistRowTitle: { color: "#FFF", fontSize: 13, marginLeft: 10, flex: 1 },
});
