const { SlashCommandBuilder, EmbedBuilder, PermissionFlagsBits } = require('discord.js');

const TRIGGER_TYPES = {
  level: { name: 'Reach Level', description: 'Triggers when user reaches specified level' },
  prestige: { name: 'Reach Prestige', description: 'Triggers when user reaches prestige level' },
  total_xp: { name: 'Total XP Earned', description: 'Triggers when total XP reaches value' },
  messages: { name: 'Messages Sent', description: 'Triggers after sending X messages' },
  reactions_given: { name: 'Reactions Given', description: 'Triggers after giving X reactions' },
  reactions_received: { name: 'Reactions Received', description: 'Triggers after receiving X reactions' },
  voice_minutes: { name: 'Voice Minutes', description: 'Triggers after X minutes in voice' },
  daily_streak: { name: 'Daily Streak', description: 'Triggers at X day claim streak' },
  commands_used: { name: 'Commands Used', description: 'Triggers after using X commands' }
};

module.exports = {
  data: new SlashCommandBuilder()
    .setName('achievements')
    .setDescription('Manage server achievements and badges')
    .addSubcommand(sub =>
      sub.setName('create')
        .setDescription('Create a new achievement')
        .addStringOption(opt =>
          opt.setName('name')
            .setDescription('Achievement name')
            .setRequired(true)
            .setMaxLength(100))
        .addStringOption(opt =>
          opt.setName('trigger')
            .setDescription('What triggers this achievement')
            .setRequired(true)
            .addChoices(
              { name: 'Reach Level', value: 'level' },
              { name: 'Reach Prestige', value: 'prestige' },
              { name: 'Total XP Earned', value: 'total_xp' },
              { name: 'Messages Sent', value: 'messages' },
              { name: 'Reactions Given', value: 'reactions_given' },
              { name: 'Reactions Received', value: 'reactions_received' },
              { name: 'Voice Minutes', value: 'voice_minutes' },
              { name: 'Daily Streak', value: 'daily_streak' },
              { name: 'Commands Used', value: 'commands_used' }
            ))
        .addIntegerOption(opt =>
          opt.setName('value')
            .setDescription('Trigger value (e.g., level 10, 1000 XP)')
            .setRequired(true)
            .setMinValue(1))
        .addStringOption(opt =>
          opt.setName('description')
            .setDescription('Achievement description')
            .setMaxLength(200))
        .addStringOption(opt =>
          opt.setName('icon')
            .setDescription('Emoji icon for the achievement')
            .setMaxLength(50))
        .addIntegerOption(opt =>
          opt.setName('reward_xp')
            .setDescription('XP reward for earning this achievement')
            .setMinValue(0)
            .setMaxValue(10000))
        .addRoleOption(opt =>
          opt.setName('reward_role')
            .setDescription('Role to award when achievement is earned'))
        .addBooleanOption(opt =>
          opt.setName('hidden')
            .setDescription('Hide this achievement until earned')))
    .addSubcommand(sub =>
      sub.setName('delete')
        .setDescription('Delete an achievement')
        .addStringOption(opt =>
          opt.setName('name')
            .setDescription('Achievement name to delete')
            .setRequired(true)
            .setAutocomplete(true)))
    .addSubcommand(sub =>
      sub.setName('list')
        .setDescription('List all server achievements'))
    .addSubcommand(sub =>
      sub.setName('view')
        .setDescription('View your earned achievements')
        .addUserOption(opt =>
          opt.setName('user')
            .setDescription('User to view achievements for')))
    .addSubcommand(sub =>
      sub.setName('grant')
        .setDescription('Manually grant an achievement to a user')
        .addUserOption(opt =>
          opt.setName('user')
            .setDescription('User to grant achievement to')
            .setRequired(true))
        .addStringOption(opt =>
          opt.setName('name')
            .setDescription('Achievement name')
            .setRequired(true)
            .setAutocomplete(true)))
    .addSubcommand(sub =>
      sub.setName('revoke')
        .setDescription('Revoke an achievement from a user')
        .addUserOption(opt =>
          opt.setName('user')
            .setDescription('User to revoke achievement from')
            .setRequired(true))
        .addStringOption(opt =>
          opt.setName('name')
            .setDescription('Achievement name')
            .setRequired(true)
            .setAutocomplete(true))),

  async autocomplete(interaction, supabase) {
    if (!supabase) return;
    
    const focused = interaction.options.getFocused().toLowerCase();
    const guildId = interaction.guildId;
    
    try {
      const { data: achievements } = await supabase
        .from('achievements')
        .select('name')
        .eq('guild_id', guildId);
      
      const filtered = (achievements || [])
        .filter(a => a.name.toLowerCase().includes(focused))
        .slice(0, 25)
        .map(a => ({ name: a.name, value: a.name }));
      
      await interaction.respond(filtered);
    } catch (e) {
      await interaction.respond([]);
    }
  },

  async execute(interaction, client, supabase) {
    if (!supabase) {
      return interaction.reply({
        content: 'Database not configured. Achievements require Supabase.',
        ephemeral: true
      });
    }

    const guildId = interaction.guildId;
    const sub = interaction.options.getSubcommand();

    switch (sub) {
      case 'create':
        return handleCreate(interaction, supabase, guildId);
      case 'delete':
        return handleDelete(interaction, supabase, guildId);
      case 'list':
        return handleList(interaction, supabase, guildId);
      case 'view':
        return handleView(interaction, supabase, guildId);
      case 'grant':
        return handleGrant(interaction, supabase, guildId, client);
      case 'revoke':
        return handleRevoke(interaction, supabase, guildId);
    }
  }
};

async function handleCreate(interaction, supabase, guildId) {
  if (!interaction.member.permissions.has(PermissionFlagsBits.Administrator)) {
    return interaction.reply({ content: 'You need Administrator permission to create achievements.', ephemeral: true });
  }

  const name = interaction.options.getString('name');
  const trigger = interaction.options.getString('trigger');
  const value = interaction.options.getInteger('value');
  const description = interaction.options.getString('description') || `${TRIGGER_TYPES[trigger].name}: ${value}`;
  const icon = interaction.options.getString('icon') || '🏆';
  const rewardXp = interaction.options.getInteger('reward_xp') || 0;
  const rewardRole = interaction.options.getRole('reward_role');
  const hidden = interaction.options.getBoolean('hidden') || false;

  try {
    const { error } = await supabase
      .from('achievements')
      .insert({
        guild_id: guildId,
        name,
        description,
        icon,
        trigger_type: trigger,
        trigger_value: value,
        reward_xp: rewardXp,
        reward_role_id: rewardRole?.id || null,
        hidden
      });

    if (error) {
      if (error.code === '23505') {
        return interaction.reply({ content: `An achievement named "${name}" already exists.`, ephemeral: true });
      }
      throw error;
    }

    const embed = new EmbedBuilder()
      .setColor(0x10b981)
      .setTitle('Achievement Created')
      .addFields(
        { name: 'Name', value: `${icon} ${name}`, inline: true },
        { name: 'Trigger', value: `${TRIGGER_TYPES[trigger].name}: ${value.toLocaleString()}`, inline: true },
        { name: 'Description', value: description },
        { name: 'Rewards', value: [
          rewardXp > 0 ? `+${rewardXp.toLocaleString()} XP` : null,
          rewardRole ? `Role: ${rewardRole}` : null,
          hidden ? '(Hidden achievement)' : null
        ].filter(Boolean).join('\n') || 'None' }
      )
      .setTimestamp();

    return interaction.reply({ embeds: [embed] });
  } catch (error) {
    console.error('Achievement create error:', error);
    return interaction.reply({ content: 'Failed to create achievement.', ephemeral: true });
  }
}

async function handleDelete(interaction, supabase, guildId) {
  if (!interaction.member.permissions.has(PermissionFlagsBits.Administrator)) {
    return interaction.reply({ content: 'You need Administrator permission to delete achievements.', ephemeral: true });
  }

  const name = interaction.options.getString('name');

  try {
    const { data, error } = await supabase
      .from('achievements')
      .delete()
      .eq('guild_id', guildId)
      .eq('name', name)
      .select();

    if (error) throw error;

    if (!data || data.length === 0) {
      return interaction.reply({ content: `Achievement "${name}" not found.`, ephemeral: true });
    }

    return interaction.reply({ content: `Achievement "${name}" has been deleted.`, ephemeral: true });
  } catch (error) {
    console.error('Achievement delete error:', error);
    return interaction.reply({ content: 'Failed to delete achievement.', ephemeral: true });
  }
}

async function handleList(interaction, supabase, guildId) {
  try {
    const { data: achievements, error } = await supabase
      .from('achievements')
      .select('*')
      .eq('guild_id', guildId)
      .order('trigger_type')
      .order('trigger_value', { ascending: true });

    if (error) throw error;

    if (!achievements || achievements.length === 0) {
      return interaction.reply({
        content: 'No achievements configured. Use `/achievements create` to add some!',
        ephemeral: true
      });
    }

    const grouped = {};
    for (const ach of achievements) {
      const type = ach.trigger_type;
      if (!grouped[type]) grouped[type] = [];
      grouped[type].push(ach);
    }

    const embed = new EmbedBuilder()
      .setColor(0x7c3aed)
      .setTitle('Server Achievements')
      .setDescription(`${achievements.length} achievement(s) configured`)
      .setTimestamp();

    for (const [type, achs] of Object.entries(grouped)) {
      const typeInfo = TRIGGER_TYPES[type] || { name: type };
      const lines = achs.map(a => {
        const hiddenTag = a.hidden ? ' (Hidden)' : '';
        const rewards = [];
        if (a.reward_xp > 0) rewards.push(`+${a.reward_xp} XP`);
        if (a.reward_role_id) rewards.push(`<@&${a.reward_role_id}>`);
        const rewardStr = rewards.length > 0 ? ` | ${rewards.join(', ')}` : '';
        return `${a.icon} **${a.name}**${hiddenTag} - ${a.trigger_value.toLocaleString()}${rewardStr}`;
      });
      
      embed.addFields({
        name: typeInfo.name,
        value: lines.join('\n') || 'None',
        inline: false
      });
    }

    return interaction.reply({ embeds: [embed] });
  } catch (error) {
    console.error('Achievement list error:', error);
    return interaction.reply({ content: 'Failed to list achievements.', ephemeral: true });
  }
}

async function handleView(interaction, supabase, guildId) {
  const target = interaction.options.getUser('user') || interaction.user;
  await interaction.deferReply();

  try {
    const { data: link } = await supabase
      .from('discord_links')
      .select('user_id')
      .eq('discord_id', target.id)
      .maybeSingle();

    if (!link) {
      return interaction.editReply({
        embeds: [
          new EmbedBuilder()
            .setColor(0xff6b6b)
            .setDescription(`${target.id === interaction.user.id ? 'You are' : `${target.tag} is`} not linked to AeThex.`)
        ]
      });
    }

    const [achievementsResult, earnedResult] = await Promise.all([
      supabase.from('achievements').select('*').eq('guild_id', guildId),
      supabase.from('user_achievements')
        .select('achievement_id, earned_at')
        .eq('user_id', link.user_id)
        .eq('guild_id', guildId)
    ]);

    const allAchievements = achievementsResult.data || [];
    const earnedIds = new Set((earnedResult.data || []).map(e => e.achievement_id));
    const earnedMap = Object.fromEntries((earnedResult.data || []).map(e => [e.achievement_id, e.earned_at]));

    const earned = allAchievements.filter(a => earnedIds.has(a.id));
    const available = allAchievements.filter(a => !earnedIds.has(a.id) && !a.hidden);

    const embed = new EmbedBuilder()
      .setColor(0x7c3aed)
      .setTitle(`${target.username}'s Achievements`)
      .setThumbnail(target.displayAvatarURL())
      .setTimestamp();

    if (earned.length > 0) {
      const earnedLines = earned.map(a => {
        const date = earnedMap[a.id] ? new Date(earnedMap[a.id]).toLocaleDateString() : '';
        return `${a.icon} **${a.name}** - ${a.description} (${date})`;
      });
      embed.addFields({ name: `Earned (${earned.length})`, value: earnedLines.join('\n').slice(0, 1024) });
    } else {
      embed.addFields({ name: 'Earned', value: 'No achievements earned yet!' });
    }

    if (available.length > 0) {
      const availableLines = available.slice(0, 10).map(a => {
        const typeInfo = TRIGGER_TYPES[a.trigger_type] || { name: a.trigger_type };
        return `🔒 **${a.name}** - ${typeInfo.name}: ${a.trigger_value.toLocaleString()}`;
      });
      if (available.length > 10) {
        availableLines.push(`... and ${available.length - 10} more`);
      }
      embed.addFields({ name: `Available (${available.length})`, value: availableLines.join('\n').slice(0, 1024) });
    }

    const hiddenCount = allAchievements.filter(a => a.hidden && !earnedIds.has(a.id)).length;
    if (hiddenCount > 0) {
      embed.setFooter({ text: `${hiddenCount} hidden achievement(s) to discover` });
    }

    return interaction.editReply({ embeds: [embed] });
  } catch (error) {
    console.error('Achievement view error:', error);
    return interaction.editReply({ content: 'Failed to fetch achievements.' });
  }
}

async function handleGrant(interaction, supabase, guildId, client) {
  if (!interaction.member.permissions.has(PermissionFlagsBits.Administrator)) {
    return interaction.reply({ content: 'You need Administrator permission to grant achievements.', ephemeral: true });
  }

  const target = interaction.options.getUser('user');
  const name = interaction.options.getString('name');

  try {
    const { data: link } = await supabase
      .from('discord_links')
      .select('user_id')
      .eq('discord_id', target.id)
      .maybeSingle();

    if (!link) {
      return interaction.reply({ content: `${target.tag} is not linked to AeThex.`, ephemeral: true });
    }

    const { data: achievement } = await supabase
      .from('achievements')
      .select('*')
      .eq('guild_id', guildId)
      .eq('name', name)
      .maybeSingle();

    if (!achievement) {
      return interaction.reply({ content: `Achievement "${name}" not found.`, ephemeral: true });
    }

    const { error } = await supabase
      .from('user_achievements')
      .upsert({
        user_id: link.user_id,
        guild_id: guildId,
        achievement_id: achievement.id,
        notified: true
      }, { onConflict: 'user_id,guild_id,achievement_id' });

    if (error) throw error;

    if (achievement.reward_role_id) {
      const member = await interaction.guild.members.fetch(target.id).catch(() => null);
      if (member) {
        await member.roles.add(achievement.reward_role_id).catch(() => {});
      }
    }

    if (achievement.reward_xp > 0) {
      await supabase
        .from('user_profiles')
        .update({ xp: supabase.rpc('increment_xp', { user_id: link.user_id, amount: achievement.reward_xp }) })
        .eq('id', link.user_id);
    }

    return interaction.reply({
      content: `${achievement.icon} Granted **${achievement.name}** to ${target}!`,
      ephemeral: true
    });
  } catch (error) {
    console.error('Achievement grant error:', error);
    return interaction.reply({ content: 'Failed to grant achievement.', ephemeral: true });
  }
}

async function handleRevoke(interaction, supabase, guildId) {
  if (!interaction.member.permissions.has(PermissionFlagsBits.Administrator)) {
    return interaction.reply({ content: 'You need Administrator permission to revoke achievements.', ephemeral: true });
  }

  const target = interaction.options.getUser('user');
  const name = interaction.options.getString('name');

  try {
    const { data: link } = await supabase
      .from('discord_links')
      .select('user_id')
      .eq('discord_id', target.id)
      .maybeSingle();

    if (!link) {
      return interaction.reply({ content: `${target.tag} is not linked to AeThex.`, ephemeral: true });
    }

    const { data: achievement } = await supabase
      .from('achievements')
      .select('id, name, icon, reward_role_id')
      .eq('guild_id', guildId)
      .eq('name', name)
      .maybeSingle();

    if (!achievement) {
      return interaction.reply({ content: `Achievement "${name}" not found.`, ephemeral: true });
    }

    const { data, error } = await supabase
      .from('user_achievements')
      .delete()
      .eq('user_id', link.user_id)
      .eq('guild_id', guildId)
      .eq('achievement_id', achievement.id)
      .select();

    if (error) throw error;

    if (!data || data.length === 0) {
      return interaction.reply({ content: `${target.tag} doesn't have this achievement.`, ephemeral: true });
    }

    if (achievement.reward_role_id) {
      const member = await interaction.guild.members.fetch(target.id).catch(() => null);
      if (member) {
        await member.roles.remove(achievement.reward_role_id).catch(() => {});
      }
    }

    return interaction.reply({
      content: `Revoked **${achievement.name}** from ${target}.`,
      ephemeral: true
    });
  } catch (error) {
    console.error('Achievement revoke error:', error);
    return interaction.reply({ content: 'Failed to revoke achievement.', ephemeral: true });
  }
}

module.exports.checkAchievements = async function(userId, discordMember, stats, supabase, guildId, client) {
  if (!supabase || !userId || !guildId) return;

  try {
    const { data: achievements } = await supabase
      .from('achievements')
      .select('*')
      .eq('guild_id', guildId);

    if (!achievements || achievements.length === 0) return;

    const { data: earned } = await supabase
      .from('user_achievements')
      .select('achievement_id')
      .eq('user_id', userId)
      .eq('guild_id', guildId);

    const earnedIds = new Set((earned || []).map(e => e.achievement_id));
    const newlyEarned = [];

    for (const ach of achievements) {
      if (earnedIds.has(ach.id)) continue;

      let qualifies = false;
      const val = ach.trigger_value;

      switch (ach.trigger_type) {
        case 'level':
          qualifies = (stats.level || 0) >= val;
          break;
        case 'prestige':
          qualifies = (stats.prestige || 0) >= val;
          break;
        case 'total_xp':
          qualifies = (stats.totalXp || 0) >= val;
          break;
        case 'messages':
          qualifies = (stats.messages || 0) >= val;
          break;
        case 'reactions_given':
          qualifies = (stats.reactionsGiven || 0) >= val;
          break;
        case 'reactions_received':
          qualifies = (stats.reactionsReceived || 0) >= val;
          break;
        case 'voice_minutes':
          qualifies = (stats.voiceMinutes || 0) >= val;
          break;
        case 'daily_streak':
          qualifies = (stats.dailyStreak || 0) >= val;
          break;
        case 'commands_used':
          qualifies = (stats.commandsUsed || 0) >= val;
          break;
      }

      if (qualifies) {
        newlyEarned.push(ach);
      }
    }

    for (const ach of newlyEarned) {
      await supabase.from('user_achievements').insert({
        user_id: userId,
        guild_id: guildId,
        achievement_id: ach.id,
        notified: true
      }).catch(() => {});

      if (ach.reward_role_id && discordMember) {
        await discordMember.roles.add(ach.reward_role_id).catch(() => {});
      }

      if (ach.reward_xp > 0) {
        const { data: profile } = await supabase
          .from('user_profiles')
          .select('xp, total_xp_earned')
          .eq('id', userId)
          .maybeSingle();

        if (profile) {
          await supabase
            .from('user_profiles')
            .update({
              xp: (profile.xp || 0) + ach.reward_xp,
              total_xp_earned: (profile.total_xp_earned || 0) + ach.reward_xp
            })
            .eq('id', userId);
        }
      }

      if (discordMember && client) {
        try {
          await discordMember.send({
            embeds: [
              new EmbedBuilder()
                .setColor(0x10b981)
                .setTitle('Achievement Unlocked!')
                .setDescription(`${ach.icon} **${ach.name}**\n${ach.description}`)
                .addFields(
                  ach.reward_xp > 0 ? { name: 'Reward', value: `+${ach.reward_xp} XP`, inline: true } : []
                )
                .setTimestamp()
            ]
          }).catch(() => {});
        } catch (e) {}
      }
    }

    return newlyEarned;
  } catch (error) {
    console.error('Achievement check error:', error);
    return [];
  }
};
