import WebSocket from 'ws';

type PhonicConfig = {
    baseUrl?: string;
    headers?: Record<string, string>;
    __downstreamWebSocketUrl?: string;
};
type FetchOptions = {
    method: "GET";
    headers?: Record<string, string>;
} | {
    method: "POST";
    headers?: Record<string, string>;
    body: string;
};
type DataOrError<T> = Promise<{
    data: T;
    error: null;
} | {
    data: null;
    error: {
        message: string;
        code?: string;
    };
}>;
type ISODate = `${string}-${string}-${string}`;
type ISODateTime$1 = `${string}Z`;

type ISODateTime = `${string}Z`;
type ConversationItem = {
    role: "user";
    item_idx: number;
    text: string;
    duration_ms: number;
    started_at: string;
} | {
    role: "assistant";
    item_idx: number;
    text: string;
    voice_id: string;
    system_prompt: string;
    output_audio_speed: number;
    duration_ms: number;
    started_at: string;
};
type Conversation = {
    id: string;
    external_id: string | null;
    model: string;
    welcome_message: string | null;
    input_format: "pcm_44100" | "mulaw_8000";
    output_format: "pcm_44100" | "mulaw_8000";
    text: string;
    duration_ms: number;
    started_at: ISODateTime;
    ended_at: ISODateTime;
    items: Array<ConversationItem>;
};
type ConversationSuccessResponse = {
    conversation: Conversation;
};
type ConversationsSuccessResponse = {
    conversations: Array<Conversation>;
};

declare class Conversations {
    private readonly phonic;
    constructor(phonic: Phonic);
    get(id: string): DataOrError<ConversationSuccessResponse>;
    getByExternalId({ project, externalId, }: {
        project?: string;
        externalId: string;
    }): DataOrError<ConversationSuccessResponse>;
    list({ project, durationMin, durationMax, startedAtMin, startedAtMax, }: {
        project?: string;
        durationMin?: number;
        durationMax?: number;
        startedAtMin?: ISODate | ISODateTime$1;
        startedAtMax?: ISODate | ISODateTime$1;
    }): DataOrError<ConversationsSuccessResponse>;
}

type PhonicSTSTool = "send_dtmf_tone" | "end_conversation";
type PhonicSTSConfig = {
    project: string;
    input_format: "pcm_44100" | "mulaw_8000";
    system_prompt?: string;
    welcome_message?: string;
    voice_id?: string;
    output_format?: "pcm_44100" | "mulaw_8000";
    enable_silent_audio_fallback?: boolean;
    experimental_params?: Record<string, unknown>;
    tools?: Array<PhonicSTSTool>;
    vad_prebuffer_duration_ms?: number;
    vad_min_speech_duration_ms?: number;
    vad_min_silence_duration_ms?: number;
    vad_threshold?: number;
};
type PhonicSTSWebSocketResponseMessage = {
    type: "ready_to_start_conversation";
} | {
    type: "input_text";
    text: string;
} | {
    type: "audio_chunk";
    text: string;
    audio: string;
} | {
    type: "is_user_speaking";
    isUserSpeaking: boolean;
} | {
    type: "interrupted_response";
    interruptedResponse: string;
} | {
    type: "assistant_ended_conversation";
} | {
    type: "error";
    error: {
        message: string;
        code?: string;
    };
    param_errors?: {
        input_format?: string;
        system_prompt?: string;
        welcome_message?: string;
        voice_id?: string;
        output_format?: string;
    };
};
type OnMessageCallback = (message: PhonicSTSWebSocketResponseMessage) => void;
type OnCloseCallback = (event: WebSocket.CloseEvent) => void;
type OnErrorCallback = (event: WebSocket.ErrorEvent) => void;
type PhonicSTSOutboundCallConfig = Omit<PhonicSTSConfig, "input_format" | "output_format">;
type OutboundCallSuccessResponse = {
    success: true;
};
type PhonicTool = "send_dtmf_tone" | "end_conversation";
type PhonicConfigurationEndpointRequestPayload = {
    project: {
        name: string;
    };
    agent: {
        name: string;
        welcome_message: string;
        system_prompt: string;
        tools: Array<PhonicTool>;
        boosted_keywords: string[];
    };
    from_phone_number?: string;
    to_phone_number?: string;
};
type PhonicConfigurationEndpointResponsePayload = {
    welcome_message?: string | null;
    system_prompt?: string;
    tools?: Array<PhonicTool>;
    boosted_keywords?: string[];
};

type PhonicSTSTwilioOutboundCallParams = {
    account_sid: string;
    api_key_sid: string;
    api_key_secret: string;
    from_phone_number: string;
    to_phone_number: string;
};
type PhonicSTSTwilioOutboundCallConfig = PhonicSTSOutboundCallConfig;
type TwilioOutboundCallSuccessResponse = {
    success: true;
    callSid: string;
};

declare class Twilio {
    private readonly phonic;
    constructor(phonic: Phonic);
    outboundCall(params: PhonicSTSTwilioOutboundCallParams, config: PhonicSTSTwilioOutboundCallConfig): DataOrError<TwilioOutboundCallSuccessResponse>;
}

declare class PhonicSTSWebSocket {
    private readonly ws;
    private readonly config;
    private onMessageCallback;
    private onCloseCallback;
    private onErrorCallback;
    private buffer;
    private isOpen;
    constructor(ws: WebSocket, config: PhonicSTSConfig);
    onMessage(callback: OnMessageCallback): void;
    onClose(callback: OnCloseCallback): void;
    onError(callback: OnErrorCallback): void;
    audioChunk({ audio }: {
        audio: string;
    }): void;
    updateSystemPrompt({ systemPrompt }: {
        systemPrompt: string;
    }): void;
    setExternalId({ externalId }: {
        externalId: string;
    }): void;
    close(code?: number): void;
}

declare class SpeechToSpeech {
    private readonly phonic;
    readonly twilio: Twilio;
    constructor(phonic: Phonic);
    websocket(config: PhonicSTSConfig): PhonicSTSWebSocket;
    outboundCall(toPhoneNumber: string, config: PhonicSTSOutboundCallConfig): DataOrError<OutboundCallSuccessResponse>;
}

type Voice = {
    id: string;
    name: string;
};
type VoicesSuccessResponse = {
    voices: Array<Voice>;
};
type VoiceSuccessResponse = {
    voice: Voice;
};

declare class Voices {
    private readonly phonic;
    constructor(phonic: Phonic);
    list({ model }: {
        model: string;
    }): DataOrError<VoicesSuccessResponse>;
    get(id: string): DataOrError<VoiceSuccessResponse>;
}

declare class Phonic {
    readonly apiKey: string;
    readonly baseUrl: string;
    readonly __downstreamWebSocketUrl: string | null;
    readonly headers: Record<string, string>;
    readonly conversations: Conversations;
    readonly voices: Voices;
    readonly sts: SpeechToSpeech;
    constructor(apiKey: string, config?: PhonicConfig);
    fetchRequest<T>(path: string, options: FetchOptions): DataOrError<T>;
    get<T>(path: string): Promise<{
        data: null;
        error: {
            message: string;
            code?: string;
        };
    } | {
        data: T;
        error: null;
    }>;
    post<T>(path: string, body: Record<string, unknown>, headers?: Record<string, string>): Promise<{
        data: null;
        error: {
            message: string;
            code?: string;
        };
    } | {
        data: T;
        error: null;
    }>;
}

export { Phonic, type PhonicConfigurationEndpointRequestPayload, type PhonicConfigurationEndpointResponsePayload, type PhonicSTSConfig, PhonicSTSWebSocket };
