/**
 * ElevenLabs Pronunciation Dictionary Service
 *
 * Manages pronunciation dictionaries and rules for voice agents.
 * Supports alias and phoneme-based pronunciation overrides.
 */

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

export interface PronunciationRule {
  stringToReplace: string;
  type: 'phoneme' | 'alias';
  phoneme?: string;
  alias?: string;
  alphabet?: 'ipa' | 'cmu-arpabet' | 'x-sampa';
}

export interface PronunciationDictionary {
  id: string;
  name: string;
  rules: PronunciationRule[];
}

/** Common GCC business pronunciation presets */
export const GCC_PRONUNCIATION_PRESETS: PronunciationRule[] = [
  { stringToReplace: 'Mawidi', type: 'alias', alias: 'Mah-wee-dee' },
  { stringToReplace: 'QAR', type: 'alias', alias: 'Qatari Riyal' },
  { stringToReplace: 'SAR', type: 'alias', alias: 'Saudi Riyal' },
  { stringToReplace: 'AED', type: 'alias', alias: 'UAE Dirham' },
  { stringToReplace: 'Doha', type: 'alias', alias: 'Doh-ha' },
  { stringToReplace: 'Riyadh', type: 'alias', alias: 'Ree-yaad' },
  { stringToReplace: 'Jeddah', type: 'alias', alias: 'Jed-dah' },
  { stringToReplace: 'Abu Dhabi', type: 'alias', alias: 'Ah-boo Dah-bee' },
  { stringToReplace: 'Dammam', type: 'alias', alias: 'Dahm-mahm' },
  { stringToReplace: 'Muscat', type: 'alias', alias: 'Mus-kat' },
];

export class ElevenLabsPronunciationService {
  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;
  }

  /**
   * Create a pronunciation dictionary with initial rules
   */
  async createDictionary(
    name: string,
    rules: PronunciationRule[]
  ): Promise<{ id: string } | { error: string }> {
    try {
      logger.info('Creating pronunciation dictionary', { name, ruleCount: rules.length });

      const response = await fetch(
        `${this.baseUrl}/pronunciation-dictionaries/add-from-rules`,
        {
          method: 'POST',
          headers: {
            'xi-api-key': this.getApiKey(),
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            name,
            rules: rules.map(r => ({
              string_to_replace: r.stringToReplace,
              type: r.type,
              ...(r.type === 'phoneme' ? { phoneme: r.phoneme, alphabet: r.alphabet || 'ipa' } : {}),
              ...(r.type === 'alias' ? { alias: r.alias } : {}),
            })),
          }),
        }
      );

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

      const result = await response.json();
      logger.info('Pronunciation dictionary created', { id: result.id });
      return { id: result.id };
    } catch (error) {
      logger.error('Error creating pronunciation dictionary', error);
      return { error: 'Failed to create pronunciation dictionary' };
    }
  }

  /**
   * Add rules to an existing dictionary
   */
  async addRules(
    dictId: string,
    rules: PronunciationRule[]
  ): Promise<{ success: boolean; error?: string }> {
    try {
      logger.info('Adding pronunciation rules', { dictId, ruleCount: rules.length });

      const response = await fetch(
        `${this.baseUrl}/pronunciation-dictionaries/${dictId}/add-rules`,
        {
          method: 'POST',
          headers: {
            'xi-api-key': this.getApiKey(),
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            rules: rules.map(r => ({
              string_to_replace: r.stringToReplace,
              type: r.type,
              ...(r.type === 'phoneme' ? { phoneme: r.phoneme, alphabet: r.alphabet || 'ipa' } : {}),
              ...(r.type === 'alias' ? { alias: r.alias } : {}),
            })),
          }),
        }
      );

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

      logger.info('Pronunciation rules added', { dictId });
      return { success: true };
    } catch (error) {
      logger.error('Error adding pronunciation rules', error);
      return { success: false, error: 'Failed to add pronunciation rules' };
    }
  }

  /**
   * Remove a rule from a dictionary
   */
  async removeRule(
    dictId: string,
    ruleString: string
  ): Promise<{ success: boolean; error?: string }> {
    try {
      const response = await fetch(
        `${this.baseUrl}/pronunciation-dictionaries/${dictId}/remove-rules`,
        {
          method: 'POST',
          headers: {
            'xi-api-key': this.getApiKey(),
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            rule_strings: [ruleString],
          }),
        }
      );

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

      return { success: true };
    } catch (error) {
      logger.error('Error removing pronunciation rule', error);
      return { success: false, error: 'Failed to remove pronunciation rule' };
    }
  }

  /**
   * Link a pronunciation dictionary to an agent
   */
  async linkToAgent(
    agentId: string,
    dictId: string
  ): Promise<{ success: boolean; error?: string }> {
    try {
      logger.info('Linking pronunciation dictionary to agent', { agentId, dictId });

      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: {
            tts: {
              pronunciation_dictionary_locators: [
                { pronunciation_dictionary_id: dictId },
              ],
            },
          },
        }),
      });

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

      logger.info('Pronunciation dictionary linked to agent', { agentId, dictId });
      return { success: true };
    } catch (error) {
      logger.error('Error linking pronunciation dictionary', error);
      return { success: false, error: 'Failed to link pronunciation dictionary' };
    }
  }
}

export const elevenLabsPronunciationService = new ElevenLabsPronunciationService();
