import { GlobalFunctions, TransferAreaProperties } from '@/GlobalFunctions';
import { apiService } from './api';

/**
 * Tipos de vozes disponíveis para geração de áudio
 */
export type VoiceType = 'alloy' | 'echo' | 'fable' | 'nova' | 'onyx' | 'shimmer';

/**
 * Interface para a resposta da API de geração de áudio
 */
export interface AudioGenerationResponse {
  success: boolean;
  audio_url: string; // URL do áudio gerado
  audio_generation_id: string;
  message: string; // Texto que foi convertido em áudio
}

/**
 * Interface para um áudio armazenado no banco de dados
 */
export interface AudioRecord {
  id: string;
  user_email: string;
  estabelecimento_id: number;
  input_text: string;
  model: string;
  voice: VoiceType;
  audio_url: string;
  duration_seconds: number | null;
  file_size: number;
  cost_usd: string;
  created_at: string;
}

/**
 * Interface para os dados necessários para geração de áudio
 */
export interface AudioGenerationRequest {
  message: string;
  voice: VoiceType;
  userEmail?: string;
  estabelecimentoId?: number;
}

/**
 * Informações sobre cada tipo de voz disponível
 */
export const VOICE_OPTIONS = {
  alloy: {
    label: "Alloy",
    gender: "Masculina",
    style: "Neutra, equilibrada, tom corporativo",
    description: "Boa para tutoriais e comunicações institucionais."
  },
  echo: {
    label: "Echo",
    gender: "Masculina",
    style: "Forte e profissional, mais grave",
    description: "Ideal para voz de autoridade ou locução firme."
  },
  fable: {
    label: "Fable",
    gender: "Feminina",
    style: "Narrativa, calorosa e envolvente",
    description: "Ótima para storytelling e áudios empáticos."
  },
  onyx: {
    label: "Onyx",
    gender: "Masculina",
    style: "Grave, autoritária, impactante",
    description: "Excelente para trailers, mensagens sérias ou institucionais."
  },
  nova: {
    label: "Nova",
    gender: "Feminina",
    style: "Brilhante, animada, energética",
    description: "Boa para vídeos curtos, marketing ou conteúdos leves."
  },
  shimmer: {
    label: "Shimmer",
    gender: "Feminina",
    style: "Suave, otimista, clara",
    description: "Boa para mensagens acolhedoras, explicações e IA conversacional."
  }
} as const;

/**
 * Serviço de geração de áudio (Text-to-Speech)
 */
class AudioGenerationService {
  private readonly AUDIO_GENERATION_ENDPOINT = '/webhook/codex/gerar_audio';
  private readonly GET_AUDIOS_ENDPOINT = '/webhook/fd073ec0-81ab-4681-8acd-b0da71f6ad30/codex/get_gerar_audios';
  private readonly DELETE_AUDIO_ENDPOINT = '/webhook/fd073ec0-81ab-4681-8acd-b0da71f6ad30/codex/delete_gerar_audio';

  /**
   * Gera um arquivo de áudio a partir de texto
   *
   * @param request - Dados da requisição (texto, voz, email, estabelecimento)
   * @returns Promise com a resposta da API
   */
  async generateAudio(request: AudioGenerationRequest): Promise<AudioGenerationResponse> {
    const { message, voice, userEmail, estabelecimentoId } = request;

    // Usa valores do .env se não forem fornecidos
    const email = GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);//userEmail || import.meta.env.VITE_USER_EMAIL || '';
    const estabId = GlobalFunctions.getTransferProperty(TransferAreaProperties.EstabelecimentoCodigo);//estabelecimentoId || parseInt(import.meta.env.VITE_ESTABELECIMENTO_ID) || 1;

    // Valida o texto
    if (!message || message.trim().length === 0) {
      throw {
        success: false,
        message: 'O texto não pode estar vazio',
      };
    }

    // Valida a voz
    if (!this.isValidVoice(voice)) {
      throw {
        success: false,
        message: `Voz inválida. Opções disponíveis: ${Object.keys(VOICE_OPTIONS).join(', ')}`,
      };
    }

    // Log para debug (remover em produção se necessário)
    console.log('Gerando áudio:', {
      messageLength: message.length,
      voice,
      userEmail: email,
      estabelecimentoId: estabId,
    });

    try {
      // Faz a requisição usando o serviço de API
      const response = await apiService.post<AudioGenerationResponse>(
        this.AUDIO_GENERATION_ENDPOINT,
        {
          estabelecimento_id: estabId,
          user_email: email,
          message: message,
          voice: voice,
        }
      );

      return response.data;
    } catch (error: any) {
      // Trata erros específicos
      console.error('Erro na geração de áudio:', error);

      throw {
        success: false,
        message: error.message || 'Erro ao gerar áudio',
        status: error.status,
      };
    }
  }

  /**
   * Valida se a voz selecionada é suportada
   *
   * @param voice - Voz a ser validada
   * @returns true se a voz é válida
   */
  isValidVoice(voice: string): voice is VoiceType {
    return Object.keys(VOICE_OPTIONS).includes(voice);
  }

  /**
   * Obtém informações sobre uma voz específica
   *
   * @param voice - Tipo de voz
   * @returns Informações da voz
   */
  getVoiceInfo(voice: VoiceType) {
    return VOICE_OPTIONS[voice];
  }

  /**
   * Lista todas as vozes disponíveis
   *
   * @returns Array com todas as opções de voz
   */
  getAllVoices() {
    return Object.entries(VOICE_OPTIONS).map(([key, info]) => ({
      value: key as VoiceType,
      ...info,
    }));
  }

  /**
   * Valida o texto para geração de áudio
   *
   * @param text - Texto a ser validado
   * @param maxLength - Comprimento máximo (padrão: 4096 caracteres)
   * @returns Objeto com resultado da validação
   */
  validateText(text: string, maxLength: number = 4096): { valid: boolean; error?: string } {
    if (!text || text.trim().length === 0) {
      return {
        valid: false,
        error: 'O texto não pode estar vazio',
      };
    }

    if (text.length > maxLength) {
      return {
        valid: false,
        error: `O texto é muito longo. Máximo: ${maxLength} caracteres`,
      };
    }

    return { valid: true };
  }

  /**
   * Lista áudios do banco de dados com paginação
   *
   * @param userEmail - Email do usuário
   * @param page - Número da página (padrão: 1)
   * @param perPage - Quantidade de itens por página (padrão: 10)
   * @returns Promise com o array de áudios
   */
  async getAudios(
    userEmail?: string,
    page: number = 1,
    perPage: number = 10
  ): Promise<AudioRecord[]> {
    // Usa valores do GlobalFunctions se não forem fornecidos
    const email = userEmail || GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);

    if (!email) {
      throw {
        success: false,
        message: 'Email do usuário não fornecido',
      };
    }

    console.log('Buscando áudios:', {
      userEmail: email,
      page,
      perPage,
    });

    try {
      // Faz a requisição GET com parâmetros na URL e query
      const response = await apiService.get<AudioRecord[]>(
        `${this.GET_AUDIOS_ENDPOINT}/${email}`,
        {
          params: {
            page: page.toString(),
            per_page: perPage.toString(),
          },
        }
      );

      console.log('Resposta completa da API:', response);
      console.log('response.data:', response.data);
      console.log('É array?:', Array.isArray(response.data));

      // A API retorna diretamente o array de áudios
      // Garante que sempre retorna um array
      if (Array.isArray(response.data)) {
        return response.data;
      } else if (response.data && typeof response.data === 'object') {
        // Se a resposta for um objeto com uma propriedade 'audios' ou similar
        console.warn('API retornou objeto em vez de array:', response.data);

        // Tenta encontrar o array dentro do objeto
        if (Array.isArray((response.data as any).audios)) {
          return (response.data as any).audios;
        } else if (Array.isArray((response.data as any).data)) {
          return (response.data as any).data;
        }
      }

      // Se não conseguir extrair array, retorna vazio
      console.warn('Não foi possível extrair array de áudios da resposta');
      return [];
    } catch (error: any) {
      console.error('Erro ao buscar áudios:', error);

      throw {
        success: false,
        message: error.message || 'Erro ao buscar áudios',
        status: error.status,
      };
    }
  }

  /**
   * Deleta um áudio do banco de dados
   *
   * @param audioId - ID do áudio a ser deletado
   * @param userEmail - Email do usuário (opcional)
   * @returns Promise com sucesso ou erro
   */
  async deleteAudio(audioId: string, userEmail?: string): Promise<{ success: boolean; message?: string }> {
    // Usa valores do GlobalFunctions se não forem fornecidos
    const email = userEmail || GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);

    if (!email) {
      throw {
        success: false,
        message: 'Email do usuário não fornecido',
      };
    }

    if (!audioId) {
      throw {
        success: false,
        message: 'ID do áudio não fornecido',
      };
    }

    console.log('Deletando áudio:', {
      audioId,
      userEmail: email,
    });

    try {
      // Faz a requisição DELETE com parâmetros na URL
      const response = await apiService.delete<{ success: boolean; message?: string } | Array<{ success: boolean; message?: string }>>(
        `${this.DELETE_AUDIO_ENDPOINT}/${email}/${audioId}`
      );

      console.log('Resposta completa do DELETE:', response);
      console.log('response.data:', response.data);

      // A API retorna um array com um objeto: [{"success":true}]
      let result: { success: boolean; message?: string };

      if (Array.isArray(response.data)) {
        // Se for array, pega o primeiro elemento
        result = response.data[0];
        console.log('API retornou array, usando primeiro elemento:', result);
      } else {
        // Se for objeto direto
        result = response.data;
        console.log('API retornou objeto direto:', result);
      }

      // Garante que tem a estrutura mínima
      return {
        success: result.success ?? true,
        message: result.message || 'Áudio deletado com sucesso',
      };
    } catch (error: any) {
      console.error('Erro ao deletar áudio:', error);

      throw {
        success: false,
        message: error.message || 'Erro ao deletar áudio',
        status: error.status,
      };
    }
  }
}

// Exporta instância única (Singleton)
export const audioGenerationService = new AudioGenerationService();
