/**
 * ElevenLabs Knowledge Base Service
 *
 * Uploads documents to ElevenLabs KB and links them to agents.
 * Uses the v1 two-step flow: create text document, then link to agent.
 */

import { logger } from '@/lib/logger';

export interface KBDocumentRef {
  id: string;
  name: string;
}

export class ElevenLabsKBService {
  private baseUrl = 'https://api.elevenlabs.io/v1';

  private getApiKey(): string {
    const apiKey = process.env.ELEVENLABS_API_KEY;
    if (!apiKey) throw new Error('ELEVENLABS_API_KEY environment variable is required');
    return apiKey;
  }

  /**
   * Step 1: Create a standalone text document in the KB
   */
  async createTextDocument(
    name: string,
    content: string
  ): Promise<{ id: string } | { error: string }> {
    try {
      logger.info('Creating text document in ElevenLabs KB', { name });

      const response = await fetch(`${this.baseUrl}/convai/knowledge-base/text`, {
        method: 'POST',
        headers: {
          'xi-api-key': this.getApiKey(),
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ text: content, name }),
      });

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}));
        logger.error('Failed to create text document', new Error(response.statusText), {
          status: response.status,
          errorData,
        });
        return { error: `Create failed: ${response.status} ${response.statusText}` };
      }

      const result = await response.json();
      const docId = result.id;
      logger.info('Text document created in ElevenLabs KB', { documentId: docId });
      return { id: docId };
    } catch (error) {
      logger.error('Error creating text document in ElevenLabs KB', error);
      return { error: 'Failed to create text document' };
    }
  }

  /**
   * Step 2: Link documents to an agent's knowledge base via PATCH
   */
  async linkDocumentsToAgent(
    agentId: string,
    documents: KBDocumentRef[]
  ): Promise<{ success: boolean; error?: string }> {
    try {
      logger.info('Linking documents to ElevenLabs agent', {
        agentId,
        documentCount: documents.length,
      });

      const response = await fetch(`${this.baseUrl}/convai/agents/${agentId}`, {
        method: 'PATCH',
        headers: {
          'xi-api-key': this.getApiKey(),
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          conversation_config: {
            agent: {
              prompt: {
                knowledge_base: documents.map(d => ({
                  type: 'text',
                  id: d.id,
                  name: d.name,
                  usage_mode: 'auto',
                })),
                rag: {
                  enabled: true,
                  embedding_model: 'multilingual_e5_large_instruct',
                },
              },
            },
          },
        }),
      });

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}));
        logger.error('Failed to link documents to agent', new Error(response.statusText), {
          status: response.status,
          errorData,
        });
        return { success: false, error: `Link failed: ${response.status} ${response.statusText}` };
      }

      logger.info('Documents linked to ElevenLabs agent', { agentId });
      return { success: true };
    } catch (error) {
      logger.error('Error linking documents to agent', error);
      return { success: false, error: 'Failed to link documents to agent' };
    }
  }

  /**
   * Upload a document to ElevenLabs knowledge base (backward-compatible).
   * Internally uses the two-step flow: create text doc, then link to agent.
   */
  async uploadDocument(params: {
    agentId: string;
    name: string;
    content: string;
    mimeType?: string;
  }): Promise<{ documentId: string } | { error: string }> {
    try {
      logger.info('Uploading document to ElevenLabs KB', {
        agentId: params.agentId,
        name: params.name,
      });

      // Step 1: Create the text document
      const createResult = await this.createTextDocument(params.name, params.content);
      if ('error' in createResult) {
        return { error: createResult.error };
      }

      // Step 2: Link it to the agent
      const linkResult = await this.linkDocumentsToAgent(params.agentId, [
        { id: createResult.id, name: params.name },
      ]);
      if (!linkResult.success) {
        return { error: linkResult.error || 'Failed to link document to agent' };
      }

      return { documentId: createResult.id };
    } catch (error) {
      logger.error('Error uploading document to ElevenLabs KB', error);
      return { error: 'Failed to upload document' };
    }
  }

  /**
   * Delete a standalone document from ElevenLabs knowledge base
   */
  async deleteDocument(_agentId: string, documentId: string): Promise<{ success: boolean; error?: string }> {
    try {
      const response = await fetch(
        `${this.baseUrl}/convai/knowledge-base/${documentId}`,
        {
          method: 'DELETE',
          headers: {
            'xi-api-key': this.getApiKey(),
          },
        }
      );

      if (!response.ok) {
        return { success: false, error: `Delete failed: ${response.statusText}` };
      }

      logger.info('Deleted document from ElevenLabs KB', { documentId });
      return { success: true };
    } catch (error) {
      logger.error('Error deleting document from ElevenLabs KB', error);
      return { success: false, error: 'Failed to delete document' };
    }
  }
}

export const elevenLabsKBService = new ElevenLabsKBService();
