import { VoiceConnection } from "@discordjs/voice";
import { Awaitable, BaseMessageOptions, ChatInputCommandInteraction, Client, ClientEvents, ClientPresenceStatusData, Message, MessageCreateOptions, OmitPartialGroupDMChannel, Presence, User } from "discord.js";
import { EventEmitter } from "events";

export type SMessage = OmitPartialGroupDMChannel<Message>;

export type RunFunkce = (message: SMessage, argumenty: string) => Awaitable<string | MessageCreateOptions | void>;
export type InteractionRunFunkce = (interaction: ChatInputCommandInteraction) => Awaitable<string | BaseMessageOptions | void>;

export type BaseKomandProps = {
  als?: string[];
  arg?: string;
};

export type KomandRaw = BaseKomandProps &
{
  cd?: number;
  hidden?: true;
  DMUnsafe?: true;
  premium?: true;
} & (
    {
      run: string | RunFunkce;
      slashRun?: never;
    }
    | {
      run?: never;
      slashRun: InteractionRunFunkce;
    }
  );


export type ListenerFunkce<T extends keyof ClientEvents> = (...args: ClientEvents[T]) => void;

export type SuperListenerFunkce<T extends keyof ClientEvents> = (...args: ClientEvents[T]) => Awaitable<boolean>;

interface SuperObject<T extends keyof ClientEvents> {
  pos: number;
  fun: SuperListenerFunkce<T>;
}

export type SRecord<T> = Record<string, T>;

export type Modul = {
  more_komandy?: SRecord<RunFunkce | KomandRaw | string>;
  client?: Client<boolean>;
  on_userPresenceUpdate?: (bef: Presence | null, aft: Presence) => void;
} & { [key in keyof ClientEvents as `on_${key}`]?: ListenerFunkce<key> }
  & { [key in keyof ClientEvents as `super_on_${key}`]?: SuperObject<key> | SuperListenerFunkce<key>; };

export type Komand = {
  run?: string | RunFunkce;
  slashRun?: InteractionRunFunkce;
  cd?: number;
  DMUnsafe?: true;
  premium?: true;
};

export interface Spinkackar {
  spinkacek: boolean;
  timeup: number | false;
}

export interface FakePresence {
  status: "online" | "idle" | "dnd" | "offline";
  clientStatus?: ClientPresenceStatusData;
}

export interface UserChange {
  user: User;
  ch?: "user" | "stat";
  stat?: string;
}

export type StatusyINaFounu = "Online" | "OnlinePhone" | "Idle" | "IdlePhone" | "DND" | "DNDPhone" | "Offline";

export interface ZmenovejObjekt {
  id: string;
  nick?: string;
  pfp?: string;
  status?: string;
}

export type KomandNaExport = {
  name: string;
  custom?: true;
} & BaseKomandProps;

export interface JoinHovna {
  conn: VoiceConnection;
  prev: string | boolean;
}

export interface CUser extends User {
  presence?: ClientPresenceStatusData;
}

export interface CustomKomandy {
  cKomandy: SRecord<Komand>;
  cAliasy: SRecord<string>;
  emitter: EventEmitter;
  naucse: RunFunkce;
  zapomen: RunFunkce;
  kohoje: RunFunkce;
  naucsealias: RunFunkce;
  zapomenalias: RunFunkce;
  naSend: KomandNaExport[];
  realKomandy: SRecord<Komand>;
  realAliasy: SRecord<string>;
}

export interface HelpServer {
  komandy: KomandNaExport[];
  customKomandy: KomandNaExport[];
  customAliasy: SRecord<string>;
}

export class CClient extends Client {
  komandy!: SRecord<Komand>;
  aliasy!: SRecord<string>;
  slashCommandy!: SRecord<string>;
}
