import { Ionicons } from "@expo/vector-icons";
import { useQuery } from "@tanstack/react-query";
import { BlurView } from "expo-blur";
import { Image } from "expo-image";
import { LinearGradient } from "expo-linear-gradient";
import { useLocalSearchParams } from "expo-router";
import React, { useCallback, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import {
  Animated,
  Dimensions,
  Pressable,
  ScrollView,
  TVFocusGuideView,
  View,
} from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { toast } from "sonner-native";
import { Text } from "@/components/common/Text";
import { GenreTags } from "@/components/GenreTags";
import { Loader } from "@/components/Loader";
import { JellyserrRatings } from "@/components/Ratings";
import { TVButton } from "@/components/tv";
import { useTVFocusAnimation } from "@/components/tv/hooks/useTVFocusAnimation";
import { useScaledTVTypography } from "@/constants/TVTypography";
import useRouter from "@/hooks/useAppRouter";
import { useJellyseerr } from "@/hooks/useJellyseerr";
import { useTVRequestModal } from "@/hooks/useTVRequestModal";
import { useTVSeasonSelectModal } from "@/hooks/useTVSeasonSelectModal";
import { useJellyseerrCanRequest } from "@/utils/_jellyseerr/useJellyseerrCanRequest";
import {
  MediaRequestStatus,
  MediaStatus,
  MediaType,
} from "@/utils/jellyseerr/server/constants/media";
import type MediaRequest from "@/utils/jellyseerr/server/entity/MediaRequest";
import type Season from "@/utils/jellyseerr/server/entity/Season";
import type { MediaRequestBody } from "@/utils/jellyseerr/server/interfaces/api/requestInterfaces";
import {
  hasPermission,
  Permission,
} from "@/utils/jellyseerr/server/lib/permissions";
import type { MovieDetails } from "@/utils/jellyseerr/server/models/Movie";
import type {
  MovieResult,
  TvResult,
} from "@/utils/jellyseerr/server/models/Search";
import type { TvDetails } from "@/utils/jellyseerr/server/models/Tv";

const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get("window");

// Cast card component
interface TVCastCardProps {
  person: {
    id: number;
    name: string;
    character?: string;
    profilePath?: string;
  };
  imageProxy: (path: string, size?: string) => string;
  onPress: () => void;
  refSetter?: (ref: View | null) => void;
}

const TVCastCard: React.FC<TVCastCardProps> = ({
  person,
  imageProxy,
  onPress,
  refSetter,
}) => {
  const typography = useScaledTVTypography();
  const { focused, handleFocus, handleBlur, animatedStyle } =
    useTVFocusAnimation({ scaleAmount: 1.08 });

  const profileUrl = person.profilePath
    ? imageProxy(person.profilePath, "w185")
    : null;

  return (
    <Pressable
      ref={refSetter}
      onPress={onPress}
      onFocus={handleFocus}
      onBlur={handleBlur}
    >
      <Animated.View
        style={[
          animatedStyle,
          {
            width: 140,
            alignItems: "center",
            shadowColor: "#fff",
            shadowOffset: { width: 0, height: 0 },
            shadowOpacity: focused ? 0.4 : 0,
            shadowRadius: focused ? 12 : 0,
          },
        ]}
      >
        <View
          style={{
            width: 120,
            height: 120,
            borderRadius: 60,
            overflow: "hidden",
            backgroundColor: "rgba(255,255,255,0.1)",
            marginBottom: 12,
            borderWidth: focused ? 3 : 0,
            borderColor: "#fff",
          }}
        >
          {profileUrl ? (
            <Image
              source={{ uri: profileUrl }}
              style={{ width: "100%", height: "100%" }}
              contentFit='cover'
              cachePolicy='memory-disk'
            />
          ) : (
            <View
              style={{
                flex: 1,
                justifyContent: "center",
                alignItems: "center",
              }}
            >
              <Ionicons name='person' size={48} color='rgba(255,255,255,0.4)' />
            </View>
          )}
        </View>
        <Text
          style={{
            fontSize: typography.callout,
            color: focused ? "#fff" : "rgba(255,255,255,0.9)",
            fontWeight: "600",
            textAlign: "center",
          }}
          numberOfLines={2}
        >
          {person.name}
        </Text>
        {person.character && (
          <Text
            style={{
              fontSize: 14,
              color: focused
                ? "rgba(255,255,255,0.7)"
                : "rgba(255,255,255,0.5)",
              textAlign: "center",
              marginTop: 4,
            }}
            numberOfLines={1}
          >
            {person.character}
          </Text>
        )}
      </Animated.View>
    </Pressable>
  );
};

export const TVJellyseerrPage: React.FC = () => {
  const typography = useScaledTVTypography();
  const insets = useSafeAreaInsets();
  const params = useLocalSearchParams();
  const { t } = useTranslation();
  const router = useRouter();

  const { mediaTitle, releaseYear, posterSrc, mediaType, ...result } =
    params as unknown as {
      mediaTitle: string;
      releaseYear: number;
      canRequest: string;
      posterSrc: string;
      mediaType: MediaType;
    } & Partial<MovieResult | TvResult | MovieDetails | TvDetails>;

  const { jellyseerrApi, jellyseerrUser, requestMedia } = useJellyseerr();
  const { showRequestModal } = useTVRequestModal();
  const { showSeasonSelectModal } = useTVSeasonSelectModal();

  // Refs for TVFocusGuideView destinations (useState triggers re-render when set)
  const [playButtonRef, setPlayButtonRef] = useState<View | null>(null);
  const [firstCastCardRef, setFirstCastCardRef] = useState<View | null>(null);

  const {
    data: details,
    isFetching,
    isLoading,
    refetch,
  } = useQuery({
    enabled: !!jellyseerrApi && !!result && !!result.id,
    queryKey: ["jellyseerr", "detail", mediaType, result.id],
    staleTime: 0,
    refetchOnMount: true,
    queryFn: async () => {
      return mediaType === MediaType.MOVIE
        ? jellyseerrApi?.movieDetails(result.id!)
        : jellyseerrApi?.tvDetails(result.id!);
    },
  });

  const [canRequest, hasAdvancedRequestPermission] =
    useJellyseerrCanRequest(details);

  const canManageRequests = useMemo(() => {
    if (!jellyseerrUser) return false;
    return hasPermission(
      Permission.MANAGE_REQUESTS,
      jellyseerrUser.permissions,
    );
  }, [jellyseerrUser]);

  const pendingRequest = useMemo(() => {
    return details?.mediaInfo?.requests?.find(
      (r: MediaRequest) => r.status === MediaRequestStatus.PENDING,
    );
  }, [details]);

  // Get seasons with status for TV shows
  const seasons = useMemo(() => {
    if (!details || mediaType !== MediaType.TV) return [];
    const tvDetails = details as TvDetails;
    const mediaInfoSeasons = tvDetails.mediaInfo?.seasons?.filter(
      (s: Season) => s.seasonNumber !== 0,
    );
    const requestedSeasons =
      tvDetails.mediaInfo?.requests?.flatMap((r: MediaRequest) => r.seasons) ??
      [];
    return (
      tvDetails.seasons?.map((season) => ({
        ...season,
        status:
          mediaInfoSeasons?.find(
            (mediaSeason: Season) =>
              mediaSeason.seasonNumber === season.seasonNumber,
          )?.status ??
          requestedSeasons?.find(
            (s: Season) => s.seasonNumber === season.seasonNumber,
          )?.status ??
          MediaStatus.UNKNOWN,
      })) ?? []
    );
  }, [details, mediaType]);

  const _allSeasonsAvailable = useMemo(
    () => seasons.every((season) => season.status === MediaStatus.AVAILABLE),
    [seasons],
  );

  // Check if there are any requestable seasons (status === UNKNOWN)
  const hasRequestableSeasons = useMemo(
    () =>
      seasons.some(
        (season) =>
          season.seasonNumber !== 0 && season.status === MediaStatus.UNKNOWN,
      ),
    [seasons],
  );

  // Get cast
  const cast = useMemo(() => {
    return details?.credits?.cast?.slice(0, 10) ?? [];
  }, [details]);

  // Backdrop URL
  const backdropUrl = useMemo(() => {
    const path = details?.backdropPath || result.backdropPath;
    return path
      ? jellyseerrApi?.imageProxy(path, "w1920_and_h800_multi_faces")
      : null;
  }, [details, result.backdropPath, jellyseerrApi]);

  // Poster URL
  const posterUrl = useMemo(() => {
    if (posterSrc) return posterSrc;
    const path = details?.posterPath;
    return path ? jellyseerrApi?.imageProxy(path, "w342") : null;
  }, [posterSrc, details, jellyseerrApi]);

  // Handlers
  const handleApproveRequest = useCallback(async () => {
    if (!pendingRequest?.id) return;
    try {
      await jellyseerrApi?.approveRequest(pendingRequest.id);
      toast.success(t("jellyseerr.toasts.request_approved"));
      refetch();
    } catch (_error) {
      toast.error(t("jellyseerr.toasts.failed_to_approve_request"));
    }
  }, [jellyseerrApi, pendingRequest, refetch, t]);

  const handleDeclineRequest = useCallback(async () => {
    if (!pendingRequest?.id) return;
    try {
      await jellyseerrApi?.declineRequest(pendingRequest.id);
      toast.success(t("jellyseerr.toasts.request_declined"));
      refetch();
    } catch (_error) {
      toast.error(t("jellyseerr.toasts.failed_to_decline_request"));
    }
  }, [jellyseerrApi, pendingRequest, refetch, t]);

  const handleRequest = useCallback(async () => {
    const body: MediaRequestBody = {
      mediaId: Number(result.id!),
      mediaType: mediaType!,
      tvdbId: details?.externalIds?.tvdbId,
      ...(mediaType === MediaType.TV && {
        seasons: (details as TvDetails)?.seasons
          ?.filter?.((s) => s.seasonNumber !== 0)
          ?.map?.((s) => s.seasonNumber),
      }),
    };

    if (hasAdvancedRequestPermission) {
      showRequestModal({
        requestBody: body,
        title: mediaTitle,
        id: result.id!,
        mediaType: mediaType!,
        onRequested: refetch,
      });
      return;
    }

    requestMedia(mediaTitle, body, refetch);
  }, [
    details,
    result,
    requestMedia,
    hasAdvancedRequestPermission,
    mediaTitle,
    refetch,
    mediaType,
    showRequestModal,
  ]);

  const handleRequestAll = useCallback(() => {
    const body: MediaRequestBody = {
      mediaId: Number(result.id!),
      mediaType: MediaType.TV,
      tvdbId: details?.externalIds?.tvdbId,
      seasons: seasons
        .filter((s) => s.status === MediaStatus.UNKNOWN && s.seasonNumber !== 0)
        .map((s) => s.seasonNumber),
    };

    if (hasAdvancedRequestPermission) {
      showRequestModal({
        requestBody: body,
        title: mediaTitle,
        id: result.id!,
        mediaType: MediaType.TV,
        onRequested: refetch,
      });
      return;
    }

    requestMedia(`${mediaTitle}, ${t("jellyseerr.season_all")}`, body, refetch);
  }, [
    details,
    result,
    seasons,
    hasAdvancedRequestPermission,
    requestMedia,
    mediaTitle,
    refetch,
    t,
    showRequestModal,
  ]);

  const handleOpenSeasonSelectModal = useCallback(() => {
    showSeasonSelectModal({
      seasons: seasons.filter((s) => s.seasonNumber !== 0),
      title: mediaTitle,
      mediaId: Number(result.id!),
      tvdbId: details?.externalIds?.tvdbId,
      hasAdvancedRequestPermission,
      onRequested: refetch,
    });
  }, [
    seasons,
    mediaTitle,
    result,
    details,
    hasAdvancedRequestPermission,
    refetch,
    showSeasonSelectModal,
  ]);

  const handlePlay = useCallback(() => {
    const jellyfinMediaId = details?.mediaInfo?.jellyfinMediaId;
    if (!jellyfinMediaId) return;
    router.push({
      pathname:
        mediaType === MediaType.MOVIE
          ? "/(auth)/(tabs)/(search)/items/page"
          : "/(auth)/(tabs)/(search)/series/[id]",
      params: { id: jellyfinMediaId },
    });
  }, [details, mediaType, router]);

  const handleCastPress = useCallback(
    (personId: number) => {
      router.push(`/(auth)/jellyseerr/person/${personId}` as any);
    },
    [router],
  );

  const hasJellyfinMedia = !!details?.mediaInfo?.jellyfinMediaId;
  const requestedByName =
    pendingRequest?.requestedBy?.displayName ||
    pendingRequest?.requestedBy?.username ||
    pendingRequest?.requestedBy?.jellyfinUsername ||
    t("jellyseerr.unknown_user");

  if (isLoading || isFetching) {
    return (
      <View
        style={{
          flex: 1,
          backgroundColor: "#000",
          justifyContent: "center",
          alignItems: "center",
        }}
      >
        <Loader />
      </View>
    );
  }

  return (
    <View style={{ flex: 1, backgroundColor: "#000" }}>
      {/* Full-screen backdrop */}
      <View
        style={{
          position: "absolute",
          top: 0,
          left: 0,
          right: 0,
          bottom: 0,
        }}
      >
        {backdropUrl ? (
          <Image
            source={{ uri: backdropUrl }}
            style={{ width: "100%", height: "100%" }}
            contentFit='cover'
            cachePolicy='memory-disk'
            transition={300}
          />
        ) : (
          <View style={{ flex: 1, backgroundColor: "#1a1a1a" }} />
        )}
        {/* Bottom gradient */}
        <LinearGradient
          colors={["transparent", "rgba(0,0,0,0.7)", "rgba(0,0,0,0.95)"]}
          locations={[0, 0.5, 1]}
          style={{
            position: "absolute",
            left: 0,
            right: 0,
            bottom: 0,
            height: "70%",
          }}
        />
        {/* Left gradient */}
        <LinearGradient
          colors={["rgba(0,0,0,0.8)", "transparent"]}
          start={{ x: 0, y: 0 }}
          end={{ x: 0.6, y: 0 }}
          style={{
            position: "absolute",
            left: 0,
            top: 0,
            bottom: 0,
            width: "60%",
          }}
        />
      </View>

      {/* Main content */}
      <ScrollView
        style={{ flex: 1 }}
        contentContainerStyle={{
          paddingTop: insets.top + 140,
          paddingBottom: insets.bottom + 60,
          paddingHorizontal: insets.left + 80,
        }}
        showsVerticalScrollIndicator={false}
      >
        {/* Top section - Poster + Content */}
        <View
          style={{
            flexDirection: "row",
            minHeight: SCREEN_HEIGHT * 0.45,
          }}
        >
          {/* Left side - Poster */}
          <View
            style={{
              width: SCREEN_WIDTH * 0.22,
              marginRight: 50,
            }}
          >
            <View
              style={{
                aspectRatio: 2 / 3,
                borderRadius: 16,
                overflow: "hidden",
                shadowColor: "#000",
                shadowOffset: { width: 0, height: 10 },
                shadowOpacity: 0.5,
                shadowRadius: 20,
              }}
            >
              {posterUrl ? (
                <Image
                  source={{ uri: posterUrl }}
                  style={{ width: "100%", height: "100%" }}
                  contentFit='cover'
                  cachePolicy='memory-disk'
                />
              ) : (
                <View
                  style={{
                    flex: 1,
                    backgroundColor: "rgba(255,255,255,0.1)",
                    justifyContent: "center",
                    alignItems: "center",
                  }}
                >
                  <Ionicons
                    name='image-outline'
                    size={48}
                    color='rgba(255,255,255,0.3)'
                  />
                </View>
              )}
            </View>
          </View>

          {/* Right side - Content */}
          <View style={{ flex: 1, justifyContent: "center" }}>
            {/* Ratings */}
            {details && (
              <JellyserrRatings
                result={
                  details as MovieDetails | TvDetails | MovieResult | TvResult
                }
              />
            )}

            {/* Title */}
            <Text
              style={{
                fontSize: typography.display,
                fontWeight: "bold",
                color: "#FFFFFF",
                marginTop: 8,
                marginBottom: 12,
              }}
              numberOfLines={2}
            >
              {mediaTitle}
            </Text>

            {/* Year */}
            <Text
              style={{
                fontSize: typography.body,
                color: "rgba(255,255,255,0.7)",
                marginBottom: 16,
              }}
            >
              {releaseYear}
            </Text>

            {/* Genres */}
            {details?.genres && details.genres.length > 0 && (
              <View style={{ marginBottom: 24 }}>
                <GenreTags genres={details.genres.map((g) => g.name)} />
              </View>
            )}

            {/* Overview */}
            {(details?.overview || result.overview) && (
              <BlurView
                intensity={10}
                tint='light'
                style={{
                  borderRadius: 8,
                  overflow: "hidden",
                  maxWidth: SCREEN_WIDTH * 0.45,
                  marginBottom: 32,
                }}
              >
                <View
                  style={{
                    padding: 16,
                    backgroundColor: "rgba(0,0,0,0.3)",
                  }}
                >
                  <Text
                    style={{
                      fontSize: typography.body,
                      color: "#E5E7EB",
                      lineHeight: 32,
                    }}
                    numberOfLines={4}
                  >
                    {details?.overview || result.overview}
                  </Text>
                </View>
              </BlurView>
            )}

            {/* Action buttons */}
            <View
              style={{
                flexDirection: "row",
                gap: 16,
                marginBottom: 24,
              }}
            >
              {hasJellyfinMedia && (
                <TVButton
                  onPress={handlePlay}
                  hasTVPreferredFocus
                  variant='primary'
                  refSetter={setPlayButtonRef}
                >
                  <Ionicons
                    name='play'
                    size={28}
                    color='#000000'
                    style={{ marginRight: 10 }}
                  />
                  <Text
                    style={{
                      fontSize: typography.callout,
                      fontWeight: "bold",
                      color: "#000000",
                    }}
                  >
                    {t("common.play")}
                  </Text>
                </TVButton>
              )}

              {/* Request button - only show for movies, TV series use Request All + season cards */}
              {canRequest && mediaType === MediaType.MOVIE && (
                <TVButton
                  onPress={handleRequest}
                  variant='secondary'
                  hasTVPreferredFocus={!hasJellyfinMedia}
                  refSetter={!hasJellyfinMedia ? setPlayButtonRef : undefined}
                  scaleAmount={1.01}
                >
                  <Ionicons
                    name='add'
                    size={24}
                    color='#FFFFFF'
                    style={{ marginRight: 8 }}
                  />
                  <Text
                    style={{
                      fontSize: typography.callout,
                      fontWeight: "bold",
                      color: "#FFFFFF",
                    }}
                  >
                    {t("jellyseerr.request_button")}
                  </Text>
                </TVButton>
              )}

              {/* Request All button for TV series */}
              {mediaType === MediaType.TV &&
                seasons.filter((s) => s.seasonNumber !== 0).length > 0 &&
                hasRequestableSeasons && (
                  <TVButton
                    onPress={handleRequestAll}
                    variant='secondary'
                    hasTVPreferredFocus={!hasJellyfinMedia}
                    refSetter={!hasJellyfinMedia ? setPlayButtonRef : undefined}
                  >
                    <View
                      style={{
                        height: 40,
                        flexDirection: "row",
                        alignItems: "center",
                      }}
                    >
                      <Ionicons
                        name='bag-add'
                        size={20}
                        color='#FFFFFF'
                        style={{ marginRight: 8 }}
                      />
                      <Text
                        style={{
                          fontSize: typography.callout,
                          fontWeight: "600",
                          color: "#FFFFFF",
                        }}
                      >
                        {t("jellyseerr.request_all")}
                      </Text>
                    </View>
                  </TVButton>
                )}

              {/* Request Seasons button for TV series */}
              {mediaType === MediaType.TV &&
                seasons.filter((s) => s.seasonNumber !== 0).length > 0 &&
                hasRequestableSeasons && (
                  <TVButton
                    onPress={handleOpenSeasonSelectModal}
                    variant='secondary'
                  >
                    <View
                      style={{
                        height: 40,
                        flexDirection: "row",
                        alignItems: "center",
                      }}
                    >
                      <Ionicons
                        name='list'
                        size={20}
                        color='#FFFFFF'
                        style={{ marginRight: 8 }}
                      />
                      <Text
                        style={{
                          fontSize: typography.callout,
                          fontWeight: "600",
                          color: "#FFFFFF",
                        }}
                      >
                        {t("jellyseerr.request_seasons")}
                      </Text>
                    </View>
                  </TVButton>
                )}
            </View>

            {/* Approve/Decline for managers */}
            {canManageRequests && pendingRequest && (
              <View style={{ marginBottom: 24 }}>
                <View
                  style={{
                    flexDirection: "row",
                    alignItems: "center",
                    marginBottom: 12,
                  }}
                >
                  <Ionicons name='person-outline' size={18} color='#9CA3AF' />
                  <Text
                    style={{
                      fontSize: typography.callout,
                      color: "#9CA3AF",
                      marginLeft: 8,
                    }}
                  >
                    {t("jellyseerr.requested_by", { user: requestedByName })}
                  </Text>
                </View>

                <View style={{ flexDirection: "row", gap: 16 }}>
                  <TVButton onPress={handleApproveRequest} variant='secondary'>
                    <Ionicons
                      name='checkmark'
                      size={22}
                      color='#FFFFFF'
                      style={{ marginRight: 8 }}
                    />
                    <Text
                      style={{
                        fontSize: typography.callout,
                        fontWeight: "600",
                        color: "#FFFFFF",
                      }}
                    >
                      {t("jellyseerr.approve")}
                    </Text>
                  </TVButton>

                  <TVButton onPress={handleDeclineRequest} variant='secondary'>
                    <Ionicons
                      name='close'
                      size={22}
                      color='#FFFFFF'
                      style={{ marginRight: 8 }}
                    />
                    <Text
                      style={{
                        fontSize: typography.callout,
                        fontWeight: "600",
                        color: "#FFFFFF",
                      }}
                    >
                      {t("jellyseerr.decline")}
                    </Text>
                  </TVButton>
                </View>
              </View>
            )}
          </View>
        </View>

        {/* Cast section */}
        {cast.length > 0 && jellyseerrApi && (
          <View style={{ marginTop: 24 }}>
            <Text
              style={{
                fontSize: typography.heading,
                fontWeight: "bold",
                color: "#FFFFFF",
                marginBottom: 16,
              }}
            >
              {t("jellyseerr.cast")}
            </Text>

            {/* Focus guides for bidirectional navigation - stacked together */}
            {/* Downward: action buttons → first cast card */}
            {firstCastCardRef && (
              <TVFocusGuideView
                destinations={[firstCastCardRef]}
                style={{
                  height: 1,
                  width: SCREEN_WIDTH,
                  marginLeft: -(insets.left + 80),
                }}
              />
            )}
            {/* Upward: cast → action buttons */}
            {playButtonRef && (
              <TVFocusGuideView
                destinations={[playButtonRef]}
                style={{
                  height: 1,
                  width: SCREEN_WIDTH,
                  marginLeft: -(insets.left + 80),
                }}
              />
            )}

            <ScrollView
              horizontal
              showsHorizontalScrollIndicator={false}
              style={{ overflow: "visible" }}
              contentContainerStyle={{
                paddingVertical: 16,
                gap: 28,
              }}
            >
              {cast.map((person, index) => (
                <TVCastCard
                  key={person.id}
                  person={person}
                  imageProxy={(path, size) =>
                    jellyseerrApi.imageProxy(path, size || "w185")
                  }
                  onPress={() => handleCastPress(person.id)}
                  refSetter={index === 0 ? setFirstCastCardRef : undefined}
                />
              ))}
            </ScrollView>
          </View>
        )}
      </ScrollView>
    </View>
  );
};
