import { ChannelType, PermissionsBitField, EmbedBuilder } from 'discord.js';
import { db } from '../../core/db.js';

export async function handleCloneInteraction(interaction, client) {
  const id = interaction.customId;

  if (id.startsWith('clone_cancel:')) {
    return interaction.update({ content: '❌ Cancelled', embeds: [], components: [] });
  }

  if (id.startsWith('clone_apply:')) {
    const [, snapshotId, mode] = id.split(':');
    const row = db.prepare('SELECT * FROM clone_snapshots WHERE id = ?').get(parseInt(snapshotId));
    if (!row) return interaction.update({ content: '❌ Snapshot not found', embeds: [], components: [] });

    await interaction.update({ content: '⏳ Cloning…', embeds: [], components: [] });
    const snapshot = JSON.parse(row.data);
    const guild = interaction.guild;

    const result = { roles: 0, categories: 0, channels: 0, emojis: 0, errors: [] };
    const roleIdMap = new Map(); // old id → new id
    roleIdMap._sourceGuildId = row.source_guild_id; // Store source guild ID for @everyone mapping

    try {
      if (mode === 'roles' || mode === 'full') {
        // Create roles in reverse position order so position increments correctly
        for (const r of [...snapshot.roles].reverse()) {
          try {
            const created = await guild.roles.create({
              name: r.name,
              color: r.color,
              hoist: r.hoist,
              mentionable: r.mentionable,
              permissions: BigInt(r.permissions),
              reason: `Clone from snapshot #${snapshotId}`,
            });
            roleIdMap.set(r.id, created.id);
            result.roles++;
          } catch (e) { result.errors.push(`role ${r.name}: ${e.message}`); }
        }
      }

      if (mode === 'channels' || mode === 'full') {
        const categoryIdMap = new Map();
        for (const c of snapshot.categories) {
          try {
            const created = await guild.channels.create({
              name: c.name,
              type: ChannelType.GuildCategory,
              permissionOverwrites: mapOverwrites(c.permission_overwrites, roleIdMap, guild.id),
              reason: `Clone from snapshot #${snapshotId}`,
            });
            categoryIdMap.set(c.id, created.id);
            result.categories++;
          } catch (e) { result.errors.push(`category ${c.name}: ${e.message}`); }
        }
        for (const ch of snapshot.channels) {
          try {
            const opts = {
              name: ch.name,
              type: ch.type,
              parent: categoryIdMap.get(ch.parent_id),
              topic: ch.topic || undefined,
              nsfw: ch.nsfw,
              rateLimitPerUser: ch.rate_limit_per_user || 0,
              permissionOverwrites: mapOverwrites(ch.permission_overwrites, roleIdMap, guild.id),
              reason: `Clone from snapshot #${snapshotId}`,
            };
            if (ch.type === ChannelType.GuildVoice || ch.type === ChannelType.GuildStageVoice) {
              opts.bitrate = ch.bitrate;
              opts.userLimit = ch.user_limit;
            }
            await guild.channels.create(opts);
            result.channels++;
          } catch (e) { result.errors.push(`channel ${ch.name}: ${e.message}`); }
        }
      }
    } catch (e) {
      result.errors.push(`fatal: ${e.message}`);
    }

    const embed = new EmbedBuilder()
      .setTitle('✅ Clone Complete')
      .setColor(result.errors.length ? 0xf59e0b : 0x10b981)
      .addFields(
        { name: 'Roles created', value: `${result.roles}`, inline: true },
        { name: 'Categories', value: `${result.categories}`, inline: true },
        { name: 'Channels', value: `${result.channels}`, inline: true },
      );
    if (result.errors.length) {
      embed.addFields({ name: `Errors (${result.errors.length})`, value: '```\n' + result.errors.slice(0, 10).join('\n').slice(0, 900) + '\n```' });
    }
    await interaction.editReply({ content: '', embeds: [embed], components: [] });
  }
}

function mapOverwrites(overwrites, roleIdMap, guildId) {
  if (!overwrites) return [];
  return overwrites
    .filter(o => o.type === 0) // skip member overwrites (members not cloned)
    .map(o => {
      // @everyone has same id as guild → keep as-is
      const newId = o.id === roleIdMap._sourceGuildId ? guildId : (roleIdMap.get(o.id) || o.id);
      return {
        id: newId,
        allow: BigInt(o.allow),
        deny: BigInt(o.deny),
      };
    })
    .filter(o => o.id); // skip if role wasn't mapped (e.g. roles not cloned)
}
