import React, { useEffect, useMemo, useRef, useState } from "react";
import {
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  ActivityIndicator,
  Alert,
  Image,
  SectionList,
  Modal,
} from "react-native";
import { WebView, type WebViewNavigation } from "react-native-webview";
import { SafeAreaView } from "react-native-safe-area-context";
import { router } from "expo-router";
import { Ionicons } from "@expo/vector-icons";
import { useMedia } from "../context/MediaContext";
import { API_BASE_URL } from "../config";
import { authFetch } from "../lib/apiFetch";
import type { VideoMetadata } from "../types/download";
import { useMiniPlayerInset } from "../hooks/useMiniPlayerInset";
import { useServiceStatus } from "../context/ServiceStatusContext";
import ServiceStatusBanner from "../components/ServiceStatusBanner";

const YOUTUBE_HOME = "https://m.youtube.com";

/** Pulls the video id out of a YouTube watch/short/youtu.be URL, or null if this isn't a single-video page (e.g. the home feed, search results, a channel page). */
function extractVideoId(url: string): string | null {
  try {
    const u = new URL(url);
    const host = u.hostname.replace(/^m\./, "").replace(/^www\./, "");
    if (host === "youtube.com" && u.pathname === "/watch") {
      return u.searchParams.get("v");
    }
    if (host === "youtube.com" && u.pathname.startsWith("/shorts/")) {
      return u.pathname.split("/")[2] || null;
    }
    if (host === "youtu.be") {
      return u.pathname.slice(1) || null;
    }
  } catch {
    // not a parseable URL
  }
  return null;
}

export default function BrowseScreen() {
  const webviewRef = useRef<WebView>(null);
  const {
    searchAndDownload,
    downloads,
    pendingDownloads,
    activeTrack,
    isPlaying,
    videoPlaying,
    requestPause,
    requestResume,
  } = useMedia();
  const miniPlayerInset = useMiniPlayerInset();
  const { refreshServiceStatus } = useServiceStatus();

  const [currentUrl, setCurrentUrl] = useState(YOUTUBE_HOME);
  const [canGoBack, setCanGoBack] = useState(false);
  const [canGoForward, setCanGoForward] = useState(false);

  const [loadingFormats, setLoadingFormats] = useState(false);
  const [mediaData, setMediaData] = useState<VideoMetadata | null>(null);
  const [showSheet, setShowSheet] = useState(false);

  const videoId = extractVideoId(currentUrl);

  // Pause whatever's playing while this screen is open, and resume it (only
  // if it was actually this screen that paused it) once the user navigates
  // back. Captured once at mount — later changes to isPlaying/videoPlaying
  // while browsing (e.g. the user pausing manually) shouldn't be undone on
  // the way out.
  const wasPlayingOnMountRef = useRef(
    activeTrack?.type === "video" ? videoPlaying : isPlaying,
  );
  useEffect(() => {
    if (!wasPlayingOnMountRef.current) return;
    requestPause();
    return () => {
      requestResume();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Matched by video id (not raw URL) against both in-flight jobs and
  // finished downloads, since the URL YouTube reports here can carry extra
  // query params that a stored webpageUrl won't. Drives the FAB below so it
  // reflects reality instead of staying "Download this video" forever.
  const downloadState = useMemo(():
    | { kind: "none" }
    | { kind: "pending"; status: "queued" | "processing" }
    | { kind: "done" } => {
    if (!videoId) return { kind: "none" };
    const pending = pendingDownloads.find(
      (p) => p.webpageUrl && extractVideoId(p.webpageUrl) === videoId,
    );
    if (pending) return { kind: "pending", status: pending.status };
    const done = downloads.some(
      (d) => d.webpageUrl && extractVideoId(d.webpageUrl) === videoId,
    );
    if (done) return { kind: "done" };
    return { kind: "none" };
  }, [videoId, pendingDownloads, downloads]);

  const handleNavStateChange = (nav: WebViewNavigation) => {
    setCurrentUrl(nav.url);
    setCanGoBack(nav.canGoBack);
    setCanGoForward(nav.canGoForward);
  };

  const fetchFormats = async () => {
    if (!videoId) return;
    setLoadingFormats(true);
    try {
      const res = await authFetch(`${API_BASE_URL}/info`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ url: currentUrl }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "Failed to fetch formats");
      if (data.type !== "video") {
        Alert.alert(
          "Not a single video",
          "That link looks like a playlist — open one specific video to download it.",
        );
        return;
      }
      setMediaData(data.video);
      setShowSheet(true);
    } catch (err: any) {
      refreshServiceStatus();
      Alert.alert("Error", err.message || "Failed to fetch formats");
    } finally {
      setLoadingFormats(false);
    }
  };

  const handleSelectFormat = (formatId: string) => {
    setShowSheet(false);
    if (mediaData) {
      // No confirmation alert needed here — the FAB below flips to
      // "Downloading…" (and later "Downloaded") the moment this lands in
      // context state, which is the actual signal the user is watching for.
      searchAndDownload(currentUrl, formatId, {
        title: mediaData.title,
        thumbnail: mediaData.thumbnail,
        channel: mediaData.uploader,
        webpageUrl: mediaData.webpageUrl,
        durationSeconds: mediaData.durationSeconds,
      });
    }
  };

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

  return (
    <SafeAreaView style={styles.container} edges={["top", "left", "right"]}>
      <View style={styles.header}>
        <TouchableOpacity onPress={() => router.back()} hitSlop={10}>
          <Ionicons name="chevron-back" size={26} color="#FFF" />
        </TouchableOpacity>
        <View style={styles.navControls}>
          <TouchableOpacity
            onPress={() => webviewRef.current?.goBack()}
            disabled={!canGoBack}
            hitSlop={10}
          >
            <Ionicons
              name="arrow-back"
              size={20}
              color={canGoBack ? "#FFF" : "#444"}
            />
          </TouchableOpacity>
          <TouchableOpacity
            onPress={() => webviewRef.current?.goForward()}
            disabled={!canGoForward}
            style={{ marginLeft: 20 }}
            hitSlop={10}
          >
            <Ionicons
              name="arrow-forward"
              size={20}
              color={canGoForward ? "#FFF" : "#444"}
            />
          </TouchableOpacity>
          <TouchableOpacity
            onPress={() => webviewRef.current?.reload()}
            style={{ marginLeft: 20 }}
            hitSlop={10}
          >
            <Ionicons name="refresh" size={20} color="#FFF" />
          </TouchableOpacity>
        </View>
        <View style={{ width: 26 }} />
      </View>

      <View style={{ marginHorizontal: 16 }}>
        <ServiceStatusBanner />
      </View>

      <WebView
        ref={webviewRef}
        source={{ uri: YOUTUBE_HOME }}
        onNavigationStateChange={handleNavStateChange}
        style={styles.webview}
        // An iPad Safari UA + allowsFullscreenVideo={false} is what actually
        // keeps YouTube's video playback inline under our header/FAB — a
        // mobile Chrome UA plus allowsInlineMediaPlayback (the "standard"
        // fix) was NOT enough, iOS still handed playback to a native
        // fullscreen AVPlayerViewController regardless.
        userAgent="Mozilla/5.0 (iPad; CPU OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1"
        allowsInlineMediaPlayback
        mediaPlaybackRequiresUserAction
        allowsFullscreenVideo={false}
      />

      {videoId && (
        <TouchableOpacity
          style={[
            styles.downloadFab,
            { bottom: 24 + miniPlayerInset },
            downloadState.kind !== "none" && styles.downloadFabDisabled,
          ]}
          onPress={fetchFormats}
          disabled={loadingFormats || downloadState.kind !== "none"}
        >
          {loadingFormats ? (
            <ActivityIndicator color="#FFF" size="small" />
          ) : downloadState.kind === "pending" ? (
            <>
              <ActivityIndicator color="#FFF" size="small" />
              <Text style={styles.downloadFabText}>
                {downloadState.status === "processing"
                  ? "Processing…"
                  : "Downloading…"}
              </Text>
            </>
          ) : downloadState.kind === "done" ? (
            <>
              <Ionicons name="checkmark-circle" size={18} color="#FFF" />
              <Text style={styles.downloadFabText}>Downloaded</Text>
            </>
          ) : (
            <>
              <Ionicons name="cloud-download-outline" size={18} color="#FFF" />
              <Text style={styles.downloadFabText}>Download this video</Text>
            </>
          )}
        </TouchableOpacity>
      )}

      <Modal
        visible={showSheet}
        transparent
        animationType="slide"
        onRequestClose={() => setShowSheet(false)}
      >
        <TouchableOpacity
          style={styles.modalOverlay}
          activeOpacity={1}
          onPress={() => setShowSheet(false)}
        >
          <View
            style={styles.bottomSheet}
            onStartShouldSetResponder={() => true}
          >
            <View style={styles.sheetHeader}>
              <Text style={styles.sheetTitle}>Select Quality & Format</Text>
              <TouchableOpacity onPress={() => setShowSheet(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>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, backgroundColor: "#121212" },
  header: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "space-between",
    paddingHorizontal: 16,
    paddingVertical: 12,
  },
  navControls: { flexDirection: "row", alignItems: "center" },
  webview: { flex: 1, backgroundColor: "#000" },
  downloadFab: {
    position: "absolute",
    bottom: 24,
    alignSelf: "center",
    flexDirection: "row",
    alignItems: "center",
    backgroundColor: "#1DB954",
    paddingHorizontal: 18,
    paddingVertical: 12,
    borderRadius: 24,
    shadowColor: "#000",
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.3,
    shadowRadius: 6,
    elevation: 6,
  },
  downloadFabDisabled: {
    backgroundColor: "#3A3A3A",
  },
  downloadFabText: {
    color: "#FFF",
    fontWeight: "bold",
    marginLeft: 8,
    fontSize: 14,
  },
  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 },
});
