import { AutoCompleteItem } from "@/apis/autoCompleteApi";
import { Season } from "@/apis/seasonApi";
import { Show } from "@/apis/showApi";
import { Colors } from "@/constants/colors";
import { useDiscoveryContext } from "@/contexts/DiscoveryContext";
import Feather from "@expo/vector-icons/Feather";
import { Stack } from "expo-router";
import React from "react";
import {
  Dimensions,
  Image,
  ScrollView,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from "react-native";

import { getShowById } from "@/apis/showApi";
import PersonRow from "@/components/discovery/PersonRow";
import TagChip from "@/components/discovery/TagChip";
import { useSearch } from "@/hooks/useSearch";
import {
  getIconName,
  mapApiPersonToUI,
  mapApiSeasonToUI,
  mapApiShowToUI,
} from "@/utils/searchMapping";
import { router } from "expo-router";

export default function ExploreScreen() {
  const { query, setQuery, suggestions } = useDiscoveryContext();

  const [tags, setTags] = React.useState<AutoCompleteItem[]>([]);
  const tagStrings = React.useMemo(() => tags.map((t) => t.text), [tags]);

  const {
    data: results = [],
    error,
    refetch,
  } = useSearch(tagStrings as string[]);

  // Lokaler Show-Cache
  const [showsById, setShowsById] = React.useState<Record<number, Show>>({});

  // Steuerung für Vorschlagsliste
  const [showSuggestions, setShowSuggestions] = React.useState(false);

  function tagAdded(tag: AutoCompleteItem) {
    const nextTags = tags.some((t) => t.text === tag.text)
      ? tags
      : [...tags, tag];
    setTags(nextTags);
    setQuery("");
    setShowSuggestions(false);
  }

  function tagRemoved(tag: AutoCompleteItem) {
    const nextTags = tags.filter((t) => t.text !== tag.text);
    setTags(nextTags);
  }

  // Cache mit SHOW-Resultaten füllen
  React.useEffect(() => {
    const fromResults: Record<number, Show> = {};
    for (const r of results) {
      if (r.type === "SHOW") {
        const uiShow = mapApiShowToUI(r.data);
        if (uiShow.showId != null)
          fromResults[Number(uiShow.showId)] = uiShow as Show;
      }
    }
    if (Object.keys(fromResults).length) {
      setShowsById((prev) => ({ ...prev, ...fromResults }));
    }
  }, [results]);

  // SEASON-Ergebnisse nach showId gruppieren
  const seasonsByShowId = React.useMemo(() => {
    const map = new Map<number, Season[]>();
    for (const r of results) {
      if (r.type !== "SEASON") continue;
      const s = mapApiSeasonToUI(r.data);
      if (!s || s.showId == null) continue;
      const key = Number(s.showId);
      const list = map.get(key) ?? [];
      list.push(s as Season);
      map.set(key, list);
    }
    for (const [k, list] of map) {
      list.sort((a, b) => {
        const da = a?.startDate
          ? new Date(a.startDate).getTime()
          : Number.POSITIVE_INFINITY;
        const db = b?.startDate
          ? new Date(b.startDate).getTime()
          : Number.POSITIVE_INFINITY;
        return da - db;
      });
      map.set(k, list);
    }
    return map;
  }, [results]);

  // Fehlende Shows für Carousels nachladen
  React.useEffect(() => {
    const needed = Array.from(seasonsByShowId.keys()).filter(
      (id) => !showsById[id],
    );
    if (needed.length === 0) return;

    let cancelled = false;
    (async () => {
      try {
        const fetched = await Promise.all(needed.map((id) => getShowById(id)));
        if (cancelled) return;

        const next: Record<number, Show> = {};
        for (const s of fetched) {
          if (!s) continue;
          next[s.id] = s;
        }
        if (Object.keys(next).length) {
          setShowsById((prev) => ({ ...prev, ...next }));
        }
      } catch (e) {
        console.error(e);
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [seasonsByShowId, showsById]);

  // PERSON-Resultate
  const persons = React.useMemo(() => {
    return results
      .filter((r) => r.type === "PERSON")
      .map((r) => mapApiPersonToUI(r.data))
      .sort((a, b) => (a.name || "").localeCompare(b.name || ""));
  }, [results]);

  // SHOW-Resultate: alle Shows (direkte Treffer + aus Seasons) vereint
  const unifiedShows = React.useMemo(() => {
    const map = new Map<number, { show: Show; seasons: Season[] }>();

    // Shows aus Season-Ergebnissen
    for (const [showId, seasons] of seasonsByShowId) {
      const show = showsById[Number(showId)];
      if (show) {
        map.set(Number(showId), { show, seasons });
      }
    }

    // Direkte Show-Treffer (ohne Seasons)
    for (const r of results) {
      if (r.type !== "SHOW") continue;
      const uiShow = mapApiShowToUI(r.data);
      const id = Number(uiShow.id);
      if (!map.has(id)) {
        const cachedShow = showsById[id];
        map.set(id, { show: cachedShow ?? uiShow, seasons: [] });
      }
    }

    return Array.from(map.values());
  }, [results, seasonsByShowId, showsById]);

  // Fehlerblock
  if (error) {
    return (
      <View
        style={[
          s.container,
          { justifyContent: "center", alignItems: "center", padding: 20 },
        ]}
      >
        <View style={s.emptyState}>
          <Feather
            name="alert-triangle"
            size={44}
            color="rgba(255,255,255,0.2)"
          />
          <Text style={s.emptyTitle}>Fehler beim Laden</Text>
          <Text style={s.emptySubtitle}>
            {error?.message || "Ein unerwarteter Fehler ist aufgetreten."}
          </Text>
          <TouchableOpacity
            onPress={() => {
              if (typeof refetch === "function") refetch();
            }}
            style={s.emptyButton}
            activeOpacity={0.7}
          >
            <Text style={s.emptyButtonText}>Erneut versuchen</Text>
          </TouchableOpacity>
        </View>
      </View>
    );
  }

  const noResults = persons.length === 0 && unifiedShows.length === 0;

  return (
    <View style={s.container}>
      <Stack.Screen
        options={{
          headerSearchBarOptions: {
            placeholder: "Wonach suchst du?",
            hideWhenScrolling: false,
            autoCapitalize: "none",
            onChangeText: (e) => {
              const text = e.nativeEvent.text;
              setQuery(text);
              setShowSuggestions(text.length > 0);
            },
            onSearchButtonPress: (e) => {
              const text = e.nativeEvent.text;
              if (!text?.trim()) return;
              tagAdded({ type: "CUSTOM", text: text.trim() });
            },
            onCancelButtonPress: () => {
              setQuery("");
              setShowSuggestions(false);
            },
          },
        }}
      />

      {/* Suggestions overlay */}
      {query.length > 0 && showSuggestions && suggestions.length > 0 && (
        <View style={s.suggestionsOverlay}>
          <ScrollView
            keyboardShouldPersistTaps="handled"
            showsVerticalScrollIndicator={false}
          >
            <Text style={s.suggestionsHeader}>VORSCHLÄGE</Text>
            <View style={s.suggestionsGroup}>
              {suggestions.slice(0, 10).map((suggestion, idx, arr) => (
                <TouchableOpacity
                  key={suggestion.text + "_" + idx}
                  style={[
                    s.suggestionRow,
                    idx === 0 && {
                      borderTopLeftRadius: 10,
                      borderTopRightRadius: 10,
                    },
                    idx === arr.length - 1 && {
                      borderBottomLeftRadius: 10,
                      borderBottomRightRadius: 10,
                      borderBottomWidth: 0,
                    },
                  ]}
                  onPress={() => tagAdded(suggestion)}
                  activeOpacity={0.6}
                >
                  <Feather
                    name={
                      suggestion.type === "PERSON"
                        ? "user"
                        : suggestion.type === "SHOW"
                          ? "tv"
                          : "tag"
                    }
                    size={14}
                    color="rgba(255,255,255,0.5)"
                  />
                  <Text style={s.suggestionText}>{suggestion.text}</Text>
                  <Feather
                    name="arrow-up-left"
                    size={12}
                    color="rgba(255,255,255,0.3)"
                  />
                </TouchableOpacity>
              ))}
            </View>
          </ScrollView>
        </View>
      )}

      <ScrollView
        contentInsetAdjustmentBehavior="automatic"
        keyboardShouldPersistTaps="handled"
      >
        {/* Tag chips */}
        {tags.length > 0 && (
          <View style={s.section}>
            <View style={s.tagRow}>
              {tags.map((tag) => (
                <TagChip
                  key={tag.text}
                  icon={getIconName(tag.type)}
                  label={tag.text}
                  onPress={() => tagRemoved(tag)}
                />
              ))}
            </View>
          </View>
        )}

        {/* Personen Section */}
        {persons.length > 0 && (
          <View style={s.section}>
            <Text style={s.sectionHeader}>PERSONEN</Text>
            <View style={s.groupedCard}>
              {persons.slice(0, 5).map((p, i, arr) => (
                <PersonRow
                  key={`p-${p.personId ?? p.id}`}
                  person={p}
                  isFirst={i === 0}
                  isLast={i === arr.length - 1}
                />
              ))}
            </View>
          </View>
        )}

        {/* Shows + Staffeln unified */}
        {unifiedShows.length > 0 && (
          <View style={s.section}>
            <Text style={s.sectionHeader}>SHOWS</Text>
            {unifiedShows.map(({ show, seasons }) => (
              <TouchableOpacity
                key={`show-${show.id}`}
                style={s.showCard}
                activeOpacity={0.7}
                onPress={() =>
                  router.push({
                    pathname: "/showDetails",
                    params: { id: String(show.id) },
                  })
                }
              >
                <Image
                  source={{
                    uri: show.bannerUri || show.thumbnailUri,
                  }}
                  style={s.showCardImage}
                  resizeMode="cover"
                />
                <View style={s.showCardBody}>
                  <View style={s.showCardHeader}>
                    <View style={{ flex: 1 }}>
                      <Text style={s.showCardTitle} numberOfLines={1}>
                        {show.title}
                      </Text>
                      {show.description ? (
                        <Text style={s.showCardDescription} numberOfLines={2}>
                          {show.description}
                        </Text>
                      ) : null}
                    </View>
                    {show.running && (
                      <View style={s.liveBadge}>
                        <Text style={s.liveBadgeText}>LIVE</Text>
                      </View>
                    )}
                  </View>
                  {seasons.length > 0 && (
                    <View style={s.seasonRow}>
                      {seasons.map((season) => (
                        <View
                          key={(season as any).seasonId}
                          style={s.seasonPill}
                        >
                          <Text style={s.seasonPillText}>
                            S{(season as any).seasonNumber}
                            {(season as any).startDate
                              ? ` · ${new Date((season as any).startDate).getFullYear()}`
                              : ""}
                          </Text>
                        </View>
                      ))}
                    </View>
                  )}
                </View>
              </TouchableOpacity>
            ))}
          </View>
        )}

        {/* Empty State */}
        {noResults && (
          <View style={s.section}>
            <View style={s.emptyState}>
              <Feather name="search" size={44} color="rgba(255,255,255,0.2)" />
              <Text style={s.emptyTitle}>Keine Ergebnisse</Text>
              <Text style={s.emptySubtitle}>
                Passe deine Tags an oder setze die Filter zurück.
              </Text>

              {tags.length > 0 && (
                <TouchableOpacity
                  onPress={() => {
                    setTags([]);
                    setQuery("");
                    setShowSuggestions(false);
                    if (typeof refetch === "function") refetch();
                  }}
                  style={s.emptyButton}
                  activeOpacity={0.7}
                >
                  <Text style={s.emptyButtonText}>Filter zurücksetzen</Text>
                </TouchableOpacity>
              )}
            </View>
          </View>
        )}
      </ScrollView>
    </View>
  );
}

const s = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: Colors.background,
  },
  section: {
    paddingHorizontal: 16,
    marginBottom: 20,
    paddingTop: 20,
  },
  sectionHeader: {
    color: "rgba(255,255,255,0.45)",
    fontSize: 13,
    fontWeight: "600",
    letterSpacing: 0.5,
    marginBottom: 8,
    paddingLeft: 4,
  },
  groupedCard: {
    borderRadius: 10,
    overflow: "hidden",
  },
  tagRow: {
    flexDirection: "row",
    flexWrap: "wrap",
  },
  // Suggestions overlay
  suggestionsOverlay: {
    position: "absolute",
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    zIndex: 10,
    paddingHorizontal: 16,
    paddingTop: 6,
    backgroundColor: Colors.background,
  },
  suggestionsHeader: {
    color: "rgba(255,255,255,0.45)",
    fontSize: 12,
    fontWeight: "600",
    letterSpacing: 0.5,
    marginBottom: 6,
    paddingLeft: 4,
    marginTop: Dimensions.get("screen").height / 7,
  },
  suggestionsGroup: {
    borderRadius: 10,
    overflow: "hidden",
  },
  suggestionRow: {
    flexDirection: "row",
    alignItems: "center",
    backgroundColor: "rgba(255,255,255,0.06)",
    paddingHorizontal: 14,
    paddingVertical: 10,
    gap: 10,
    borderBottomWidth: StyleSheet.hairlineWidth,
    borderBottomColor: "rgba(255,255,255,0.08)",
  },
  suggestionText: {
    color: "white",
    fontSize: 15,
    flex: 1,
  },
  // Empty state
  emptyState: {
    alignItems: "center",
    justifyContent: "center",
    paddingVertical: 48,
    paddingHorizontal: 32,
    gap: 8,
  },
  emptyTitle: {
    fontSize: 20,
    fontWeight: "600",
    color: "rgba(255,255,255,0.8)",
    marginTop: 8,
  },
  emptySubtitle: {
    fontSize: 15,
    color: "rgba(255,255,255,0.45)",
    textAlign: "center",
    lineHeight: 20,
  },
  emptyButton: {
    marginTop: 16,
    backgroundColor: "rgba(255,255,255,0.1)",
    paddingVertical: 10,
    paddingHorizontal: 20,
    borderRadius: 10,
  },
  emptyButtonText: {
    color: Colors.primary,
    fontSize: 15,
    fontWeight: "600",
  },
  // Unified show cards
  showCard: {
    borderRadius: 16,
    overflow: "hidden",
    backgroundColor: "rgba(255,255,255,0.06)",
    borderWidth: StyleSheet.hairlineWidth,
    borderColor: "rgba(255,255,255,0.08)",
    marginBottom: 12,
  },
  showCardImage: {
    width: "100%",
    height: 160,
  },
  showCardBody: {
    padding: 14,
    gap: 10,
  },
  showCardHeader: {
    flexDirection: "row",
    alignItems: "flex-start",
    gap: 10,
  },
  showCardTitle: {
    color: "#fff",
    fontSize: 17,
    fontWeight: "700",
    letterSpacing: 0.1,
  },
  showCardDescription: {
    color: "rgba(255,255,255,0.45)",
    fontSize: 13,
    lineHeight: 18,
    marginTop: 4,
  },
  liveBadge: {
    backgroundColor: "rgba(255,59,48,0.2)",
    borderWidth: StyleSheet.hairlineWidth,
    borderColor: "rgba(255,59,48,0.4)",
    paddingHorizontal: 8,
    paddingVertical: 3,
    borderRadius: 10,
  },
  liveBadgeText: {
    color: "#ff3b30",
    fontSize: 10,
    fontWeight: "700",
    letterSpacing: 0.5,
  },
  seasonRow: {
    flexDirection: "row",
    flexWrap: "wrap",
    gap: 6,
  },
  seasonPill: {
    paddingVertical: 5,
    paddingHorizontal: 12,
    borderRadius: 14,
    backgroundColor: "rgba(25,158,219,0.15)",
    borderWidth: StyleSheet.hairlineWidth,
    borderColor: "rgba(25,158,219,0.25)",
  },
  seasonPillText: {
    color: "#199edb",
    fontSize: 12,
    fontWeight: "600",
  },
});
