import { getPersonHistory, type PersonMini } from "@/apis/personHistoryApi";
import { getShowById } from "@/apis/showApi";
import styles from "@/app/stackStyles/participantStyles";
import { useShowContext } from "@/contexts/ShowContext";
import Ionicons from "@expo/vector-icons/Ionicons";
import { router, useLocalSearchParams } from "expo-router";
import * as WebBrowser from "expo-web-browser";
import React from "react";
import { Image, Text, TouchableOpacity, View } from "react-native";
import {
  GestureHandlerRootView,
  ScrollView,
} from "react-native-gesture-handler";

type SeasonEntry = {
  seasonNumber: number;
  partner: PersonMini | null;
  participants: PersonMini[];
  startDate: string | null;
};

type AppearanceGroup = {
  show: {
    id: number;
    title: string;
    bannerUri: string;
    thumbnailUri: string;
  };
  seasons: SeasonEntry[];
};

export default function ParticipantScreen() {
  const { shows } = useShowContext();
  const { name, participantId } = useLocalSearchParams();

  const pid = Array.isArray(participantId)
    ? Number(participantId[0])
    : Number(participantId);

  const [, setLoading] = React.useState(false);
  const [, setError] = React.useState<string | null>(null);

  const [appearances, setAppearances] = React.useState<AppearanceGroup[]>([]);

  const formatYear = (iso?: string | null) => {
    if (!iso) return null;
    const [y] = iso.split("-");
    return y || null;
  };

  React.useEffect(() => {
    if (!pid || Number.isNaN(pid)) return;
    const controller = new AbortController();
    setLoading(true);
    setError(null);

    (async () => {
      try {
        const hist = await getPersonHistory(pid, controller.signal);

        const grouped = new Map<number, Map<number, SeasonEntry>>();
        for (const h of hist) {
          if (!Number.isFinite(h.showId) || h.showId <= 0) continue;
          const seasonsForShow =
            grouped.get(h.showId) ?? new Map<number, SeasonEntry>();

          const existing = seasonsForShow.get(h.seasonNumber);
          if (existing) {
            seasonsForShow.set(h.seasonNumber, {
              seasonNumber: h.seasonNumber,
              partner: existing.partner ?? h.partner ?? null,
              participants: existing.participants.length
                ? existing.participants
                : (h.seasonParticipants ?? []),
              startDate: existing.startDate ?? h.startDate ?? null,
            });
          } else {
            seasonsForShow.set(h.seasonNumber, {
              seasonNumber: h.seasonNumber,
              partner: h.partner ?? null,
              participants: h.seasonParticipants ?? [],
              startDate: h.startDate ?? null,
            });
          }

          grouped.set(h.showId, seasonsForShow);
        }

        const showIds = Array.from(grouped.keys());

        const fromContext = showIds
          .map((id) => shows.find((s) => s.id === id))
          .filter((s): s is (typeof shows)[number] => !!s);

        const missingIds = showIds.filter(
          (id) => !fromContext.some((s) => s.id === id)
        );

        const fetched = await Promise.all(
          missingIds.map(async (id) => {
            try {
              const s = await getShowById(id);
              return s;
            } catch {
              return null;
            }
          })
        );

        const allShows = [
          ...fromContext,
          ...fetched.filter(Boolean),
        ] as typeof shows;

        const result: AppearanceGroup[] = allShows.map((s) => {
          const seasonsMap = grouped.get(s.id)!;
          const seasonsSorted = Array.from(seasonsMap.values()).sort(
            (a, b) => a.seasonNumber - b.seasonNumber
          );
          return {
            show: {
              id: s.id,
              title: s.title,
              bannerUri: s.bannerUri,
              thumbnailUri: s.thumbnailUri,
            },
            seasons: seasonsSorted,
          };
        });

        result.sort((a, b) =>
          a.show.title.localeCompare(b.show.title, "de", {
            sensitivity: "base",
          })
        );

        setAppearances(result);
      } catch (e: any) {
        if (!controller.signal.aborted)
          setError(e?.message || "Fehler beim Laden");
      } finally {
        if (!controller.signal.aborted) setLoading(false);
      }
    })();

    return () => controller.abort();
  }, [pid, shows]);

  const [expandedShows, setExpandedShows] = React.useState<Set<number>>(
    new Set()
  );
  const toggleExpand = React.useCallback((showId: number) => {
    setExpandedShows((prev) => {
      const next = new Set(prev);
      if (next.has(showId)) next.delete(showId);
      else next.add(showId);
      return next;
    });
  }, []);

  const goToShow = React.useCallback((id: number) => {
    router.push({ pathname: "/showDetails", params: { id: String(id) } });
  }, []);

  const goToPerson = React.useCallback(
    (p: PersonMini) => {
      if (!p?.personId) return;

      if (p.personId === pid) return;
      router.push({
        pathname: "/participant",
        params: { participantId: String(p.personId), name: p.name },
      });
    },
    [pid]
  );

  return (
    <GestureHandlerRootView style={styles.mainContainer}>
      <ScrollView
        showsVerticalScrollIndicator={false}
        contentContainerStyle={{ paddingBottom: 20, paddingTop: 10 }}
      >
        <Text style={styles.participantName}>{name}</Text>
        <TouchableOpacity
          style={styles.closeIcon}
          onPress={() => router.back()}
        >
          <Ionicons name="close-circle-outline" size={38} color="white" />
        </TouchableOpacity>

        <View style={styles.performedShowsSection}>
          <TouchableOpacity
            style={styles.searchButton}
            onPress={() =>
              WebBrowser.openBrowserAsync(
                "https://www.google.com/search?udm=2&q=" +
                  encodeURIComponent(String(name))
              )
            }
          >
            <Ionicons name="images-outline" size={24} color="white" />
          </TouchableOpacity>

          <Text style={styles.performedShowsTitle}>Auftritte:</Text>

          <ScrollView
            horizontal
            showsHorizontalScrollIndicator={false}
            style={{ flex: 1 }}
            contentContainerStyle={{
              gap: 20,
              paddingHorizontal: 15,
              paddingLeft: 30,
            }}
          >
            {appearances.map(({ show, seasons }) => {
              const partners = Array.from(
                new Map(
                  seasons
                    .map((s) => s.partner)
                    .filter((p): p is NonNullable<typeof p> => !!p)
                    .map((p) => [p.personId, p])
                ).values()
              );

              const allParticipants = Array.from(
                new Map(
                  seasons
                    .flatMap((s) => s.participants)
                    .filter((p) => p.personId !== pid)
                    .map((p) => [p.personId, p])
                ).values()
              );

              const isExpanded = expandedShows.has(show.id);
              const visible = isExpanded
                ? allParticipants
                : allParticipants.slice(0, 12);
              const restCount = Math.max(
                allParticipants.length - visible.length,
                0
              );

              return (
                <View key={show.id} style={styles.card}>
                  <TouchableOpacity
                    style={styles.showContainer}
                    onPress={() => goToShow(show.id)}
                  >
                    <Image
                      source={{ uri: show.bannerUri || show.thumbnailUri }}
                      style={styles.showImage}
                      resizeMode="cover"
                    />
                  </TouchableOpacity>
                  <Text style={styles.showTitle} numberOfLines={1}>
                    {show.title}
                  </Text>
                  <Text style={styles.showSeason}>
                    ({formatYear(seasons[0]?.startDate)})
                  </Text>
                  <Text style={styles.showSeason}>
                    Staffel {seasons.map((s) => s.seasonNumber).join(" und ")}
                  </Text>

                  <View style={styles.horizontalLine} />

                  <Text style={[styles.participantLabel, { marginTop: 10 }]}>
                    Weitere Teilnehmer
                  </Text>

                  <View style={styles.participantContainer}>
                    <View style={styles.participantRow}>
                      {visible.map((p) => (
                        <TouchableOpacity
                          key={p.personId}
                          style={styles.participantChip}
                          onPress={() => goToPerson(p)}
                        >
                          <Text
                            style={styles.participantChipText}
                            numberOfLines={1}
                          >
                            {p.name}
                          </Text>
                        </TouchableOpacity>
                      ))}

                      {!isExpanded && restCount > 0 && (
                        <TouchableOpacity
                          onPress={() => toggleExpand(show.id)}
                          style={styles.moreChip}
                        >
                          <Text style={styles.moreChipText}>
                            +{restCount} mehr
                          </Text>
                        </TouchableOpacity>
                      )}

                      {isExpanded && allParticipants.length > 12 && (
                        <TouchableOpacity
                          onPress={() => toggleExpand(show.id)}
                          style={styles.moreChip}
                        >
                          <Text style={styles.moreChipText}>Weniger</Text>
                        </TouchableOpacity>
                      )}
                    </View>
                  </View>

                  {partners.length > 0 && (
                    <>
                      <View style={styles.horizontalLine} />
                      <Text
                        style={[styles.participantLabel, { marginTop: 10 }]}
                      >
                        Partner
                      </Text>
                      <View
                        style={[
                          styles.showContainer,
                          {
                            backgroundColor: "hsl(221, 39%, 12%)",
                            width: 150,
                            marginTop: 20,
                          },
                        ]}
                      >
                        <Image
                          style={styles.showImage}
                          blurRadius={20}
                          source={{
                            uri: `https://i.pravatar.cc/300?img=${Math.floor(Math.random() * 70)}`,
                          }}
                        />
                      </View>
                      {partners.map((p) => (
                        <Text
                          key={p.personId}
                          style={styles.partnerLabel}
                          numberOfLines={1}
                        >
                          {p.name}
                        </Text>
                      ))}
                    </>
                  )}
                </View>
              );
            })}
          </ScrollView>
        </View>
      </ScrollView>
    </GestureHandlerRootView>
  );
}
