import {
  type ButtonInteraction,
  ModalBuilder,
  TextInputBuilder,
  TextInputStyle,
  ActionRowBuilder,
  type TextInputModalData,
} from 'discord.js';
import { api } from '../api-client.js';
import {
  buildApprovedEmbed,
  buildRejectedEmbed,
  buildDeferredEmbed,
} from '../embeds/approval-request.js';
import { logger } from '../logger.js';

/**
 * Route button interactions based on custom ID prefix.
 */
export async function handleButton(interaction: ButtonInteraction): Promise<void> {
  const [action, ...args] = interaction.customId.split(':');

  switch (action) {
    case 'approve':
      await handleApprove(interaction, args[0]);
      break;
    case 'reject':
      await handleRejectModal(interaction, args[0]);
      break;
    case 'details':
      await handleDetails(interaction, args[0]);
      break;
    case 'defer':
      await handleDefer(interaction, args[0]);
      break;
    case 'batch-approve-low':
      await handleBatchApprove(interaction, args[0]?.split(',') ?? []);
      break;
    case 'batch-approve-all':
      await handleBatchApprove(interaction, args[0]?.split(',') ?? []);
      break;
    case 'batch-review-individual':
      await interaction.reply({
        content: 'Use the select menu below to pick a task to review, or use `/factory approve <task_id>` for individual approvals.',
        ephemeral: true,
      });
      break;
    case 'deploy-retry':
      await handleDeployRetry(interaction, args[0], args[1] as 'staging' | 'production');
      break;
    default:
      await interaction.reply({
        content: `Unknown action: ${action}`,
        ephemeral: true,
      });
  }
}

// ─── Individual Actions ──────────────────────

async function handleApprove(interaction: ButtonInteraction, taskId: string): Promise<void> {
  await interaction.deferUpdate();

  try {
    // Look up the approval for this task
    const task = await api.getTask(taskId);

    // Find associated approval
    const approvals = await api.listApprovals({ pipelineId: task.pipelineId ?? undefined, status: 'pending' });
    const approval = approvals.find((a) => a.taskId === taskId);

    if (approval) {
      await api.approveApproval(approval.id, {
        notes: `Approved via Discord by ${interaction.user.tag}`,
      });
    }

    // Update the embed
    const updatedTask = await api.getTask(taskId);
    const newEmbed = buildApprovedEmbed(updatedTask, interaction.user.id);
    await interaction.editReply(newEmbed);

    logger.info(`Task ${taskId} approved by ${interaction.user.tag}`);
  } catch (error) {
    logger.error(`Failed to approve task ${taskId}:`, error);
    await interaction.followUp({
      content: `❌ Failed to approve task: ${error instanceof Error ? error.message : 'Unknown error'}`,
      ephemeral: true,
    });
  }
}

async function handleRejectModal(interaction: ButtonInteraction, taskId: string): Promise<void> {
  // Show a modal for rejection reason
  const modal = new ModalBuilder()
    .setCustomId(`reject-modal:${taskId}`)
    .setTitle('Reject Task');

  const reasonInput = new TextInputBuilder()
    .setCustomId('reason')
    .setLabel('Rejection Reason')
    .setPlaceholder('Why is this being rejected? What changes are needed?')
    .setStyle(TextInputStyle.Paragraph)
    .setRequired(true)
    .setMinLength(10)
    .setMaxLength(2000);

  const changesInput = new TextInputBuilder()
    .setCustomId('requested_changes')
    .setLabel('Requested Changes (optional, one per line)')
    .setPlaceholder('e.g.,\nAdd unit tests for edge cases\nFix error handling in auth module')
    .setStyle(TextInputStyle.Paragraph)
    .setRequired(false)
    .setMaxLength(2000);

  modal.addComponents(
    new ActionRowBuilder<TextInputBuilder>().addComponents(reasonInput),
    new ActionRowBuilder<TextInputBuilder>().addComponents(changesInput),
  );

  await interaction.showModal(modal);
}

async function handleDetails(interaction: ButtonInteraction, taskId: string): Promise<void> {
  await interaction.deferReply({ ephemeral: true });

  try {
    const task = await api.getTask(taskId);
    const ctx = task.context;

    let detailsText = `## 📋 Task Details: ${task.title}\n\n`;
    detailsText += `**ID:** \`${task.id}\`\n`;
    detailsText += `**Type:** ${task.type}\n`;
    detailsText += `**Priority:** ${task.priority}\n`;
    detailsText += `**Status:** ${task.status}\n`;
    detailsText += `**Created:** <t:${Math.floor(new Date(task.createdAt).getTime() / 1000)}:R>\n\n`;

    if (ctx.summary) {
      detailsText += `### Summary\n${ctx.summary}\n\n`;
    }
    if (ctx.details) {
      detailsText += `### Details\n${ctx.details}\n\n`;
    }

    if (ctx.testResults) {
      const tr = ctx.testResults;
      detailsText += `### Test Results\n`;
      detailsText += `- Total: ${tr.total}\n`;
      detailsText += `- ✅ Passed: ${tr.passed}\n`;
      detailsText += `- ❌ Failed: ${tr.failed}\n`;
      detailsText += `- ⏭️ Skipped: ${tr.skipped}\n`;
      detailsText += `- 📊 Coverage: ${tr.coveragePercent}%\n\n`;
    }

    if (ctx.diffSummary) {
      const diff = ctx.diffSummary;
      detailsText += `### Changes\n`;
      detailsText += `- Files changed: ${diff.filesChanged}\n`;
      detailsText += `- Insertions: +${diff.insertions}\n`;
      detailsText += `- Deletions: -${diff.deletions}\n\n`;
    }

    if (task.slaDeadline) {
      detailsText += `### SLA\n`;
      detailsText += `- Deadline: <t:${Math.floor(new Date(task.slaDeadline).getTime() / 1000)}:F>\n`;
      detailsText += `- Breached: ${task.slaBreached ? '🚨 Yes' : '✅ No'}\n`;
      detailsText += `- Escalation Level: ${task.escalationLevel}\n`;
    }

    // Create a thread for extended discussion if in a guild channel
    if (interaction.channel && 'threads' in interaction.channel) {
      try {
        const message = interaction.message;
        const thread = await (interaction.channel as any).threads.create({
          name: `Details: ${task.title.slice(0, 90)}`,
          startMessage: message.id,
          autoArchiveDuration: 1440, // 24 hours
          reason: `Details requested for task ${task.id}`,
        });
        await thread.send(detailsText);
        await interaction.editReply({
          content: `📋 Details thread created: ${thread.toString()}`,
        });
        return;
      } catch {
        // Thread creation may fail — fall back to ephemeral
      }
    }

    // Truncate if too long for a single message
    if (detailsText.length > 2000) {
      detailsText = detailsText.slice(0, 1997) + '...';
    }

    await interaction.editReply({ content: detailsText });
  } catch (error) {
    logger.error(`Failed to get details for task ${taskId}:`, error);
    await interaction.editReply({
      content: `❌ Failed to get task details: ${error instanceof Error ? error.message : 'Unknown error'}`,
    });
  }
}

async function handleDefer(interaction: ButtonInteraction, taskId: string): Promise<void> {
  await interaction.deferUpdate();

  try {
    const task = await api.getTask(taskId);

    // Find the approval and call complete with deferred
    const approvals = await api.listApprovals({ pipelineId: task.pipelineId ?? undefined, status: 'pending' });
    const approval = approvals.find((a) => a.taskId === taskId);

    if (approval) {
      // There's no direct "defer" on approvals — we escalate instead
      await api.escalateApproval(approval.id, {
        reason: `Deferred via Discord by ${interaction.user.tag}`,
      });
    }

    const updatedTask = await api.getTask(taskId);
    const newEmbed = buildDeferredEmbed(updatedTask, interaction.user.id);
    await interaction.editReply(newEmbed);

    logger.info(`Task ${taskId} deferred by ${interaction.user.tag}`);
  } catch (error) {
    logger.error(`Failed to defer task ${taskId}:`, error);
    await interaction.followUp({
      content: `❌ Failed to defer task: ${error instanceof Error ? error.message : 'Unknown error'}`,
      ephemeral: true,
    });
  }
}

// ─── Batch Actions ───────────────────────────

async function handleBatchApprove(
  interaction: ButtonInteraction,
  taskIds: string[],
): Promise<void> {
  if (taskIds.length === 0 || (taskIds.length === 1 && taskIds[0] === '')) {
    await interaction.reply({
      content: '❌ No tasks to approve.',
      ephemeral: true,
    });
    return;
  }

  await interaction.deferUpdate();

  try {
    const result = await api.bulkTasks({
      action: 'approve',
      taskIds,
      notes: `Batch approved via Discord by ${interaction.user.tag}`,
    });

    const successCount = result.succeeded.length;
    const failCount = result.failed.length;

    let summary = `✅ **Batch Approval Complete**\n`;
    summary += `- Approved: ${successCount}\n`;
    if (failCount > 0) {
      summary += `- Failed: ${failCount}\n`;
      for (const f of result.failed) {
        summary += `  - \`${f.taskId}\`: ${f.error}\n`;
      }
    }
    summary += `\nApproved by <@${interaction.user.id}>`;

    await interaction.editReply({
      content: summary,
      embeds: [],
      components: [],
    });

    logger.info(`Batch approved ${successCount}/${taskIds.length} tasks by ${interaction.user.tag}`);
  } catch (error) {
    logger.error(`Batch approve failed:`, error);
    await interaction.followUp({
      content: `❌ Batch approve failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
      ephemeral: true,
    });
  }
}

// ─── Deploy Retry ────────────────────────────

async function handleDeployRetry(
  interaction: ButtonInteraction,
  pipelineId: string,
  target: 'staging' | 'production',
): Promise<void> {
  await interaction.deferReply({ ephemeral: true });

  try {
    const result = await api.deploy(pipelineId, target);
    await interaction.editReply({
      content: `🔄 Deploy retry initiated for pipeline \`${pipelineId}\` → ${target}\n` +
        `Deploy ID: \`${result.deployId}\``,
    });
  } catch (error) {
    logger.error(`Deploy retry failed:`, error);
    await interaction.editReply({
      content: `❌ Deploy retry failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
    });
  }
}
