import { StreamType, VoiceConnection } from "@discordjs/voice";
import { Client, ClientEvents, ClientPresenceStatusData, Message, MessageOptions, User } from "discord.js";
import { EventEmitter } from "events";
import { Readable } from "node:stream";

type OutputRunFunkce = string | MessageOptions | void;

export type RunFunkce = (message: Message, argumenty: string) => OutputRunFunkce | Promise<OutputRunFunkce>;

interface BaseKomandProps {
  als?: string[];
  arg?: string;
}

type KomandRaw = {
  run: string | RunFunkce;
  cd?: number;
  hidden?: true;
  DMUnsafe?: true;
} & BaseKomandProps;

export type ListenerFunkce = (...args: any[]) => void;

export type SuperListenerFunkce = (...args: any[]) => boolean;

interface SuperObject {
  pos: number;
  fun: SuperListenerFunkce;
}

type Eventy = keyof ClientEvents | "userPresenceUpdate";

export type EventSOn = `on_${Eventy}` | `super_on_${Eventy}`;

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

export type Modul = {
  more_komandy?: SRecord<RunFunkce | KomandRaw | string>;
  client?: Client<boolean>;
} & { [key in EventSOn]?: ListenerFunkce | SuperObject | SuperListenerFunkce; };

export interface Komand {
  run: RunFunkce | string;
  cd?: number;
  DMUnsafe?: 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 interface MuzikaFace {
  name: string | Readable;
  volume: number;
  type?: StreamType;
}

export type KomandNaExport = {
  name: string;
} & 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>;
}
