import { ensure } from "@workshop/shared/utils"
import {
  Client,
  SlashCommandBuilder,
  type CacheType,
  type ChatInputCommandInteraction,
  type Interaction,
  type SlashCommandOptionsOnlyBuilder,
} from "discord.js"
import { getLogs } from "../render"

export const runCommand = async (interaction: Interaction<CacheType>) => {
  if (!interaction.isChatInputCommand()) return

  const command = commands.find((cmd) => cmd.command.name === interaction.commandName)
  ensure(command, `Command ${interaction.commandName} not found`)

  try {
    await command.execute(interaction)
  } catch (error) {
    const content = `❌ Error executing command ${interaction.commandName}: ${
      error instanceof Error ? error.message : String(error)
    }`
    console.error(content)
    if (interaction.deferred) {
      await interaction.editReply({ content })
    } else {
      await interaction.reply({ content, ephemeral: true })
    }
  }
}

export const registerCommands = async (client: Client<boolean>) => {
  const commandList = commands.map((cmd) => cmd.command)
  await client.application!.commands.set(commandList)
}

type ExecuteCommandFunction = (interaction: ChatInputCommandInteraction) => Promise<void>
const commands: { command: SlashCommandOptionsOnlyBuilder; execute: ExecuteCommandFunction }[] = [
  {
    command: new SlashCommandBuilder()
      .setName("logs")
      .setDescription("Grab the latest logs from Render.")
      .addStringOption((option) =>
        option
          .setName("type")
          .setDescription("The type of logs to fetch")
          .setRequired(true)
          .addChoices(
            { name: "App", value: "app" },
            { name: "Build", value: "build" },
            { name: "Request", value: "request" }
          )
      )
      .addNumberOption((option) =>
        option
          .setName("limit")
          .setDescription("The number of logs to fetch (default: 20)")
          .setMinValue(3)
          .setMaxValue(100)
          .setRequired(false)
      ),

    async execute(interaction) {
      await interaction.deferReply()
      const type = interaction.options.getString("type", true)
      const limit = interaction.options.getNumber("limit") ?? undefined
      await interaction.editReply(`Fetching ${type} logs...`)
      const logs = await getLogs(type as any, limit)

      if (logs.length === 0) {
        await interaction.editReply("No logs found.")
        return
      } else {
        let content = ""
        for (const log of [
          ...logs,
          "\nSee all logs at https://dashboard.render.com/web/srv-d1vrdqmuk2gs73eop8o0/logs",
        ]) {
          // Account for the opening/closing ``` in length calculation
          if (content.length + log.length >= 1990) {
            await interaction.followUp({ content: content, flags: ["SuppressEmbeds"] })
            content = log
          } else {
            content += log + "\n"
          }
        }
        await interaction.followUp({ content: content, flags: ["SuppressEmbeds"] })
      }
    },
  },
]
