import { AutoCompleteItem } from "@/apis/autoCompleteApi";
import { SearchResultItem } from "@/apis/searchApi";
import { Season } from "@/apis/seasonApi";
import { Show } from "@/apis/showApi";
import styles from "@/app/tabStyles/indexStyles";
import ShowBox from "@/components/discovery/ShowBox";
import { useDiscoveryContext } from "@/contexts/DiscoveryContext";
import { FontAwesome } from "@expo/vector-icons";
import Feather from "@expo/vector-icons/Feather";
import React from "react";
import { Keyboard, ScrollView, Text, TextInput, TouchableOpacity, View } from "react-native";

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

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 = [] } = useSearch(tagStrings);

  // Show metadata cache by id (filled from SHOW results and lazy-loaded by id)
  const [showsById, setShowsById] = React.useState<Record<number, Show>>({});

  // --- helpers ---


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

    setQuery("");
    Keyboard.dismiss();
  }

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

  // Keep our local show cache in sync with SHOW items returned by search
  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]);



  // Group SEASON results by showId
  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);
    }
    // sort seasons per show by startDate asc
    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]);

  // Lazy fetch missing shows needed for Season carousels
  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; // wichtig: s.id, nicht s.showId
        }
        if (Object.keys(next).length) {
          setShowsById((prev) => ({ ...prev, ...next }));
        }
      } catch (e) {
        console.error(e);
      }
    })();

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

  // PERSON hits shown at the top (like old screen)
  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]);

  return (
    <View style={[styles.mainContainer]}>
      <View style={styles.header}>
        <Text style={[styles.title, { fontSize: 28 }]}>Durchsuchen</Text>
      </View>

      <View style={styles.sectionContainer}>
        {/* Search bar */}
        <View style={styles.searchContainer}>
          <TextInput
            value={query}
            onChangeText={setQuery}
            placeholder="Wonach suchst du?"
            placeholderTextColor=""
            style={styles.searchInput}
            returnKeyType="search"
            onSubmitEditing={() => {
              if (!query.trim()) return;
              tagAdded({ type: "CUSTOM", text: query.trim() });
            }}
            autoCapitalize="none"
          />

          {query.length === 0 ? (
            <Feather name="search" size={24} color="hsl(221, 39%, 80%)" />
          ) : (
            <Feather name="x" size={24} color="hsl(221, 39%, 80%)" onPress={() => setQuery("")} />
          )}
        </View>

        {/* Tag chips */}
        <View style={styles.tagContainer}>
          {tags.map((tag) => (
            <TagChip
              key={tag.text}
              icon={getIconName(tag.type)}
              label={tag.text}
              onPress={() => {
                tagRemoved(tag);
                
              }}
            />
          ))}
        </View>

        {/* Suggestions dropdown */}
        {query.length > 0 && (
          <View style={styles.suggestionsSection}>
            <Text style={styles.suggestionTitle}>Suchvorschläge</Text>
            <ScrollView keyboardShouldPersistTaps="handled">
              {suggestions.map((suggestion, idx) => (
                <TouchableOpacity
                  key={suggestion.text + "_" + idx}
                  style={styles.suggestionContainer}
                  onPress={() => tagAdded(suggestion)}
                >
                  <FontAwesome name={getIconName(suggestion.type)} size={16} color="hsl(0, 0%, 90%)" />
                  <Text style={styles.suggestionLabel}>{suggestion.text}</Text>
                </TouchableOpacity>
              ))}
            </ScrollView>
          </View>
        )}
      </View>

      {/* Results */}
      <View style={{ flex: 1 }}>
        <ScrollView keyboardShouldPersistTaps="handled">
          {/* Personen Section (top) */}
          {persons.length > 0 && (
            <View style={styles.sectionContainer}>
              <Text style={styles.sectionTitle}>Personen</Text>
              {persons.slice(0, 5).map((p) => (
                  <PersonRow key={`p-${p.personId ?? p.id}`} person={p}/>
              ))}
            </View>
          )}

          {/* Staffeln grouped by Show with page view */}
          <View style={styles.sectionContainer}>
            <Text style={styles.sectionTitle}>Staffeln</Text>

            {Array.from(seasonsByShowId.entries()).map(([showId, seasons]) => {
              const show = showsById[Number(showId)];
              if (!seasons || seasons.length === 0) return null;
              // If show metadata is not yet loaded, render a minimal ShowBox fallback once per page item
              if (!show) {
                return (
                    <SeasonCarousel
                      key={`sc-${showId}`}
                      show={{ showId: showId as any, title: "blaaa", description: "", genre: "", thumbnailUrl: "", running: false } as any}
                      seasons={seasons}
                      renderItem={(s) => <ShowBox show={{ showId: showId as any, title: `Show #${showId}`, description: "", genre: "", thumbnailUrl: "", running: false } as any} displayedSeason={s} shadow={false} />}
                    />
                );
              }
              return (
                  <SeasonCarousel
                    key={`sc-${showId}`}
                    show={show}
                    seasons={seasons}
                    renderItem={(s) => <ShowBox show={show} displayedSeason={s} shadow={false} />}
                  />
              );
            })}

            {seasonsByShowId.size === 0 && (
              <Text style={styles.centerText}>
                Keine Staffeln gefunden. Passe deine Tags an.
              </Text>
            )}
          </View>
        </ScrollView>
      </View>
    </View>
  );
}
