import { Feather } from "@expo/vector-icons";
import { Image } from "expo-image";
import React, { useCallback, useEffect, useState } from "react";
import {
  ActivityIndicator,
  FlatList,
  Modal,
  ScrollView,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { PostizWorkspace } from "@/context/PostizContext";
import { useColors } from "@/hooks/useColors";

export interface LibraryMediaItem {
  id: string;
  path: string;
  workspaceId: string;
  createdAt?: string;
}

interface RawMediaItem {
  id: string;
  path: string;
  createdAt?: string;
}

interface Props {
  visible: boolean;
  workspaces: PostizWorkspace[];
  defaultWorkspaceId?: string;
  maxSelect: number;
  onClose: () => void;
  onSelect: (items: LibraryMediaItem[]) => void;
  onPickFromDevice?: () => void;
}

function resolveUrl(path: string, baseUrl: string): string {
  if (path.startsWith("http://") || path.startsWith("https://")) return path;
  const origin = baseUrl.replace(/\/api\/.*$/, "");
  return `${origin}/${path.replace(/^\//, "")}`;
}

export function MediaLibraryModal({ visible, workspaces, defaultWorkspaceId, maxSelect, onClose, onSelect, onPickFromDevice }: Props) {
  const colors = useColors();
  const insets = useSafeAreaInsets();
  const [activeId, setActiveId] = useState<string>("");
  const [items, setItems] = useState<RawMediaItem[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [selected, setSelected] = useState<Set<string>>(new Set());

  const activeWorkspace = workspaces.find((w) => w.id === activeId) ?? workspaces[0] ?? null;

  useEffect(() => {
    if (visible) {
      const initial = defaultWorkspaceId ?? workspaces[0]?.id ?? "";
      setActiveId(initial);
      setSelected(new Set());
    }
  }, [visible, defaultWorkspaceId, workspaces]);

  const load = useCallback(async () => {
    if (!activeWorkspace) return;
    setLoading(true);
    setError(null);
    const apiBase = activeWorkspace.baseUrl.replace(/\/public\/v1$/, "");
    const url = `${apiBase}/media?page=0&search=`;
    try {
      // eslint-disable-next-line no-undef
      const res = await globalThis.fetch(url, {
        headers: { Authorization: activeWorkspace.apiKey },
      });
      if (!res.ok) {
        if (res.status === 401 || res.status === 403) {
          throw new Error("SESSION_REQUIRED");
        }
        if (res.status === 404) {
          throw new Error("ENDPOINT_NOT_FOUND");
        }
        throw new Error(`HTTP ${res.status} — ${url}`);
      }
      const data = await res.json();
      const list: RawMediaItem[] = Array.isArray(data)
        ? data
        : (data?.media ?? data?.items ?? data?.files ?? []);
      setItems(list);
    } catch (e: unknown) {
      setError(e instanceof Error ? e.message : "Failed to load media");
    } finally {
      setLoading(false);
    }
  }, [activeWorkspace]);

  useEffect(() => {
    if (visible && activeWorkspace) {
      setSelected(new Set());
      load();
    }
  }, [visible, activeWorkspace, load]);

  const toggle = (id: string) => {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(id)) { next.delete(id); }
      else if (next.size < maxSelect) { next.add(id); }
      return next;
    });
  };

  const handleConfirm = () => {
    if (!activeWorkspace) return;
    const chosen = items
      .filter((i) => selected.has(i.id))
      .map((i): LibraryMediaItem => ({ ...i, workspaceId: activeWorkspace.id }));
    onSelect(chosen);
  };

  return (
    <Modal visible={visible} animationType="slide" onRequestClose={onClose}>
      <View style={[styles.root, { backgroundColor: colors.background, paddingTop: insets.top }]}>
        {/* Header */}
        <View style={[styles.header, { borderBottomColor: colors.border }]}>
          <TouchableOpacity onPress={onClose} activeOpacity={0.7} style={styles.closeBtn}>
            <Feather name="x" size={20} color={colors.foreground} />
          </TouchableOpacity>
          <Text style={[styles.title, { color: colors.foreground }]}>Media Library</Text>
          <TouchableOpacity
            onPress={handleConfirm}
            disabled={selected.size === 0}
            activeOpacity={0.8}
            style={[styles.addBtn, { backgroundColor: selected.size > 0 ? colors.primary : colors.muted }]}
          >
            <Text style={[styles.addBtnText, { color: colors.primaryForeground }]}>
              {selected.size > 0 ? `Add ${selected.size}` : "Add"}
            </Text>
          </TouchableOpacity>
        </View>

        {/* Workspace tabs (only shown when >1 workspace) */}
        {workspaces.length > 1 && (
          <ScrollView
            horizontal
            showsHorizontalScrollIndicator={false}
            style={[styles.tabs, { borderBottomColor: colors.border }]}
            contentContainerStyle={styles.tabsContent}
          >
            {workspaces.map((ws) => {
              const active = ws.id === activeId;
              return (
                <TouchableOpacity
                  key={ws.id}
                  onPress={() => setActiveId(ws.id)}
                  activeOpacity={0.7}
                  style={[
                    styles.tab,
                    active && { borderBottomColor: colors.primary, borderBottomWidth: 2 },
                  ]}
                >
                  <Text style={[styles.tabText, { color: active ? colors.primary : colors.mutedForeground }]}>
                    {ws.name}
                  </Text>
                </TouchableOpacity>
              );
            })}
          </ScrollView>
        )}

        {/* Content */}
        {loading ? (
          <View style={styles.centered}>
            <ActivityIndicator color={colors.primary} size="large" />
          </View>
        ) : error === "SESSION_REQUIRED" ? (
          <View style={styles.centered}>
            <Feather name="lock" size={28} color={colors.mutedForeground} />
            <Text style={[styles.errorText, { color: colors.mutedForeground }]}>
              {"Media library requires a web session.\nAPI key access is not supported by Postiz."}
            </Text>
            {onPickFromDevice && (
              <TouchableOpacity
                onPress={() => { onClose(); onPickFromDevice(); }}
                style={[styles.retryBtn, { backgroundColor: colors.primary }]}
                activeOpacity={0.8}
              >
                <Text style={[styles.retryText, { color: colors.primaryForeground }]}>Use device gallery</Text>
              </TouchableOpacity>
            )}
          </View>
        ) : error === "ENDPOINT_NOT_FOUND" ? (
          <View style={styles.centered}>
            <Feather name="slash" size={28} color={colors.mutedForeground} />
            <Text style={[styles.errorText, { color: colors.mutedForeground }]}>
              {"Media library endpoint not found on this server."}
            </Text>
          </View>
        ) : error ? (
          <View style={styles.centered}>
            <Feather name="alert-circle" size={28} color={colors.error} />
            <Text style={[styles.errorText, { color: colors.mutedForeground }]}>{error}</Text>
            <TouchableOpacity onPress={load} style={[styles.retryBtn, { backgroundColor: colors.primary }]} activeOpacity={0.8}>
              <Text style={[styles.retryText, { color: colors.primaryForeground }]}>Retry</Text>
            </TouchableOpacity>
          </View>
        ) : items.length === 0 ? (
          <View style={styles.centered}>
            <Feather name="image" size={36} color={colors.mutedForeground} />
            <Text style={[styles.emptyText, { color: colors.mutedForeground }]}>No media found</Text>
          </View>
        ) : (
          <FlatList
            data={items}
            keyExtractor={(item) => item.id}
            numColumns={3}
            contentContainerStyle={[styles.grid, { paddingBottom: insets.bottom + 16 }]}
            renderItem={({ item }) => {
              const isSelected = selected.has(item.id);
              const uri = resolveUrl(item.path, activeWorkspace?.baseUrl ?? "");
              return (
                <TouchableOpacity onPress={() => toggle(item.id)} activeOpacity={0.8} style={styles.cell}>
                  <Image source={{ uri }} style={styles.cellImage} contentFit="cover" />
                  {isSelected && (
                    <View style={[styles.selectedOverlay, { backgroundColor: colors.primary + "99" }]}>
                      <View style={[styles.checkCircle, { backgroundColor: colors.primary }]}>
                        <Feather name="check" size={14} color="#fff" />
                      </View>
                    </View>
                  )}
                </TouchableOpacity>
              );
            }}
          />
        )}
      </View>
    </Modal>
  );
}

const CELL = 120;

const styles = StyleSheet.create({
  root: { flex: 1 },
  header: {
    flexDirection: "row", alignItems: "center",
    paddingHorizontal: 16, paddingVertical: 14,
    borderBottomWidth: StyleSheet.hairlineWidth, gap: 12,
  },
  closeBtn: { padding: 4 },
  title: { flex: 1, fontSize: 17, fontFamily: "Inter_600SemiBold" },
  addBtn: { paddingHorizontal: 16, paddingVertical: 8, borderRadius: 20 },
  addBtnText: { fontSize: 14, fontFamily: "Inter_600SemiBold" },
  tabs: { borderBottomWidth: StyleSheet.hairlineWidth, flexGrow: 0 },
  tabsContent: { paddingHorizontal: 12, gap: 4 },
  tab: { paddingHorizontal: 12, paddingVertical: 12 },
  tabText: { fontSize: 13, fontFamily: "Inter_500Medium" },
  centered: { flex: 1, alignItems: "center", justifyContent: "center", gap: 12 },
  errorText: { fontSize: 14, fontFamily: "Inter_400Regular", textAlign: "center", paddingHorizontal: 32 },
  emptyText: { fontSize: 14, fontFamily: "Inter_400Regular" },
  retryBtn: { paddingHorizontal: 20, paddingVertical: 10, borderRadius: 10 },
  retryText: { fontSize: 14, fontFamily: "Inter_600SemiBold" },
  grid: { padding: 2 },
  cell: { width: CELL, height: CELL, margin: 2 },
  cellImage: { width: CELL, height: CELL, borderRadius: 4 },
  selectedOverlay: {
    ...StyleSheet.absoluteFillObject, borderRadius: 4,
    alignItems: "center", justifyContent: "center",
  },
  checkCircle: { width: 28, height: 28, borderRadius: 14, alignItems: "center", justifyContent: "center" },
});
