/**
 * Definições de tipo para lib-jitsi-meet
 * Baseado na documentação oficial do Jitsi Meet
 */

export interface JitsiConnection {
	connect(): void;
	disconnect(): void;
	addEventListener(event: string, handler: (data?: unknown) => void): void;
	removeEventListener(event: string, handler: (data?: unknown) => void): void;
	initJitsiConference(roomName: string, options: Record<string, unknown>): JitsiConference;
}

export interface JitsiConference {
	join(): void;
	leave(): void;
	on(event: string, handler: (...args: unknown[]) => void): void;
	off(event: string, handler: (...args: unknown[]) => void): void;
	removeEventListener(event: string, handler: (...args: unknown[]) => void): void;
	muteAudio(): void;
	unmuteAudio(): void;
	muteVideo(): void;
	unmuteVideo(): void;
	getParticipants(): Map<string, JitsiParticipant>;
	getLocalTracks(): JitsiTrack[];
	setDisplayName(name: string): void;
	addTrack(track: JitsiTrack): Promise<void>;
	removeTrack(track: JitsiTrack): Promise<void>;
	getLocalVideoTrack(): JitsiTrack | null;
	getLocalAudioTrack(): JitsiTrack | null;
}

export interface JitsiTrack {
	getType(): 'audio' | 'video';
	isMuted(): boolean;
	mute(): Promise<void>;
	unmute(): Promise<void>;
	attach(element: HTMLElement): void;
	detach(element: HTMLElement): void;
	dispose(): Promise<void>;
	getParticipantId(): string;
	track: MediaStreamTrack;
	isLocal(): boolean;
	getVideoType(): 'camera' | 'desktop' | undefined;
}

export interface JitsiParticipant {
	getId(): string;
	getDisplayName(): string;
	isAudioMuted(): boolean;
	isVideoMuted(): boolean;
	getRole(): string;
}

export interface JitsiMeetJSLib {
	JitsiConnection: new (
		appId: string | null,
		token: string | null,
		options: JitsiConnectionOptions
	) => JitsiConnection;
	constants: {
		events: {
			connection: {
				CONNECTION_ESTABLISHED: string;
				CONNECTION_FAILED: string;
				CONNECTION_DISCONNECTED: string;
				WRONG_STATE: string;
			};
			conference: {
				USER_JOINED: string;
				USER_LEFT: string;
				TRACK_ADDED: string;
				TRACK_REMOVED: string;
				TRACK_MUTE_CHANGED: string;
				CONFERENCE_JOINED: string;
				CONFERENCE_LEFT: string;
				CONFERENCE_ERROR: string;
				DISPLAY_NAME_CHANGED: string;
				DOMINANT_SPEAKER_CHANGED: string;
			};
		};
		logLevels: {
			ERROR: number;
			WARN: number;
			INFO: number;
			DEBUG: number;
		};
	};
	init(options: JitsiInitOptions): void;
	setLogLevel(level: number): void;
	createLocalTracks(
		options: MediaStreamConstraints,
		advancedOptions?: JitsiLocalTrackOptions
	): Promise<JitsiTrack[]>;
	mediaDevices: {
		enumerateDevices(): Promise<MediaDeviceInfo[]>;
		isDeviceChangeAvailable(type: 'audio' | 'video'): Promise<boolean>;
	};
}

export interface JitsiConnectionOptions {
	hosts?: {
		domain?: string;
		muc?: string;
		focus?: string;
	};
	serviceUrl?: string;
	bosh?: string;
	websocket?: string;
	clientNode?: string;
	useStunTurn?: boolean;
	iceServers?: RTCIceServer[];
	enableLayerSuspension?: boolean;
	enableLipSync?: boolean;
	disableAudioLevels?: boolean;
	disableSimulcast?: boolean;
	enableRemb?: boolean;
	enableTcc?: boolean;
	useRoomAsSharedDocumentName?: boolean;
	enableStatsID?: boolean;
	channelLastN?: number;
	startBitrate?: number;
	stereo?: boolean;
	forcedVideoCodec?: string;
	preferredVideoCodec?: string;
	disableH264?: boolean;
	disableVP8?: boolean;
	disableVP9?: boolean;
	enableOpusRed?: boolean;
	enableDtmf?: boolean;
	openBridgeChannel?: string | boolean;
}

export interface JitsiInitOptions {
	disableAudioLevels?: boolean;
	disableSimulcast?: boolean;
	enableWindowOnErrorHandler?: boolean;
	enableRemb?: boolean;
	enableTcc?: boolean;
	disableThirdPartyRequests?: boolean;
	useStunTurn?: boolean;
	iceServers?: RTCIceServer[];
}

export interface JitsiLocalTrackOptions {
	devices?: string[];
	cameraDeviceId?: string;
	micDeviceId?: string;
	facingMode?: 'user' | 'environment';
	resolution?: number;
	frameRate?: number;
}

// Extensão do Window para BlobBuilder (polyfill)
export interface WindowWithBlobBuilder extends Window {
	BlobBuilder?: {
		new (): {
			append(data: Blob | string): void;
			getBlob(type?: string): Blob;
		};
	};
	webkitBlobBuilder?: {
		new (): {
			append(data: Blob | string): void;
			getBlob(type?: string): Blob;
		};
	};
	MozBlobBuilder?: {
		new (): {
			append(data: Blob | string): void;
			getBlob(type?: string): Blob;
		};
	};
}

// Tipo para API Jitsi (pode ser Connection ou Conference)
export type JitsiApi = JitsiConnection | JitsiConference | null;

// Declaração de módulo para lib-jitsi-meet
declare module 'lib-jitsi-meet' {
	export interface JitsiConnection {
		connect(): void;
		disconnect(): void;
		addEventListener(event: string, handler: (data?: unknown) => void): void;
		removeEventListener(event: string, handler: (data?: unknown) => void): void;
		initJitsiConference(roomName: string, options: Record<string, unknown>): JitsiConference;
	}

	export interface JitsiConference {
		join(): void;
		leave(): void;
		on(event: string, handler: (...args: unknown[]) => void): void;
		off(event: string, handler: (...args: unknown[]) => void): void;
		removeEventListener(event: string, handler: (...args: unknown[]) => void): void;
		muteAudio(): void;
		unmuteAudio(): void;
		muteVideo(): void;
		unmuteVideo(): void;
		getParticipants(): Map<string, JitsiParticipant>;
		getLocalTracks(): JitsiTrack[];
		setDisplayName(name: string): void;
		addTrack(track: JitsiTrack): Promise<void>;
		removeTrack(track: JitsiTrack): Promise<void>;
		getLocalVideoTrack(): JitsiTrack | null;
		getLocalAudioTrack(): JitsiTrack | null;
	}

	export interface JitsiTrack {
		getType(): 'audio' | 'video';
		isMuted(): boolean;
		mute(): Promise<void>;
		unmute(): Promise<void>;
		attach(element: HTMLElement): void;
		detach(element: HTMLElement): void;
		dispose(): Promise<void>;
		getParticipantId(): string;
		track: MediaStreamTrack;
		isLocal(): boolean;
		getVideoType(): 'camera' | 'desktop' | undefined;
	}

	export interface JitsiParticipant {
		getId(): string;
		getDisplayName(): string;
		isAudioMuted(): boolean;
		isVideoMuted(): boolean;
		getRole(): string;
	}

	export interface JitsiMeetJSLib {
		JitsiConnection: new (
			appId: string | null,
			token: string | null,
			options: JitsiConnectionOptions
		) => JitsiConnection;
		constants: {
			events: {
				connection: {
					CONNECTION_ESTABLISHED: string;
					CONNECTION_FAILED: string;
					CONNECTION_DISCONNECTED: string;
					WRONG_STATE: string;
				};
				conference: {
					USER_JOINED: string;
					USER_LEFT: string;
					TRACK_ADDED: string;
					TRACK_REMOVED: string;
					TRACK_MUTE_CHANGED: string;
					CONFERENCE_JOINED: string;
					CONFERENCE_LEFT: string;
					CONFERENCE_ERROR: string;
					DISPLAY_NAME_CHANGED: string;
					DOMINANT_SPEAKER_CHANGED: string;
				};
			};
			logLevels: {
				ERROR: number;
				WARN: number;
				INFO: number;
				DEBUG: number;
			};
		};
		init(options: JitsiInitOptions): void;
		setLogLevel(level: number): void;
		createLocalTracks(
			options: MediaStreamConstraints,
			advancedOptions?: JitsiLocalTrackOptions
		): Promise<JitsiTrack[]>;
		mediaDevices: {
			enumerateDevices(): Promise<MediaDeviceInfo[]>;
			isDeviceChangeAvailable(type: 'audio' | 'video'): Promise<boolean>;
		};
	}

	export interface JitsiConnectionOptions {
		hosts?: {
			domain?: string;
			muc?: string;
			focus?: string;
		};
		serviceUrl?: string;
		bosh?: string;
		websocket?: string;
		clientNode?: string;
		useStunTurn?: boolean;
		iceServers?: RTCIceServer[];
		enableLayerSuspension?: boolean;
		enableLipSync?: boolean;
		disableAudioLevels?: boolean;
		disableSimulcast?: boolean;
		enableRemb?: boolean;
		enableTcc?: boolean;
		useRoomAsSharedDocumentName?: boolean;
		enableStatsID?: boolean;
		channelLastN?: number;
		startBitrate?: number;
		stereo?: boolean;
		forcedVideoCodec?: string;
		preferredVideoCodec?: string;
		disableH264?: boolean;
		disableVP8?: boolean;
		disableVP9?: boolean;
		enableOpusRed?: boolean;
		enableDtmf?: boolean;
		openBridgeChannel?: string | boolean;
	}

	export interface JitsiInitOptions {
		disableAudioLevels?: boolean;
		disableSimulcast?: boolean;
		enableWindowOnErrorHandler?: boolean;
		enableRemb?: boolean;
		enableTcc?: boolean;
		disableThirdPartyRequests?: boolean;
		useStunTurn?: boolean;
		iceServers?: RTCIceServer[];
	}

	export interface JitsiLocalTrackOptions {
		devices?: string[];
		cameraDeviceId?: string;
		micDeviceId?: string;
		facingMode?: 'user' | 'environment';
		resolution?: number;
		frameRate?: number;
	}

	const JitsiMeetJS: JitsiMeetJSLib;
	export default JitsiMeetJS;
}
