import { ChannelType, PermissionFlagsBits } from 'discord.js';
import {
  SelfRoleBehaviorSchema,
  SelfRoleModeSchema,
  t,
  tf
} from '@nexumi/shared';
import type { SlashCommand } from '../../types.js';
import { getGuildLocale } from '../../i18n.js';
import { requirePermission } from '../../permissions.js';
import { parseDuration } from '../moderation/duration.js';
import { selfrolesCommandData } from './command-definitions.js';
import {
  createSelfRolePanel,
  deleteSelfRolePanel,
  parseRolesInput,
  SelfRoleError,
  updateSelfRolePanel
} from './service.js';

async function ensureManageGuild(
  interaction: Parameters<SlashCommand['execute']>[0],
  locale: 'de' | 'en'
): Promise<boolean> {
  if (!interaction.inGuild()) {
    await interaction.reply({ content: t(locale, 'generic.guildOnly'), ephemeral: true });
    return false;
  }
  return requirePermission(interaction, PermissionFlagsBits.ManageGuild, locale);
}

function parseOptionalDuration(
  input: string | null,
  locale: 'de' | 'en',
  interaction: Parameters<SlashCommand['execute']>[0]
): number | undefined | null {
  if (!input) {
    return undefined;
  }

  try {
    return parseDuration(input);
  } catch {
    interaction.reply({
      content: t(locale, 'selfroles.error.invalid_duration'),
      ephemeral: true
    });
    return null;
  }
}

const selfrolesCommand: SlashCommand = {
  data: selfrolesCommandData,
  async execute(interaction, context) {
    const locale = await getGuildLocale(context.prisma, interaction.guildId);
    if (!(await ensureManageGuild(interaction, locale))) {
      return;
    }

    const group = interaction.options.getSubcommandGroup(true);
    const sub = interaction.options.getSubcommand(true);

    if (group !== 'panel') {
      return;
    }

    try {
      if (sub === 'create') {
        const behavior = SelfRoleBehaviorSchema.parse(
          interaction.options.getString('behavior', true)
        );
        const mode = SelfRoleModeSchema.parse(interaction.options.getString('mode', true));
        const channel = interaction.options.getChannel('channel', true);
        if (channel.type !== ChannelType.GuildText && channel.type !== ChannelType.GuildAnnouncement) {
          await interaction.reply({
            content: t(locale, 'selfroles.error.invalid_channel'),
            ephemeral: true
          });
          return;
        }

        let temporaryDurationMs: number | undefined;
        if (behavior === 'TEMPORARY') {
          const durationInput = interaction.options.getString('duration', true);
          const parsed = parseOptionalDuration(durationInput, locale, interaction);
          if (parsed === null) {
            return;
          }
          if (!parsed || parsed < 60_000) {
            await interaction.reply({
              content: t(locale, 'selfroles.error.duration_too_short'),
              ephemeral: true
            });
            return;
          }
          temporaryDurationMs = parsed;
        }

        const roles = parseRolesInput(interaction.options.getString('roles', true));
        const panel = await createSelfRolePanel(
          context,
          {
            guildId: interaction.guildId!,
            channelId: channel.id,
            title: interaction.options.getString('title', true),
            description: interaction.options.getString('description'),
            mode,
            behavior,
            roles,
            temporaryDurationMs
          },
          locale
        );

        await interaction.reply({
          content: tf(locale, 'selfroles.panel.created', { id: panel.id }),
          ephemeral: true
        });
        return;
      }

      if (sub === 'edit') {
        const panelId = interaction.options.getString('panel_id', true);
        const behaviorRaw = interaction.options.getString('behavior');
        const behavior = behaviorRaw ? SelfRoleBehaviorSchema.parse(behaviorRaw) : undefined;
        const modeRaw = interaction.options.getString('mode');
        const mode = modeRaw ? SelfRoleModeSchema.parse(modeRaw) : undefined;

        let roles;
        const rolesInput = interaction.options.getString('roles');
        if (rolesInput) {
          roles = parseRolesInput(rolesInput);
        }

        let temporaryDurationMs: number | undefined;
        const durationInput = interaction.options.getString('duration');
        if (durationInput) {
          const parsed = parseOptionalDuration(durationInput, locale, interaction);
          if (parsed === null) {
            return;
          }
          if (!parsed || parsed < 60_000) {
            await interaction.reply({
              content: t(locale, 'selfroles.error.duration_too_short'),
              ephemeral: true
            });
            return;
          }
          temporaryDurationMs = parsed;
        } else if (behavior === 'TEMPORARY') {
          await interaction.reply({
            content: t(locale, 'selfroles.error.duration_required'),
            ephemeral: true
          });
          return;
        }

        const descriptionValue = interaction.options.getString('description');
        const panel = await updateSelfRolePanel(
          context,
          panelId,
          interaction.guildId!,
          {
            title: interaction.options.getString('title') ?? undefined,
            description: descriptionValue !== null ? descriptionValue : undefined,
            mode,
            behavior,
            roles,
            temporaryDurationMs
          },
          locale
        );

        await interaction.reply({
          content: tf(locale, 'selfroles.panel.updated', { id: panel.id }),
          ephemeral: true
        });
        return;
      }

      if (sub === 'delete') {
        const panelId = interaction.options.getString('panel_id', true);
        await deleteSelfRolePanel(context, panelId, interaction.guildId!);
        await interaction.reply({
          content: t(locale, 'selfroles.panel.deleted'),
          ephemeral: true
        });
      }
    } catch (error) {
      if (error instanceof SelfRoleError) {
        await interaction.reply({
          content: t(locale, `selfroles.error.${error.code}`),
          ephemeral: true
        });
        return;
      }
      throw error;
    }
  }
};

export const selfrolesCommands = [selfrolesCommand];
