import native from "@/utils/profiles/native";
import { Api } from "@jellyfin/sdk";
import {
  BaseItemDto,
  MediaSourceInfo,
  PlaybackInfoResponse,
} from "@jellyfin/sdk/lib/generated-client/models";
import { getMediaInfoApi } from "@jellyfin/sdk/lib/utils/api";

export const getStreamUrl = async ({
  api,
  item,
  userId,
  startTimeTicks = 0,
  maxStreamingBitrate,
  sessionData,
  deviceProfile = native,
  audioStreamIndex = 0,
  subtitleStreamIndex = undefined,
  mediaSourceId,
}: {
  api: Api | null | undefined;
  item: BaseItemDto | null | undefined;
  userId: string | null | undefined;
  startTimeTicks: number;
  maxStreamingBitrate?: number;
  sessionData?: PlaybackInfoResponse | null;
  deviceProfile?: any;
  audioStreamIndex?: number;
  subtitleStreamIndex?: number;
  height?: number;
  mediaSourceId?: string | null;
}): Promise<{
  url: string | null;
  sessionId: string | null;
  mediaSource: MediaSourceInfo | undefined;
} | null> => {
  if (!api || !userId || !item?.Id) {
    return null;
  }

  let mediaSource: MediaSourceInfo | undefined;
  let sessionId: string | null | undefined;

  if (item.Type === "Program") {
    console.log("Item is of type program...");
    const res0 = await getMediaInfoApi(api).getPlaybackInfo(
      {
        userId,
        itemId: item.ChannelId!,
      },
      {
        method: "POST",
        params: {
          startTimeTicks: 0,
          isPlayback: true,
          autoOpenLiveStream: true,
          maxStreamingBitrate,
          audioStreamIndex,
        },
        data: {
          deviceProfile,
        },
      }
    );
    const transcodeUrl = res0.data.MediaSources?.[0].TranscodingUrl;
    sessionId = res0.data.PlaySessionId || null;

    if (transcodeUrl) {
      return {
        url: `${api.basePath}${transcodeUrl}`,
        sessionId,
        mediaSource: res0.data.MediaSources?.[0],
      };
    }
  }

  const itemId = item.Id;

  const res2 = await getMediaInfoApi(api).getPlaybackInfo(
    {
      userId,
      itemId: item.Id!,
    },
    {
      method: "POST",
      data: {
        deviceProfile,
        userId,
        maxStreamingBitrate,
        startTimeTicks,
        autoOpenLiveStream: true,
        mediaSourceId,
        audioStreamIndex,
        subtitleStreamIndex,
      },
    }
  );

  if (res2.status !== 200) {
    console.error("Error getting playback info:", res2.status, res2.statusText);
  }

  sessionId = res2.data.PlaySessionId || null;

  mediaSource = res2.data.MediaSources?.find(
    (source: MediaSourceInfo) => source.Id === mediaSourceId
  );

  if (item.MediaType === "Video") {
    if (mediaSource?.TranscodingUrl) {
      const urlObj = new URL(api.basePath + mediaSource?.TranscodingUrl); // Create a URL object

      // If there is no subtitle stream index, add it to the URL.
      if (subtitleStreamIndex == -1) {
        urlObj.searchParams.set("SubtitleMethod", "Hls");
      }

      // Add 'SubtitleMethod=Hls' if it doesn't exist
      if (!urlObj.searchParams.has("SubtitleMethod")) {
        urlObj.searchParams.append("SubtitleMethod", "Hls");
      }
      // Get the updated URL
      const transcodeUrl = urlObj.toString();

      console.log("Video has transcoding URL:", `${transcodeUrl}`);
      return {
        url: transcodeUrl,
        sessionId: sessionId,
        mediaSource,
      };
    }

    if (mediaSource?.SupportsDirectPlay) {
      const searchParams = new URLSearchParams({
        playSessionId: sessionData?.PlaySessionId || "",
        mediaSourceId: mediaSource?.Id || "",
        static: "true",
        subtitleStreamIndex: subtitleStreamIndex?.toString() || "",
        audioStreamIndex: audioStreamIndex?.toString() || "",
        deviceId: api.deviceInfo.id,
        api_key: api.accessToken,
        startTimeTicks: startTimeTicks.toString(),
        maxStreamingBitrate: maxStreamingBitrate?.toString() || "",
        userId: userId || "",
      });

      const directPlayUrl = `${
        api.basePath
      }/Videos/${itemId}/stream.mp4?${searchParams.toString()}`;

      console.log("Video is being direct played:", directPlayUrl);

      return {
        url: directPlayUrl,
        sessionId: sessionId,
        mediaSource,
      };
    }
  }

  if (item.MediaType === "Audio") {
    if (mediaSource?.TranscodingUrl) {
      return {
        url: `${api.basePath}${mediaSource.TranscodingUrl}`,
        sessionId,
        mediaSource,
      };
    }

    const searchParams = new URLSearchParams({
      UserId: userId,
      DeviceId: api.deviceInfo.id,
      MaxStreamingBitrate: "140000000",
      Container:
        "opus,webm|opus,mp3,aac,m4a|aac,m4b|aac,flac,webma,webm|webma,wav,ogg",
      TranscodingContainer: "mp4",
      TranscodingProtocol: "hls",
      AudioCodec: "aac",
      api_key: api.accessToken,
      PlaySessionId: sessionData?.PlaySessionId || "",
      StartTimeTicks: "0",
      EnableRedirection: "true",
      EnableRemoteMedia: "false",
    });
    return {
      url: `${
        api.basePath
      }/Audio/${itemId}/universal?${searchParams.toString()}`,
      sessionId,
      mediaSource,
    };
  }

  throw new Error("Unsupported media type");
};
