import { AudioTrackSelector } from "@/components/AudioTrackSelector";
import { Bitrate, BitrateSelector } from "@/components/BitrateSelector";
import { DownloadItem } from "@/components/DownloadItem";
import { OverviewText } from "@/components/OverviewText";
import { ParallaxScrollView } from "@/components/ParallaxPage";
import { PlayButton } from "@/components/PlayButton";
import { PlayedStatus } from "@/components/PlayedStatus";
import { SimilarItems } from "@/components/SimilarItems";
import { SubtitleTrackSelector } from "@/components/SubtitleTrackSelector";
import { ItemImage } from "@/components/common/ItemImage";
import { CastAndCrew } from "@/components/series/CastAndCrew";
import { CurrentSeries } from "@/components/series/CurrentSeries";
import { SeasonEpisodesCarousel } from "@/components/series/SeasonEpisodesCarousel";
import { useImageColors } from "@/hooks/useImageColors";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import { useSettings } from "@/utils/atoms/settings";
import { getLogoImageUrlById } from "@/utils/jellyfin/image/getLogoImageUrlById";
import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
import { chromecastProfile } from "@/utils/profiles/chromecast";
import iosFmp4 from "@/utils/profiles/iosFmp4";
import native from "@/utils/profiles/native";
import old from "@/utils/profiles/old";
import {
  BaseItemDto,
  MediaSourceInfo,
} from "@jellyfin/sdk/lib/generated-client/models";
import { getMediaInfoApi } from "@jellyfin/sdk/lib/utils/api";
import { useQuery } from "@tanstack/react-query";
import { Image } from "expo-image";
import { useNavigation } from "expo-router";
import * as ScreenOrientation from "expo-screen-orientation";
import { useAtom } from "jotai";
import React, { useEffect, useMemo, useRef, useState } from "react";
import { View } from "react-native";
import { useCastDevice } from "react-native-google-cast";
import Animated from "react-native-reanimated";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { Chromecast } from "./Chromecast";
import { ItemHeader } from "./ItemHeader";
import { MediaSourceSelector } from "./MediaSourceSelector";
import { MoreMoviesWithActor } from "./MoreMoviesWithActor";

export const ItemContent: React.FC<{ item: BaseItemDto }> = React.memo(
  ({ item }) => {
    const [api] = useAtom(apiAtom);
    const [user] = useAtom(userAtom);

    const castDevice = useCastDevice();
    const navigation = useNavigation();
    const [settings] = useSettings();
    const [selectedMediaSource, setSelectedMediaSource] =
      useState<MediaSourceInfo | null>(null);
    const [selectedAudioStream, setSelectedAudioStream] = useState<number>(-1);
    const [selectedSubtitleStream, setSelectedSubtitleStream] =
      useState<number>(-1);
    const [maxBitrate, setMaxBitrate] = useState<Bitrate>({
      key: "Max",
      value: undefined,
    });

    const [loadingLogo, setLoadingLogo] = useState(true);

    const [orientation, setOrientation] = useState(
      ScreenOrientation.Orientation.PORTRAIT_UP
    );

    useEffect(() => {
      const subscription = ScreenOrientation.addOrientationChangeListener(
        (event) => {
          setOrientation(event.orientationInfo.orientation);
        }
      );

      ScreenOrientation.getOrientationAsync().then((initialOrientation) => {
        setOrientation(initialOrientation);
      });

      return () => {
        ScreenOrientation.removeOrientationChangeListener(subscription);
      };
    }, []);

    const headerHeightRef = useRef(400);

    useImageColors({ item });

    useEffect(() => {
      navigation.setOptions({
        headerRight: () =>
          item && (
            <View className="flex flex-row items-center space-x-2">
              <Chromecast background="blur" width={22} height={22} />
              {item.Type !== "Program" && (
                <>
                  <DownloadItem item={item} />
                  <PlayedStatus item={item} />
                </>
              )}
            </View>
          ),
      });
    }, [item]);

    useEffect(() => {
      if (orientation !== ScreenOrientation.Orientation.PORTRAIT_UP) {
        headerHeightRef.current = 230;
        return;
      }
      if (item.Type === "Episode") headerHeightRef.current = 400;
      else if (item.Type === "Movie") headerHeightRef.current = 500;
      else headerHeightRef.current = 400;
    }, [item, orientation]);

    const { data: sessionData } = useQuery({
      queryKey: ["sessionData", item.Id],
      queryFn: async () => {
        if (!api || !user?.Id || !item.Id) {
          return null;
        }
        const playbackData = await getMediaInfoApi(api!).getPlaybackInfo(
          {
            itemId: item.Id,
            userId: user?.Id,
          },
          {
            method: "POST",
          }
        );

        return playbackData.data;
      },
      enabled: !!item.Id && !!api && !!user?.Id,
      staleTime: 0,
    });

    const { data: playbackUrl } = useQuery({
      queryKey: [
        "playbackUrl",
        item.Id,
        maxBitrate,
        castDevice?.deviceId,
        selectedMediaSource?.Id,
        selectedAudioStream,
        selectedSubtitleStream,
        settings,
        sessionData?.PlaySessionId,
      ],
      queryFn: async () => {
        if (!api || !user?.Id) {
          return null;
        }

        if (
          item.Type !== "Program" &&
          (!sessionData || !selectedMediaSource?.Id)
        ) {
          return null;
        }

        let deviceProfile: any = iosFmp4;

        if (castDevice?.deviceId) {
          deviceProfile = chromecastProfile;
        } else if (settings?.deviceProfile === "Native") {
          deviceProfile = native;
        } else if (settings?.deviceProfile === "Old") {
          deviceProfile = old;
        }

        console.log("playbackUrl...");

        const url = await getStreamUrl({
          api,
          userId: user.Id,
          item,
          startTimeTicks: item.UserData?.PlaybackPositionTicks || 0,
          maxStreamingBitrate: maxBitrate.value,
          sessionData,
          deviceProfile,
          audioStreamIndex: selectedAudioStream,
          subtitleStreamIndex: selectedSubtitleStream,
          forceDirectPlay: settings?.forceDirectPlay,
          height: maxBitrate.height,
          mediaSourceId: selectedMediaSource?.Id,
        });

        console.info("Stream URL:", url);

        return url;
      },
      enabled: !!api && !!user?.Id && !!item.Id,
      staleTime: 0,
    });

    const logoUrl = useMemo(() => getLogoImageUrlById({ api, item }), [item]);

    const loading = useMemo(() => {
      return Boolean(logoUrl && loadingLogo);
    }, [loadingLogo, logoUrl]);

    const insets = useSafeAreaInsets();

    return (
      <View
        className="flex-1 relative"
        style={{
          paddingLeft: insets.left,
          paddingRight: insets.right,
        }}
      >
        <ParallaxScrollView
          className={`flex-1 ${loading ? "opacity-0" : "opacity-100"}`}
          headerHeight={headerHeightRef.current}
          headerImage={
            <>
              <Animated.View style={[{ flex: 1 }]}>
                <ItemImage
                  variant={
                    item.Type === "Movie" && logoUrl ? "Backdrop" : "Primary"
                  }
                  item={item}
                  style={{
                    width: "100%",
                    height: "100%",
                  }}
                />
              </Animated.View>
            </>
          }
          logo={
            <>
              {logoUrl ? (
                <Image
                  source={{
                    uri: logoUrl,
                  }}
                  style={{
                    height: 130,
                    width: "100%",
                    resizeMode: "contain",
                  }}
                  onLoad={() => setLoadingLogo(false)}
                  onError={() => setLoadingLogo(false)}
                />
              ) : null}
            </>
          }
        >
          <View className="flex flex-col bg-transparent shrink">
            <View className="flex flex-col px-4 w-full space-y-2 pt-2 mb-2 shrink">
              <ItemHeader item={item} className="mb-4" />
              {item.Type !== "Program" && (
                <View className="flex flex-row items-center justify-start w-full h-16">
                  <BitrateSelector
                    className="mr-1"
                    onChange={(val) => setMaxBitrate(val)}
                    selected={maxBitrate}
                  />
                  <MediaSourceSelector
                    className="mr-1"
                    item={item}
                    onChange={setSelectedMediaSource}
                    selected={selectedMediaSource}
                  />
                  {selectedMediaSource && (
                    <>
                      <AudioTrackSelector
                        className="mr-1"
                        source={selectedMediaSource}
                        onChange={setSelectedAudioStream}
                        selected={selectedAudioStream}
                      />
                      <SubtitleTrackSelector
                        source={selectedMediaSource}
                        onChange={setSelectedSubtitleStream}
                        selected={selectedSubtitleStream}
                      />
                    </>
                  )}
                </View>
              )}

              <PlayButton item={item} url={playbackUrl} className="grow" />
            </View>

            {item.Type === "Episode" && (
              <SeasonEpisodesCarousel item={item} loading={loading} />
            )}

            <OverviewText text={item.Overview} className="px-4 my-4" />
            {item.Type !== "Program" && (
              <>
                <CastAndCrew item={item} className="mb-4" loading={loading} />

                {item.People && item.People.length > 0 && (
                  <View className="mb-4">
                    {item.People.slice(0, 3).map((person) => (
                      <MoreMoviesWithActor
                        currentItem={item}
                        key={person.Id}
                        actorId={person.Id!}
                        className="mb-4"
                      />
                    ))}
                  </View>
                )}

                {item.Type === "Episode" && (
                  <CurrentSeries item={item} className="mb-4" />
                )}

                <SimilarItems itemId={item.Id} />
              </>
            )}

            <View className="h-16"></View>
          </View>
        </ParallaxScrollView>
      </View>
    );
  }
);
