/**
 * Type definitions for @mptransformation/omisdk
 * For use with ESLint in ReactJS projects
 */

declare module "@mptransformation/omisdk" {
  /**
   * Configuration options for the SDK
   */
  export interface SDKOptions {
    /** Target element ID where the SDK will be mounted */
    targetElementId?: string;
    /** Display mode for the SDK: 'none' (headless) or 'bubble' (UI visible) */
    mode?: SDKMode;
    /** Custom theme for the SDK */
    theme?: SDKTheme;
    /** Socket URL for real-time communication */
    baseUrl?: string;
    /** Debug mode flag */
    debug?: boolean;
    /** The remote audio media stream is attached to this element ID. */
    remoteAudioId?: string[];
    /** HTML elements ID for local media streams. */
    localVideoId?: string;
    /** The remote video media stream is attached to this element ID. */
    remoteVideoId?: string[];
    /** clear all saved info when init if true, default false */
    forceNew?: boolean;
  }

  /**
   * SDK display modes
   */
  export type SDKMode = "none" | "bubble";

  /**
   * Theme options for customizing the SDK appearance
   */
  export interface SDKTheme {
    /** Primary color */
    primaryColor?: string;
    /** Secondary color */
    secondaryColor?: string;
    /** Text color */
    textColor?: string;
    /** Background color */
    backgroundColor?: string;
    /** Font family */
    fontFamily?: string;
    /** Border radius for elements */
    borderRadius?: string;
    /** Bubble position (for bubble mode) */
    bubblePosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
    /** Custom CSS classes */
    customClasses?: Record<string, string>;
  }

  /**
   * Action event data
   */
  export interface SDKAction {
    /** Type of action */
    type: string;
    /** Payload data for the action */
    payload?: any;
    /** Timestamp when the action occurred */
    timestamp: number;
  }

  /**
   * Socket event data
   */
  export interface SocketEvent {
    /** Event name */
    name: string;
    /** Event data */
    data?: any;
    /** Timestamp when the event occurred */
    timestamp: number;
  }

  /**
   * Socket connection states
   */
  export enum SocketConnectionState {
    DISCONNECTED = "disconnected",
    CONNECTING = "connecting",
    CONNECTED = "connected",
    RECONNECTING = "reconnecting",
    RECONNECTION_FAILED = "reconnection_failed",
    NETWORK_ERROR = "network_connection_failed",
  }

  /**
   * Socket options for configuration
   */
  export interface SocketOptions {
    /** Whether to enable reconnection */
    reconnection?: boolean;
    /** Maximum number of reconnection attempts */
    reconnectionAttempts?: number;
    /** Delay between reconnection attempts in milliseconds */
    reconnectionDelay?: number;
    /** Connection timeout in milliseconds */
    timeout?: number;
    /** Whether to connect automatically on initialization */
    autoConnect?: boolean;
  }

  /**
   * Event emitter interface
   */
  export interface EventEmitter {
    /** Subscribe to an event */
    on(eventName: string, callback: (data: any) => void): void;
    /** Unsubscribe from an event */
    off(eventName: string, callback: (data: any) => void): void;
    /** Emit an event */
    emit(eventName: string, data: any): void;
  }

  export interface LoginRequest {
    tenantId: number;
    username: string;
    password: string;
  }

  export interface LoginSSORequest {
    ssoToken: string;
    organization: string;
  }

  export interface SdkResponse {
    success: boolean;
    message: string;
    data?: any;
  }

  export interface CallOptions {
    did?: string;
    enableVideo?: boolean;
    remoteVideoId?: string;
    localVideoId?: string;
    extraInfo?: string;
  }

  export interface SdkEvent {
    name: string;
    type?: any;
    timestamp: number;
  }

  export enum CallEventType {
    CALL_INCOMING = "call_incoming",
    CALL_OUTGOING = "call_outgoing",
    CALL_HANGUP = "call_hangup",
    CALL_ANSWERED = "call_answered",
    CALL_REJECTED = "call_rejected",
    CALL_HOLD = "call_hold",
    CALL_UNHOLD = "call_unhold",
    CALL_MUTE = "call_mute",
    CALL_UNMUTE = "call_unmute",
    CALL_TRANSFER = "call_transfer",
    CALL_CONNECTED = "call_connected",
    CALL_CLOSE_CONVERSATION = "call_close_conversation",
    CALL_REFUSE_TRANSFER = "call_refuse_transfer",
    CALL_ACCEPT_TRANSFER = "call_accept_transfer",
    CALL_TRANSFER_FAILED = "call_transfer_failed",
    CALL_TRANSFER_RINGING = "call_transfer_ringing",
    CALL_TRANSFER_ANSWER = "call_transfer_answer",
    CALL_TRANSFER_ACCEPTED = "call_transfer_accepted",
    CALL_TERMINATED_OR_IVR_MISSED = "call_terminated_or_ivr_missed",
  }

  export interface CallEvent extends SdkEvent {
    type: CallEventType;
    senderId: string;
    applicationId: string;
    channel?: string;
    direction?: string;
    hangupBy?: string;
    statusCode?: string;
    sessionId?: string;
  }

  export enum AgentStatusEventType {
    AGENT_STATUS_CHANGE = "agent_status_change",
  }

  export interface AgentStatusEvent extends SdkEvent {
    type: AgentStatusEventType;
    status: string;
    agentId: string;
    tenantId: string;
    changeTime: number;
    reasonCode: string;
    reasonCodeId: number;
  }

  export enum AppEventType {
    READY = "ready",
    DISPLAY_CHANGED = "display_changed",
    BUBBLE_HIDDEN = "bubble_hidden",
    BUBBLE_SHOWN = "bubble_shown",
    LOGGED_IN = "logged_in",
    LOGGED_OUT = "logged_out",
    TOKEN_EXPIRED = "token_expired",
    ERROR = "error",
    PERMISSION_DENIED = "permission_denied",
    NETWORK_ERROR = "network_error",
    DISCONNECTED = "disconnected",
    CONNECTED = "connected",
    DISCONNECTED_WEB_SOCKET = "disconnected_web_socket",
    CONNECTED_WEB_SOCKET = "connected_web_socket",
    AUTO_CONNECT = "auto_connect",
    NOT_AUTO_CONNECT = "not_auto_connect",
  }
  export interface AppEvent extends SdkEvent {
    type: AppEventType;
    message: string;
    error?: Error;
  }

  export interface InteractionEvent extends SdkEvent {
    type: InteractionEventType;
    message: string;
    senderId: string;
    applicationId: string;
    conversationId: string;
  }

  export enum InteractionEventType {
    NEW_CONVERSATION = "new_conversation",
    NEW_MESSAGE = "new_message",
    CLOSE_CONVERSATION = "close_conversation",
    MESSAGE_RECEIVED = "message_received",
    MESSAGE_SENT = "message_sent",
    MESSAGE_DELIVERED = "message_delivered",
    MESSAGE_READ = "message_read",
    CONVERSATION_ENDED = "conversation_ended",
  }

  export enum DestinationType {
    AGENT = "AGENT",
    QUEUE = "QUEUE",
    EXTERNAL = "EXTERNAL",
  }

  export enum TransferType {
    BLIND_TRANSFER = "BLIND_TRANSFER",
    ATTENDED_TRANSFER = "ATTENDED_TRANSFER",
  }

  export type UserInfo = {
    tenantId?: number;
    userId: number;
    userName: string;
    fullName: string;
    extension?: string;
  };
  /**
   * SDK instance interface
   */
  export interface SDK {
    /** Initialize the SDK with options */
    init(options?: SDKOptions): void;
    /** Login with username and password **/
    login(request: LoginRequest): Promise<SdkResponse>;
    /** Login with SSO token**/
    loginSSO(request: LoginSSORequest): Promise<SdkResponse>;
    /** Logout the current user**/
    logout(): Promise<SdkResponse>;
    /** Make a call to a destination**/
    makeCall(destination: string, options?: CallOptions): Promise<SdkResponse>;
    /** Hangup the current call**/
    hangup(): Promise<SdkResponse>;
    /** Answer an incoming call**/
    answerCall(options?: CallOptions): Promise<SdkResponse>;
    /** Reject an incoming call**/
    rejectCall(): Promise<SdkResponse>;
    /** Hold the current call**/
    hold(): Promise<SdkResponse>;
    /** Resume the current call**/
    unhold(): Promise<SdkResponse>;
    /** Mute the current call**/
    mute(): Promise<SdkResponse>;
    /** Unmute the current call**/
    unmute(): Promise<SdkResponse>;
    /** Turn on the camera**/
    cameraOn(): Promise<SdkResponse>;
    /** Turn off the camera**/
    cameraOff(): Promise<SdkResponse>;
    /** get current status of agent **/
    getCurrentStatus(): Promise<SdkResponse>;
    /** Transfer the current call to a different destination**/
    transfer(
      destination: string,
      destinationType: DestinationType,
      transferType: TransferType
    ): void;
    /** Change the agent status**/
    changeAgentStatus(reasonCodeId: number): Promise<SdkResponse>;
    /** Get the agent status**/
    getAgentStatus(): Promise<SdkResponse>;
    /** Hide the bubble**/
    hideBubble(): Promise<SdkResponse>;
    /** Show the bubble**/
    showBubble(): Promise<SdkResponse>;
    /** Destroy the SDK instance and clean up resources */
    destroy(): void;
    /** Update SDK options */
    updateOptions(options: Partial<SDKOptions>): void;
    /** Get the current SDK version */
    getVersion(): string;
    /** Get the current SDK options */
    getOptions(): SDKOptions;
    /** Subscribe to an event */
    on(eventName: string, callback: (data: SdkEvent) => void): void;
    /** Unsubscribe from an event */
    off(eventName: string, callback: (data: SdkEvent) => void): void;
    /** Get the agent queues**/
    getAgentQueues(): Promise<SdkResponse>;
    /** Toggle the agent queue**/
    toggleAgentQueue(queueId: string, enable: boolean): Promise<SdkResponse>;
    /** close conversation of agent**/
    closeSession(): void;
    /** call internal **/
    makeCallInternal(
      destination: string,
      extraInfo?: string
    ): Promise<SdkResponse>;
    acceptTransfer(): void;
    refuseTransfer(): void;
    getInfo(): UserInfo;
    /** get group agents **/
    getGroupAgents(): Promise<SdkResponse>;
    /** get agent by extension **/
    getAgentByExtension(queueExtension: string): Promise<SdkResponse>;
    /** get agent by id **/
    getAgentQueuesById(queueId: string): Promise<SdkResponse>;
    customHangup(sessionId: string): void;
  }

  // Export the OmiSDK class
  export class OmiSDK implements SDK {
    constructor(options?: SDKOptions);
    /** Initialize the SDK with options */
    init(options?: SDKOptions): void;
    /** Login with username and password **/
    login(request: LoginRequest): Promise<SdkResponse>;
    /** Login with SSO token**/
    loginSSO(request: LoginSSORequest): Promise<SdkResponse>;
    /** Logout the current user**/
    logout(): Promise<SdkResponse>;
    /** Make a call to a destination**/
    makeCall(destination: string, options?: CallOptions): Promise<SdkResponse>;
    /** Hangup the current call**/
    hangup(): Promise<SdkResponse>;
    /** Answer an incoming call**/
    answerCall(options?: CallOptions): Promise<SdkResponse>;
    /** Reject an incoming call**/
    rejectCall(): Promise<SdkResponse>;
    /** Hold the current call**/
    hold(): Promise<SdkResponse>;
    /** Resume the current call**/
    unhold(): Promise<SdkResponse>;
    /** Mute the current call**/
    mute(): Promise<SdkResponse>;
    /** Unmute the current call**/
    unmute(): Promise<SdkResponse>;
    /** Turn on the camera**/
    cameraOn(): Promise<SdkResponse>;
    /** Turn off the camera**/
    cameraOff(): Promise<SdkResponse>;
    /** get current status of agent **/
    getCurrentStatus(): Promise<SdkResponse>;
    /** Transfer the current call to a different destination**/
    transfer(
      destination: string,
      destinationType: DestinationType,
      transferType: TransferType
    ): void;
    /** Change the agent status**/
    changeAgentStatus(reasonCodeId: number): Promise<SdkResponse>;
    /** Get the agent status**/
    getAgentStatus(): Promise<SdkResponse>;
    /** Hide the bubble**/
    hideBubble(): Promise<SdkResponse>;
    /** Show the bubble**/
    showBubble(): Promise<SdkResponse>;
    /** Destroy the SDK instance and clean up resources */
    destroy(): void;
    /** Update SDK options */
    updateOptions(options: Partial<SDKOptions>): void;
    /** Get the current SDK version */
    getVersion(): string;
    /** Get the current SDK options */
    getOptions(): SDKOptions;
    /** Subscribe to an event */
    on(eventName: string, callback: (data: SdkEvent) => void): void;
    /** Unsubscribe from an event */
    off(eventName: string, callback: (data: SdkEvent) => void): void;
    /** Get the agent queues**/
    getAgentQueues(): Promise<SdkResponse>;
    /** Toggle the agent queue**/
    toggleAgentQueue(queueId: string, enable: boolean): Promise<SdkResponse>;
    /** close conversation of agent**/
    closeSession(): void;
    /** call internal **/
    makeCallInternal(
      destination: string,
      extraInfo?: string
    ): Promise<SdkResponse>;
    acceptTransfer(): void;
    refuseTransfer(): void;
    getInfo(): UserInfo;
    /** get group agents **/
    getGroupAgents(): Promise<SdkResponse>;
    /** get agent by extension **/
    getAgentByExtension(queueExtension: string): Promise<SdkResponse>;
    /** get agent by id **/
    getAgentQueuesById(queueId: string): Promise<SdkResponse>;
    customHangup(sessionId: string): void;
  }

  // Export the default instance
  const sdkInstance: SDK;
  export default sdkInstance;
}

// Declare global types
declare global {
  interface Window {
    omisdk: import("@mptransformation/omisdk").SDK;
  }
}
