import type { DiscordGatewayPayload, GatewayDispatchEventNames } from '@discordeno/types';
import type { Bot } from './bot.js';
import type { DesiredPropertiesBehavior, TransformersDesiredProperties } from './desiredProperties.js';
import * as handlers from './handlers/index.js';

export function createBotGatewayHandlers<TProps extends TransformersDesiredProperties, TBehavior extends DesiredPropertiesBehavior>(
  options: Partial<GatewayHandlers<TProps, TBehavior>>,
): GatewayHandlers<TProps, TBehavior> {
  const _options = options as Partial<GatewayHandlers<TransformersDesiredProperties, DesiredPropertiesBehavior.RemoveKey>>;

  return {
    APPLICATION_COMMAND_PERMISSIONS_UPDATE: _options.APPLICATION_COMMAND_PERMISSIONS_UPDATE ?? handlers.handleApplicationCommandPermissionsUpdate,
    AUTO_MODERATION_ACTION_EXECUTION: _options.AUTO_MODERATION_ACTION_EXECUTION ?? handlers.handleAutoModerationActionExecution,
    AUTO_MODERATION_RULE_CREATE: _options.AUTO_MODERATION_RULE_CREATE ?? handlers.handleAutoModerationRuleCreate,
    AUTO_MODERATION_RULE_DELETE: _options.AUTO_MODERATION_RULE_DELETE ?? handlers.handleAutoModerationRuleDelete,
    AUTO_MODERATION_RULE_UPDATE: _options.AUTO_MODERATION_RULE_UPDATE ?? handlers.handleAutoModerationRuleUpdate,
    CHANNEL_CREATE: _options.CHANNEL_CREATE ?? handlers.handleChannelCreate,
    CHANNEL_DELETE: _options.CHANNEL_DELETE ?? handlers.handleChannelDelete,
    CHANNEL_PINS_UPDATE: _options.CHANNEL_PINS_UPDATE ?? handlers.handleChannelPinsUpdate,
    CHANNEL_UPDATE: _options.CHANNEL_UPDATE ?? handlers.handleChannelUpdate,
    GUILD_AUDIT_LOG_ENTRY_CREATE: _options.GUILD_AUDIT_LOG_ENTRY_CREATE ?? handlers.handleGuildAuditLogEntryCreate,
    GUILD_BAN_ADD: _options.GUILD_BAN_ADD ?? handlers.handleGuildBanAdd,
    GUILD_BAN_REMOVE: _options.GUILD_BAN_REMOVE ?? handlers.handleGuildBanRemove,
    GUILD_CREATE: _options.GUILD_CREATE ?? handlers.handleGuildCreate,
    GUILD_DELETE: _options.GUILD_DELETE ?? handlers.handleGuildDelete,
    GUILD_EMOJIS_UPDATE: _options.GUILD_EMOJIS_UPDATE ?? handlers.handleGuildEmojisUpdate,
    GUILD_INTEGRATIONS_UPDATE: _options.GUILD_INTEGRATIONS_UPDATE ?? handlers.handleGuildIntegrationsUpdate,
    GUILD_MEMBER_ADD: _options.GUILD_MEMBER_ADD ?? handlers.handleGuildMemberAdd,
    GUILD_MEMBER_REMOVE: _options.GUILD_MEMBER_REMOVE ?? handlers.handleGuildMemberRemove,
    GUILD_MEMBER_UPDATE: _options.GUILD_MEMBER_UPDATE ?? handlers.handleGuildMemberUpdate,
    GUILD_MEMBERS_CHUNK: _options.GUILD_MEMBERS_CHUNK ?? handlers.handleGuildMembersChunk,
    GUILD_ROLE_CREATE: _options.GUILD_ROLE_CREATE ?? handlers.handleGuildRoleCreate,
    GUILD_ROLE_DELETE: _options.GUILD_ROLE_DELETE ?? handlers.handleGuildRoleDelete,
    GUILD_ROLE_UPDATE: _options.GUILD_ROLE_UPDATE ?? handlers.handleGuildRoleUpdate,
    GUILD_SCHEDULED_EVENT_CREATE: _options.GUILD_SCHEDULED_EVENT_CREATE ?? handlers.handleGuildScheduledEventCreate,
    GUILD_SCHEDULED_EVENT_DELETE: _options.GUILD_SCHEDULED_EVENT_DELETE ?? handlers.handleGuildScheduledEventDelete,
    GUILD_SCHEDULED_EVENT_UPDATE: _options.GUILD_SCHEDULED_EVENT_UPDATE ?? handlers.handleGuildScheduledEventUpdate,
    GUILD_SCHEDULED_EVENT_USER_ADD: _options.GUILD_SCHEDULED_EVENT_USER_ADD ?? handlers.handleGuildScheduledEventUserAdd,
    GUILD_SCHEDULED_EVENT_USER_REMOVE: _options.GUILD_SCHEDULED_EVENT_USER_REMOVE ?? handlers.handleGuildScheduledEventUserRemove,
    GUILD_STICKERS_UPDATE: _options.GUILD_STICKERS_UPDATE ?? handlers.handleGuildStickersUpdate,
    GUILD_UPDATE: _options.GUILD_UPDATE ?? handlers.handleGuildUpdate,
    INTERACTION_CREATE: _options.INTERACTION_CREATE ?? handlers.handleInteractionCreate,
    INTEGRATION_CREATE: _options.INTEGRATION_CREATE ?? handlers.handleIntegrationCreate,
    INTEGRATION_UPDATE: _options.INTEGRATION_UPDATE ?? handlers.handleIntegrationUpdate,
    INTEGRATION_DELETE: _options.INTEGRATION_DELETE ?? handlers.handleIntegrationDelete,
    INVITE_CREATE: _options.INVITE_CREATE ?? handlers.handleInviteCreate,
    INVITE_DELETE: _options.INVITE_DELETE ?? handlers.handleInviteDelete,
    MESSAGE_CREATE: _options.MESSAGE_CREATE ?? handlers.handleMessageCreate,
    MESSAGE_DELETE_BULK: _options.MESSAGE_DELETE_BULK ?? handlers.handleMessageDeleteBulk,
    MESSAGE_DELETE: _options.MESSAGE_DELETE ?? handlers.handleMessageDelete,
    MESSAGE_REACTION_ADD: _options.MESSAGE_REACTION_ADD ?? handlers.handleMessageReactionAdd,
    MESSAGE_REACTION_REMOVE_ALL: _options.MESSAGE_REACTION_REMOVE_ALL ?? handlers.handleMessageReactionRemoveAll,
    MESSAGE_REACTION_REMOVE_EMOJI: _options.MESSAGE_REACTION_REMOVE_EMOJI ?? handlers.handleMessageReactionRemoveEmoji,
    MESSAGE_REACTION_REMOVE: _options.MESSAGE_REACTION_REMOVE ?? handlers.handleMessageReactionRemove,
    MESSAGE_UPDATE: _options.MESSAGE_UPDATE ?? handlers.handleMessageUpdate,
    PRESENCE_UPDATE: _options.PRESENCE_UPDATE ?? handlers.handlePresenceUpdate,
    READY: _options.READY ?? handlers.handleReady,
    RESUMED: _options.RESUMED ?? handlers.handleResumed,
    RATE_LIMITED: _options.RATE_LIMITED ?? handlers.handleRateLimited,
    STAGE_INSTANCE_CREATE: _options.STAGE_INSTANCE_CREATE ?? handlers.handleStageInstanceCreate,
    STAGE_INSTANCE_DELETE: _options.STAGE_INSTANCE_DELETE ?? handlers.handleStageInstanceDelete,
    STAGE_INSTANCE_UPDATE: _options.STAGE_INSTANCE_UPDATE ?? handlers.handleStageInstanceUpdate,
    THREAD_CREATE: _options.THREAD_CREATE ?? handlers.handleThreadCreate,
    THREAD_DELETE: _options.THREAD_DELETE ?? handlers.handleThreadDelete,
    THREAD_UPDATE: _options.THREAD_UPDATE ?? handlers.handleThreadUpdate,
    THREAD_LIST_SYNC: _options.THREAD_LIST_SYNC ?? handlers.handleThreadListSync,
    THREAD_MEMBER_UPDATE: _options.THREAD_MEMBERS_UPDATE ?? handlers.handleThreadMembersUpdate,
    THREAD_MEMBERS_UPDATE: _options.THREAD_MEMBERS_UPDATE ?? handlers.handleThreadMembersUpdate,
    TYPING_START: _options.TYPING_START ?? handlers.handleTypingStart,
    USER_UPDATE: _options.USER_UPDATE ?? handlers.handleUserUpdate,
    VOICE_CHANNEL_EFFECT_SEND: _options.VOICE_CHANNEL_EFFECT_SEND ?? handlers.handleVoiceChannelEffectSend,
    VOICE_SERVER_UPDATE: _options.VOICE_SERVER_UPDATE ?? handlers.handleVoiceServerUpdate,
    VOICE_STATE_UPDATE: _options.VOICE_STATE_UPDATE ?? handlers.handleVoiceStateUpdate,
    WEBHOOKS_UPDATE: _options.WEBHOOKS_UPDATE ?? handlers.handleWebhooksUpdate,
    ENTITLEMENT_CREATE: _options.ENTITLEMENT_CREATE ?? handlers.handleEntitlementCreate,
    ENTITLEMENT_UPDATE: _options.ENTITLEMENT_UPDATE ?? handlers.handleEntitlementUpdate,
    ENTITLEMENT_DELETE: _options.ENTITLEMENT_DELETE ?? handlers.handleEntitlementDelete,
    MESSAGE_POLL_VOTE_ADD: _options.MESSAGE_POLL_VOTE_ADD ?? handlers.handleMessagePollVoteAdd,
    MESSAGE_POLL_VOTE_REMOVE: _options.MESSAGE_POLL_VOTE_REMOVE ?? handlers.handleMessagePollVoteRemove,
    SUBSCRIPTION_CREATE: _options.SUBSCRIPTION_CREATE ?? handlers.handleSubscriptionCreate,
    SUBSCRIPTION_UPDATE: _options.SUBSCRIPTION_UPDATE ?? handlers.handleSubscriptionUpdate,
    SUBSCRIPTION_DELETE: _options.SUBSCRIPTION_DELETE ?? handlers.handleSubscriptionDelete,
    GUILD_SOUNDBOARD_SOUND_CREATE: _options.GUILD_SOUNDBOARD_SOUND_CREATE ?? handlers.handleGuildSoundboardSoundCreate,
    GUILD_SOUNDBOARD_SOUND_DELETE: _options.GUILD_SOUNDBOARD_SOUND_DELETE ?? handlers.handleGuildSoundboardSoundDelete,
    GUILD_SOUNDBOARD_SOUND_UPDATE: _options.GUILD_SOUNDBOARD_SOUND_UPDATE ?? handlers.handleGuildSoundboardSoundUpdate,
    GUILD_SOUNDBOARD_SOUNDS_UPDATE: _options.GUILD_SOUNDBOARD_SOUNDS_UPDATE ?? handlers.handleGuildSoundboardSoundsUpdate,
    SOUNDBOARD_SOUNDS: _options.SOUNDBOARD_SOUNDS ?? handlers.handleSoundboardSounds,
  } satisfies GatewayHandlers<TransformersDesiredProperties, DesiredPropertiesBehavior.RemoveKey> as unknown as GatewayHandlers<TProps, TBehavior>;
}

export type GatewayHandlers<TProps extends TransformersDesiredProperties, TBehavior extends DesiredPropertiesBehavior> = Record<
  GatewayDispatchEventNames,
  BotGatewayHandler<TProps, TBehavior>
>;

export type BotGatewayHandler<TProps extends TransformersDesiredProperties, TBehavior extends DesiredPropertiesBehavior> = (
  bot: Bot<TProps, TBehavior>,
  data: DiscordGatewayPayload,
  shardId: number,
) => unknown;
