const { SlashCommandBuilder, EmbedBuilder } = require("discord.js");
const { getServerMode, EMBED_COLORS } = require("../utils/modeHelper");
const { getStandaloneLeaderboard, calculateLevel } = require("../utils/standaloneXp");

module.exports = {
  data: new SlashCommandBuilder()
    .setName("leaderboard")
    .setDescription("View the top contributors")
    .addStringOption((option) =>
      option
        .setName("category")
        .setDescription("Leaderboard category")
        .setRequired(false)
        .addChoices(
          { name: "XP Leaders (All-Time)", value: "xp" },
          { name: "This Week", value: "weekly" },
          { name: "This Month", value: "monthly" },
          { name: "Most Active (Posts)", value: "posts" },
          { name: "Most Liked", value: "likes" },
          { name: "Top Creators", value: "creators" }
        )
    ),

  async execute(interaction, supabase) {
    if (!supabase) {
      return interaction.reply({ content: "This feature requires Supabase to be configured.", ephemeral: true });
    }
    await interaction.deferReply();

    try {
      const mode = await getServerMode(supabase, interaction.guildId);
      const category = interaction.options.getString("category") || "xp";

      if (mode === 'standalone') {
        return handleStandaloneLeaderboard(interaction, supabase, category);
      } else {
        return handleFederatedLeaderboard(interaction, supabase, category);
      }
    } catch (error) {
      console.error("Leaderboard command error:", error);
      const embed = new EmbedBuilder()
        .setColor(0xff0000)
        .setTitle("Error")
        .setDescription("Failed to fetch leaderboard. Please try again.");

      await interaction.editReply({ embeds: [embed] });
    }
  },
};

async function handleStandaloneLeaderboard(interaction, supabase, category) {
  const guildId = interaction.guildId;

  if (category !== 'xp' && category !== 'weekly' && category !== 'monthly') {
    return interaction.editReply({
      embeds: [
        new EmbedBuilder()
          .setColor(EMBED_COLORS.standalone)
          .setTitle("🏠 Standalone Mode")
          .setDescription("This leaderboard category is only available in Federation mode.\n\nIn Standalone mode, only XP, Weekly, and Monthly leaderboards are available.")
      ]
    });
  }

  let leaderboardData = [];
  let title = "";
  let color = EMBED_COLORS.standalone;

  if (category === 'xp') {
    title = "Server XP Leaderboard";
    const data = await getStandaloneLeaderboard(supabase, guildId, 10);

    for (const entry of data) {
      const level = calculateLevel(entry.xp || 0, 'normal');
      let displayName = entry.username || 'Unknown';
      
      try {
        const member = await interaction.guild.members.fetch(entry.discord_id).catch(() => null);
        if (member) displayName = member.displayName;
      } catch (e) {}

      leaderboardData.push({
        name: displayName,
        value: `Level ${level} • ${(entry.xp || 0).toLocaleString()} XP`,
        xp: entry.xp || 0
      });
    }
  } else if (category === 'weekly' || category === 'monthly') {
    const periodType = category === 'weekly' ? 'week' : 'month';
    title = category === 'weekly' ? 'Weekly XP Leaderboard' : 'Monthly XP Leaderboard';

    const now = new Date();
    let periodStart;
    
    if (category === 'weekly') {
      const dayOfWeek = now.getDay();
      const diffToMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
      periodStart = new Date(now);
      periodStart.setDate(now.getDate() - diffToMonday);
      periodStart.setHours(0, 0, 0, 0);
    } else {
      periodStart = new Date(now.getFullYear(), now.getMonth(), 1);
    }

    const periodStartStr = periodStart.toISOString().split('T')[0];

    const { data: periodicData } = await supabase
      .from("periodic_xp")
      .select("discord_id, weekly_xp, monthly_xp")
      .eq("guild_id", guildId)
      .eq("period_type", periodType)
      .eq("period_start", periodStartStr);

    const aggregated = {};
    for (const entry of periodicData || []) {
      if (!aggregated[entry.discord_id]) {
        aggregated[entry.discord_id] = 0;
      }
      aggregated[entry.discord_id] += category === 'weekly' ? (entry.weekly_xp || 0) : (entry.monthly_xp || 0);
    }

    const sortedUsers = Object.entries(aggregated)
      .sort(([, a], [, b]) => b - a)
      .slice(0, 10);

    for (const [discordId, xp] of sortedUsers) {
      let displayName = 'Unknown User';
      try {
        const member = await interaction.guild.members.fetch(discordId).catch(() => null);
        if (member) displayName = member.displayName;
      } catch (e) {}

      leaderboardData.push({
        name: displayName,
        value: `${xp.toLocaleString()} XP`,
        xp: xp
      });
    }
  }

  const medals = ['1.', '2.', '3.'];

  const description = leaderboardData.length > 0
    ? leaderboardData
        .map((user, index) => {
          const medal = index < 3 ? medals[index] : `${index + 1}.`;
          return `**${medal}** ${user.name}\n    ${user.value}`;
        })
        .join("\n\n")
    : "No data available yet. Be the first to contribute!";

  const embed = new EmbedBuilder()
    .setColor(color)
    .setTitle(`🏠 ${title}`)
    .setDescription(description)
    .setThumbnail(interaction.guild.iconURL({ size: 128 }))
    .setFooter({ 
      text: `${interaction.guild.name} • Standalone Mode`,
      iconURL: interaction.guild.iconURL({ size: 32 })
    })
    .setTimestamp();

  if (leaderboardData.length > 0) {
    embed.addFields({
      name: 'Showing',
      value: `Top ${leaderboardData.length} contributors`,
      inline: true
    });
  }

  await interaction.editReply({ embeds: [embed] });
}

async function handleFederatedLeaderboard(interaction, supabase, category) {
  const guildId = interaction.guildId;

  let leaderboardData = [];
  let title = "";
  let emoji = "";
  let color = 0x7c3aed;
  let periodInfo = "";

  if (category === "weekly") {
    title = "Weekly XP Leaderboard";
    emoji = "";
    color = 0x22c55e;
    
    const now = new Date();
    const dayOfWeek = now.getDay();
    const diffToMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
    const weekStart = new Date(now);
    weekStart.setDate(now.getDate() - diffToMonday);
    weekStart.setHours(0, 0, 0, 0);
    const weekStartStr = weekStart.toISOString().split('T')[0];
    
    const weekEnd = new Date(weekStart);
    weekEnd.setDate(weekStart.getDate() + 6);
    periodInfo = `${weekStart.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })} - ${weekEnd.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}`;

    const { data: periodicData } = await supabase
      .from("periodic_xp")
      .select("discord_id, weekly_xp, weekly_messages")
      .eq("guild_id", guildId)
      .eq("period_type", "week")
      .eq("period_start", weekStartStr);

    const aggregated = {};
    for (const entry of periodicData || []) {
      if (!aggregated[entry.discord_id]) {
        aggregated[entry.discord_id] = { xp: 0, messages: 0 };
      }
      aggregated[entry.discord_id].xp += entry.weekly_xp || 0;
      aggregated[entry.discord_id].messages += entry.weekly_messages || 0;
    }

    const sortedUsers = Object.entries(aggregated)
      .sort(([, a], [, b]) => b.xp - a.xp)
      .slice(0, 10);

    for (const [discordId, data] of sortedUsers) {
      try {
        const member = await interaction.guild.members.fetch(discordId).catch(() => null);
        const displayName = member?.displayName || member?.user?.username || "Unknown User";
        leaderboardData.push({
          name: displayName,
          value: `${data.xp.toLocaleString()} XP • ${data.messages} msgs`,
          xp: data.xp
        });
      } catch (e) {
        continue;
      }
    }
  } else if (category === "monthly") {
    title = "Monthly XP Leaderboard";
    emoji = "";
    color = 0x3b82f6;
    
    const now = new Date();
    const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
    const monthStartStr = monthStart.toISOString().split('T')[0];
    
    periodInfo = monthStart.toLocaleDateString('en-US', { month: 'long', year: 'numeric' });

    const { data: periodicData } = await supabase
      .from("periodic_xp")
      .select("discord_id, monthly_xp, monthly_messages")
      .eq("guild_id", guildId)
      .eq("period_type", "month")
      .eq("period_start", monthStartStr);

    const aggregated = {};
    for (const entry of periodicData || []) {
      if (!aggregated[entry.discord_id]) {
        aggregated[entry.discord_id] = { xp: 0, messages: 0 };
      }
      aggregated[entry.discord_id].xp += entry.monthly_xp || 0;
      aggregated[entry.discord_id].messages += entry.monthly_messages || 0;
    }

    const sortedUsers = Object.entries(aggregated)
      .sort(([, a], [, b]) => b.xp - a.xp)
      .slice(0, 10);

    for (const [discordId, data] of sortedUsers) {
      try {
        const member = await interaction.guild.members.fetch(discordId).catch(() => null);
        const displayName = member?.displayName || member?.user?.username || "Unknown User";
        leaderboardData.push({
          name: displayName,
          value: `${data.xp.toLocaleString()} XP • ${data.messages} msgs`,
          xp: data.xp
        });
      } catch (e) {
        continue;
      }
    }
  } else if (category === "xp") {
    title = "XP Leaderboard (All-Time)";
    emoji = "";
    color = 0xfbbf24;

    const { data: profiles } = await supabase
      .from("user_profiles")
      .select("id, username, full_name, avatar_url, xp")
      .not("xp", "is", null)
      .order("xp", { ascending: false })
      .limit(10);

    for (const profile of profiles || []) {
      const level = Math.floor(Math.sqrt((profile.xp || 0) / 100));
      leaderboardData.push({
        name: profile.full_name || profile.username || "Anonymous",
        value: `Level ${level} • ${(profile.xp || 0).toLocaleString()} XP`,
        username: profile.username,
        xp: profile.xp || 0
      });
    }
  } else if (category === "posts") {
    title = "Most Active Posters";
    emoji = "";
    color = 0xef4444;

    const { data: posts } = await supabase
      .from("community_posts")
      .select("user_id")
      .not("user_id", "is", null);

    const postCounts = {};
    posts?.forEach((post) => {
      postCounts[post.user_id] = (postCounts[post.user_id] || 0) + 1;
    });

    const sortedUsers = Object.entries(postCounts)
      .sort(([, a], [, b]) => b - a)
      .slice(0, 10);

    for (const [userId, count] of sortedUsers) {
      const { data: profile } = await supabase
        .from("user_profiles")
        .select("username, full_name, avatar_url")
        .eq("id", userId)
        .maybeSingle();

      if (profile) {
        leaderboardData.push({
          name: profile.full_name || profile.username || "Anonymous",
          value: `${count} posts`,
          username: profile.username,
        });
      }
    }
  } else if (category === "likes") {
    title = "Most Liked Users";
    emoji = "";
    color = 0xec4899;

    const { data: posts } = await supabase
      .from("community_posts")
      .select("user_id, likes_count")
      .not("user_id", "is", null)
      .order("likes_count", { ascending: false });

    const likeCounts = {};
    posts?.forEach((post) => {
      likeCounts[post.user_id] =
        (likeCounts[post.user_id] || 0) + (post.likes_count || 0);
    });

    const sortedUsers = Object.entries(likeCounts)
      .sort(([, a], [, b]) => b - a)
      .slice(0, 10);

    for (const [userId, count] of sortedUsers) {
      const { data: profile } = await supabase
        .from("user_profiles")
        .select("username, full_name, avatar_url")
        .eq("id", userId)
        .maybeSingle();

      if (profile) {
        leaderboardData.push({
          name: profile.full_name || profile.username || "Anonymous",
          value: `${count.toLocaleString()} likes`,
          username: profile.username,
        });
      }
    }
  } else if (category === "creators") {
    title = "Top Creators";
    emoji = "";
    color = 0x8b5cf6;

    const { data: creators } = await supabase
      .from("aethex_creators")
      .select("user_id, total_projects, verified, featured")
      .order("total_projects", { ascending: false })
      .limit(10);

    for (const creator of creators || []) {
      const { data: profile } = await supabase
        .from("user_profiles")
        .select("username, full_name, avatar_url")
        .eq("id", creator.user_id)
        .maybeSingle();

      if (profile) {
        const badges = [];
        if (creator.verified) badges.push("Verified");
        if (creator.featured) badges.push("Featured");

        leaderboardData.push({
          name: profile.full_name || profile.username || "Anonymous",
          value: `${creator.total_projects || 0} projects ${badges.join(" ")}`,
          username: profile.username,
        });
      }
    }
  }

  const medals = ['1.', '2.', '3.'];

  const description = leaderboardData.length > 0
    ? leaderboardData
        .map((user, index) => {
          const medal = index < 3 ? medals[index] : `${index + 1}.`;
          return `**${medal}** ${user.name}\n    ${user.value}`;
        })
        .join("\n\n")
    : "No data available yet. Be the first to contribute!";

  const embed = new EmbedBuilder()
    .setColor(color)
    .setTitle(`🌐 ${title}`)
    .setDescription(description)
    .setThumbnail(interaction.guild.iconURL({ size: 128 }))
    .setFooter({ 
      text: `${interaction.guild.name} • Federation Mode`,
      iconURL: interaction.guild.iconURL({ size: 32 })
    })
    .setTimestamp();

  if (periodInfo) {
    embed.addFields({
      name: 'Period',
      value: periodInfo,
      inline: true
    });
  }

  if (leaderboardData.length > 0) {
    embed.addFields({
      name: 'Showing',
      value: `Top ${leaderboardData.length} contributors`,
      inline: true
    });
  }

  if (category === "weekly" || category === "monthly") {
    embed.addFields({
      name: 'Tip',
      value: 'Leaderboards reset automatically at the start of each period!',
      inline: false
    });
  }

  await interaction.editReply({ embeds: [embed] });
}
