/**
 * YouTube Channel Data
 * Fetches from Indiekit's endpoint-youtube public API
 * Supports single or multiple channels
 */

import EleventyFetch from "@11ty/eleventy-fetch";

const INDIEKIT_URL = process.env.SITE_URL || "https://example.com";

/**
 * Fetch from Indiekit's public YouTube API endpoint
 */
async function fetchFromIndiekit(endpoint) {
  try {
    const url = `${INDIEKIT_URL}/youtubeapi/api/${endpoint}`;
    console.log(`[youtubeChannel] Fetching from Indiekit: ${url}`);
    const data = await EleventyFetch(url, {
      duration: "5m",
      type: "json",
    });
    console.log(`[youtubeChannel] Indiekit ${endpoint} success`);
    return data;
  } catch (error) {
    console.log(
      `[youtubeChannel] Indiekit API unavailable for ${endpoint}: ${error.message}`
    );
    return null;
  }
}

/**
 * Format large numbers with locale separators
 */
function formatNumber(num) {
  if (!num) return "0";
  return new Intl.NumberFormat().format(num);
}

/**
 * Format view count with K/M suffix for compact display
 */
function formatViewCount(num) {
  if (!num) return "0";
  if (num >= 1000000) {
    return (num / 1000000).toFixed(1).replace(/\.0$/, "") + "M";
  }
  if (num >= 1000) {
    return (num / 1000).toFixed(1).replace(/\\.0$/, "") + "K";
  }
  return num.toString();
}

/**
 * Format relative time from ISO date string
 */
function formatRelativeTime(dateString) {
  if (!dateString) return "";
  const date = new Date(dateString);
  const now = new Date();
  const diffMs = now - date;
  const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));

  if (diffDays === 0) return "Today";
  if (diffDays === 1) return "Yesterday";
  if (diffDays < 7) return `${diffDays} days ago`;
  if (diffDays < 30) return `${Math.floor(diffDays / 7)} weeks ago`;
  if (diffDays < 365) return `${Math.floor(diffDays / 30)} months ago`;
  return `${Math.floor(diffDays / 365)} years ago`;
}

/**
 * Format channel data with computed fields
 */
function formatChannel(channel) {
  if (!channel) return null;
  return {
    ...channel,
    subscriberCountFormatted: formatNumber(channel.subscriberCount),
    videoCountFormatted: formatNumber(channel.videoCount),
    viewCountFormatted: formatNumber(channel.viewCount),
    url: `https://www.youtube.com/channel/${channel.id}`,
  };
}

/**
 * Format video data with computed fields
 */
function formatVideo(video) {
  return {
    ...video,
    viewCountFormatted: formatViewCount(video.viewCount),
    relativeTime: formatRelativeTime(video.publishedAt),
  };
}

export default async function () {
  try {
    console.log("[youtubeChannel] Fetching YouTube data...");

    // Fetch all data from Indiekit API
    const [channelData, videosData, liveData] = await Promise.all([
      fetchFromIndiekit("channel"),
      fetchFromIndiekit("videos"),
      fetchFromIndiekit("live"),
    ]);

    // Check if we got data
    const hasData =
      channelData?.channel ||
      channelData?.channels?.length ||
      videosData?.videos?.length;

    if (!hasData) {
      console.log("[youtubeChannel] No data available from Indiekit");
      return {
        channel: null,
        channels: [],
        videos: [],
        videosByChannel: {},
        liveStatus: null,
        liveStatuses: [],
        isMultiChannel: false,
        source: "unavailable",
      };
    }

    console.log("[youtubeChannel] Using Indiekit API data");

    // Determine if multi-channel mode
    const isMultiChannel = !!(channelData?.channels && channelData.channels.length > 1);

    // Format channels
    let channels = [];
    let channel = null;

    if (isMultiChannel) {
      channels = (channelData.channels || []).map(formatChannel).filter(Boolean);
      channel = channels[0] || null;
    } else {
      channel = formatChannel(channelData?.channel);
      channels = channel ? [channel] : [];
    }

    // Format videos
    const videos = (videosData?.videos || []).map(formatVideo);

    // Group videos by channel if multi-channel
    let videosByChannel = {};
    if (isMultiChannel && videosData?.videosByChannel) {
      for (const [channelName, channelVideos] of Object.entries(videosData.videosByChannel)) {
        videosByChannel[channelName] = (channelVideos || []).map(formatVideo);
      }
    } else if (channel) {
      videosByChannel[channel.configName || channel.title] = videos;
    }

    // Format live status
    let liveStatus = null;
    let liveStatuses = [];

    if (liveData) {
      if (isMultiChannel && liveData.liveStatuses) {
        liveStatuses = liveData.liveStatuses;
        // Find first live or upcoming
        const live = liveStatuses.find((s) => s.isLive);
        const upcoming = liveStatuses.find((s) => s.isUpcoming && !s.isLive);
        liveStatus = {
          isLive: !!live,
          isUpcoming: !live && !!upcoming,
          stream: live?.stream || upcoming?.stream || null,
        };
      } else {
        liveStatus = {
          isLive: liveData.isLive || false,
          isUpcoming: liveData.isUpcoming || false,
          stream: liveData.stream || null,
        };
        liveStatuses = [{ ...liveStatus, channelConfigName: channel?.configName }];
      }
    }

    return {
      channel,
      channels,
      videos,
      videosByChannel,
      liveStatus,
      liveStatuses,
      isMultiChannel,
      source: "indiekit",
    };
  } catch (error) {
    console.error("[youtubeChannel] Error:", error.message);
    return {
      channel: null,
      channels: [],
      videos: [],
      videosByChannel: {},
      liveStatus: null,
      liveStatuses: [],
      isMultiChannel: false,
      source: "error",
    };
  }
}
