import { z } from 'zod';

const LocaleSchema = z.enum(['de', 'en']);

export const DashboardModuleIdSchema = z.enum([
  'moderation',
  'automod',
  'logging',
  'welcome',
  'verification',
  'leveling',
  'economy',
  'fun',
  'giveaways',
  'tickets',
  'selfroles',
  'tags',
  'starboard',
  'suggestions',
  'birthdays',
  'tempvoice',
  'stats',
  'feeds',
  'scheduler',
  'guildbackup',
  'messages'
]);

export type DashboardModuleId = z.infer<typeof DashboardModuleIdSchema>;

export const DashboardModuleGroupSchema = z.enum([
  'moderation',
  'engagement',
  'utility',
  'community',
  'integrations'
]);

export type DashboardModuleGroup = z.infer<typeof DashboardModuleGroupSchema>;

export const DASHBOARD_MODULES = [
  { id: 'moderation', group: 'moderation', href: 'moderation' },
  { id: 'automod', group: 'moderation', href: 'automod' },
  { id: 'logging', group: 'moderation', href: 'logging' },
  { id: 'welcome', group: 'engagement', href: 'welcome' },
  { id: 'verification', group: 'engagement', href: 'verification' },
  { id: 'leveling', group: 'engagement', href: 'leveling' },
  { id: 'economy', group: 'engagement', href: 'economy' },
  { id: 'fun', group: 'engagement', href: 'fun' },
  { id: 'giveaways', group: 'community', href: 'giveaways' },
  { id: 'tickets', group: 'community', href: 'tickets' },
  { id: 'selfroles', group: 'community', href: 'selfroles' },
  { id: 'tags', group: 'utility', href: 'tags' },
  { id: 'messages', group: 'utility', href: 'messages' },
  { id: 'starboard', group: 'community', href: 'starboard' },
  { id: 'suggestions', group: 'community', href: 'suggestions' },
  { id: 'birthdays', group: 'community', href: 'birthdays' },
  { id: 'tempvoice', group: 'utility', href: 'tempvoice' },
  { id: 'stats', group: 'integrations', href: 'stats' },
  { id: 'feeds', group: 'integrations', href: 'feeds' },
  { id: 'scheduler', group: 'integrations', href: 'scheduler' },
  { id: 'guildbackup', group: 'integrations', href: 'backup' }
] as const satisfies ReadonlyArray<{
  id: DashboardModuleId;
  group: DashboardModuleGroup;
  href: string;
}>;

export const SessionUserSchema = z.object({
  id: z.string().min(1),
  username: z.string().min(1),
  globalName: z.string().nullable(),
  avatar: z.string().nullable(),
  locale: LocaleSchema.optional()
});

export type SessionUser = z.infer<typeof SessionUserSchema>;

export const DashboardGuildSchema = z.object({
  id: z.string().min(1),
  name: z.string().min(1),
  icon: z.string().nullable(),
  botPresent: z.boolean(),
  permissions: z.string()
});

export type DashboardGuild = z.infer<typeof DashboardGuildSchema>;

export const GuildGeneralSettingsSchema = z.object({
  locale: LocaleSchema,
  timezone: z.string().min(1).max(64),
  moderationEnabled: z.boolean(),
  snipeEnabled: z.boolean()
});

export type GuildGeneralSettings = z.infer<typeof GuildGeneralSettingsSchema>;

export const GuildGeneralSettingsPatchSchema = GuildGeneralSettingsSchema.partial().refine(
  (value) => Object.keys(value).length > 0,
  { message: 'At least one field is required' }
);

export type GuildGeneralSettingsPatch = z.infer<typeof GuildGeneralSettingsPatchSchema>;

export const ModuleStatusSchema = z.object({
  id: DashboardModuleIdSchema,
  enabled: z.boolean(),
  group: DashboardModuleGroupSchema,
  href: z.string()
});

export type ModuleStatus = z.infer<typeof ModuleStatusSchema>;

export const ModulesUpdateSchema = z.object({
  modules: z.record(DashboardModuleIdSchema, z.boolean()).refine((value) => Object.keys(value).length > 0, {
    message: 'At least one module toggle is required'
  })
});

export type ModulesUpdate = z.infer<typeof ModulesUpdateSchema>;

export const DashboardAccessRuleSchema = z.object({
  id: z.string().optional(),
  roleId: z.string().regex(/^\d{17,20}$/),
  modules: z.union([z.literal('all'), z.array(DashboardModuleIdSchema).min(1)])
});

export type DashboardAccessRule = z.infer<typeof DashboardAccessRuleSchema>;

export const DashboardAccessRulesUpdateSchema = z.object({
  rules: z.array(DashboardAccessRuleSchema)
});

export type DashboardAccessRulesUpdate = z.infer<typeof DashboardAccessRulesUpdateSchema>;

export const DashboardAuditEntrySchema = z.object({
  id: z.string(),
  guildId: z.string().nullable(),
  actorUserId: z.string(),
  action: z.string(),
  path: z.string().nullable(),
  createdAt: z.string()
});

export type DashboardAuditEntry = z.infer<typeof DashboardAuditEntrySchema>;

export const DISCORD_PERMISSION_MANAGE_GUILD = 1n << 5n;

export function hasManageGuildPermission(permissions: string | bigint): boolean {
  const value = typeof permissions === 'bigint' ? permissions : BigInt(permissions);
  return (value & DISCORD_PERMISSION_MANAGE_GUILD) === DISCORD_PERMISSION_MANAGE_GUILD;
}
