import { Type } from "@sinclair/typebox";

import { createReactionSchema } from "./reaction-schema.js";

export const DiscordToolSchema = Type.Union([
  createReactionSchema({
    ids: {
      channelId: Type.String(),
      messageId: Type.String(),
    },
    includeRemove: true,
  }),
  Type.Object({
    action: Type.Literal("reactions"),
    channelId: Type.String(),
    messageId: Type.String(),
    limit: Type.Optional(Type.Number()),
  }),
  Type.Object({
    action: Type.Literal("sticker"),
    to: Type.String(),
    stickerIds: Type.Array(Type.String()),
    content: Type.Optional(Type.String()),
  }),
  Type.Object({
    action: Type.Literal("poll"),
    to: Type.String(),
    question: Type.String(),
    answers: Type.Array(Type.String()),
    allowMultiselect: Type.Optional(Type.Boolean()),
    durationHours: Type.Optional(Type.Number()),
    content: Type.Optional(Type.String()),
  }),
  Type.Object({
    action: Type.Literal("permissions"),
    channelId: Type.String(),
  }),
  Type.Union([
    Type.Object({
      action: Type.Literal("fetchMessage"),
      messageLink: Type.String(),
      guildId: Type.Optional(Type.String()),
      channelId: Type.Optional(Type.String()),
      messageId: Type.Optional(Type.String()),
    }),
    Type.Object({
      action: Type.Literal("fetchMessage"),
      guildId: Type.String(),
      channelId: Type.String(),
      messageId: Type.String(),
    }),
  ]),
  Type.Object({
    action: Type.Literal("readMessages"),
    channelId: Type.String(),
    limit: Type.Optional(Type.Number()),
    before: Type.Optional(Type.String()),
    after: Type.Optional(Type.String()),
    around: Type.Optional(Type.String()),
  }),
  Type.Object({
    action: Type.Literal("sendMessage"),
    to: Type.String(),
    content: Type.String(),
    mediaUrl: Type.Optional(Type.String()),
    replyTo: Type.Optional(Type.String()),
  }),
  Type.Object({
    action: Type.Literal("editMessage"),
    channelId: Type.String(),
    messageId: Type.String(),
    content: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("deleteMessage"),
    channelId: Type.String(),
    messageId: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("threadCreate"),
    channelId: Type.String(),
    name: Type.String(),
    messageId: Type.Optional(Type.String()),
    autoArchiveMinutes: Type.Optional(Type.Number()),
  }),
  Type.Object({
    action: Type.Literal("threadList"),
    guildId: Type.String(),
    channelId: Type.Optional(Type.String()),
    includeArchived: Type.Optional(Type.Boolean()),
    before: Type.Optional(Type.String()),
    limit: Type.Optional(Type.Number()),
  }),
  Type.Object({
    action: Type.Literal("threadReply"),
    channelId: Type.String(),
    content: Type.String(),
    mediaUrl: Type.Optional(Type.String()),
    replyTo: Type.Optional(Type.String()),
  }),
  Type.Object({
    action: Type.Literal("pinMessage"),
    channelId: Type.String(),
    messageId: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("unpinMessage"),
    channelId: Type.String(),
    messageId: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("listPins"),
    channelId: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("searchMessages"),
    guildId: Type.String(),
    content: Type.String(),
    channelId: Type.Optional(Type.String()),
    channelIds: Type.Optional(Type.Array(Type.String())),
    authorId: Type.Optional(Type.String()),
    authorIds: Type.Optional(Type.Array(Type.String())),
    limit: Type.Optional(Type.Number()),
  }),
  Type.Object({
    action: Type.Literal("memberInfo"),
    guildId: Type.String(),
    userId: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("roleInfo"),
    guildId: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("emojiList"),
    guildId: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("emojiUpload"),
    guildId: Type.String(),
    name: Type.String(),
    mediaUrl: Type.String(),
    roleIds: Type.Optional(Type.Array(Type.String())),
  }),
  Type.Object({
    action: Type.Literal("stickerUpload"),
    guildId: Type.String(),
    name: Type.String(),
    description: Type.String(),
    tags: Type.String(),
    mediaUrl: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("roleAdd"),
    guildId: Type.String(),
    userId: Type.String(),
    roleId: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("roleRemove"),
    guildId: Type.String(),
    userId: Type.String(),
    roleId: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("channelInfo"),
    channelId: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("channelList"),
    guildId: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("voiceStatus"),
    guildId: Type.String(),
    userId: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("eventList"),
    guildId: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("eventCreate"),
    guildId: Type.String(),
    name: Type.String(),
    startTime: Type.String(),
    endTime: Type.Optional(Type.String()),
    description: Type.Optional(Type.String()),
    channelId: Type.Optional(Type.String()),
    entityType: Type.Optional(
      Type.Union([
        Type.Literal("voice"),
        Type.Literal("stage"),
        Type.Literal("external"),
      ]),
    ),
    location: Type.Optional(Type.String()),
  }),
  Type.Object({
    action: Type.Literal("timeout"),
    guildId: Type.String(),
    userId: Type.String(),
    durationMinutes: Type.Optional(Type.Number()),
    until: Type.Optional(Type.String()),
    reason: Type.Optional(Type.String()),
  }),
  Type.Object({
    action: Type.Literal("kick"),
    guildId: Type.String(),
    userId: Type.String(),
    reason: Type.Optional(Type.String()),
  }),
  Type.Object({
    action: Type.Literal("ban"),
    guildId: Type.String(),
    userId: Type.String(),
    reason: Type.Optional(Type.String()),
    deleteMessageDays: Type.Optional(Type.Number()),
  }),
  // Channel management actions
  Type.Object({
    action: Type.Literal("channelCreate"),
    guildId: Type.String(),
    name: Type.String(),
    type: Type.Optional(Type.Number()),
    parentId: Type.Optional(Type.String()),
    topic: Type.Optional(Type.String()),
    position: Type.Optional(Type.Number()),
    nsfw: Type.Optional(Type.Boolean()),
  }),
  Type.Object({
    action: Type.Literal("channelEdit"),
    channelId: Type.String(),
    name: Type.Optional(Type.String()),
    topic: Type.Optional(Type.String()),
    position: Type.Optional(Type.Number()),
    parentId: Type.Optional(Type.Union([Type.String(), Type.Null()])),
    nsfw: Type.Optional(Type.Boolean()),
    rateLimitPerUser: Type.Optional(Type.Number()),
  }),
  Type.Object({
    action: Type.Literal("channelDelete"),
    channelId: Type.String(),
  }),
  Type.Object({
    action: Type.Literal("channelMove"),
    guildId: Type.String(),
    channelId: Type.String(),
    parentId: Type.Optional(Type.Union([Type.String(), Type.Null()])),
    position: Type.Optional(Type.Number()),
  }),
  // Category management actions (convenience aliases)
  Type.Object({
    action: Type.Literal("categoryCreate"),
    guildId: Type.String(),
    name: Type.String(),
    position: Type.Optional(Type.Number()),
  }),
  Type.Object({
    action: Type.Literal("categoryEdit"),
    categoryId: Type.String(),
    name: Type.Optional(Type.String()),
    position: Type.Optional(Type.Number()),
  }),
  Type.Object({
    action: Type.Literal("categoryDelete"),
    categoryId: Type.String(),
  }),
  // Permission overwrite actions
  Type.Object({
    action: Type.Literal("channelPermissionSet"),
    channelId: Type.String(),
    targetId: Type.String(),
    targetType: Type.Union([Type.Literal("role"), Type.Literal("member")]),
    allow: Type.Optional(Type.String()),
    deny: Type.Optional(Type.String()),
  }),
  Type.Object({
    action: Type.Literal("channelPermissionRemove"),
    channelId: Type.String(),
    targetId: Type.String(),
  }),
]);
