/**
 * Voice Agent Database Utilities
 *
 * Helper functions for managing voice agent data in the database
 * Uses the existing ConversationLog model for voice call transcripts
 */

import { prisma } from '@/lib/db';
import { logger } from '@/lib/logger';
import { VoiceAgentConfig } from '@/lib/types/voice-agent.types';
import { createId } from '@paralleldrive/cuid2';

/**
 * Update user's voice agent ID and configuration
 */
export async function updateUserVoiceAgent(
  userId: string,
  agentId: string,
  config: VoiceAgentConfig
): Promise<void> {
  try {
    // Update in Prisma
    await prisma.users.update({
      where: { id: userId },
      data: {
        voiceAgentId: agentId,
        voiceAgentConfig: config as any,
        updatedAt: new Date(),
      },
    });

    logger.info('Updated user voice agent', { userId, agentId });
  } catch (error) {
    logger.error('Error updating user voice agent', error, { userId });
    throw error;
  }
}

/**
 * Clear user's voice agent configuration
 */
export async function clearUserVoiceAgent(userId: string): Promise<void> {
  try {
    // Clear in Prisma
    await prisma.users.update({
      where: { id: userId },
      data: {
        voiceAgentId: null,
        voiceAgentConfig: null,
        updatedAt: new Date(),
      },
    });

    logger.info('Cleared user voice agent', { userId });
  } catch (error) {
    logger.error('Error clearing user voice agent', error, { userId });
    throw error;
  }
}

/**
 * Get user's voice agent configuration
 */
export async function getUserVoiceAgent(userId: string): Promise<{
  agentId: string | null;
  config: VoiceAgentConfig | null;
} | null> {
  try {
    const user = await prisma.users.findUnique({
      where: { id: userId },
      select: {
        voiceAgentId: true,
        voiceAgentConfig: true,
      },
    });

    if (!user) {
      return null;
    }

    return {
      agentId: user.voiceAgentId,
      config: user.voiceAgentConfig as VoiceAgentConfig | null,
    };
  } catch (error) {
    logger.error('Error getting user voice agent', error, { userId });
    throw error;
  }
}

/**
 * Save voice call conversation to ConversationLog
 * Uses the existing ConversationLog model with platform='voice'
 */
export async function saveVoiceConversationLog(data: {
  userId: string;
  callId: string;
  agentId: string;
  customerPhone?: string;
  customerName?: string;
  transcript?: Array<{
    speaker: 'agent' | 'user';
    text: string;
    timestamp: string;
  }>;
  status: 'started' | 'ended' | 'failed';
  metadata?: any;
}): Promise<string> {
  try {
    const logId = createId();

    // Format messages from transcript
    const messages = data.transcript?.map((msg) => ({
      role: msg.speaker === 'agent' ? 'assistant' : 'user',
      content: msg.text,
      timestamp: msg.timestamp,
    })) || [];

    // Prepare metadata
    const metadata = {
      callId: data.callId,
      agentId: data.agentId,
      status: data.status,
      ...data.metadata,
    };

    // Save to Prisma
    await prisma.conversationLog.create({
      data: {
        id: logId,
        userId: data.userId,
        platform: 'voice',
        customerPhone: data.customerPhone || null,
        customerName: data.customerName || null,
        messages: messages as any,
        metadata: metadata as any,
        status: data.status === 'ended' ? 'resolved' : 'open',
        createdAt: new Date(),
      },
    });

    logger.info('Saved voice conversation log', {
      logId,
      callId: data.callId,
      userId: data.userId,
    });

    return logId;
  } catch (error) {
    logger.error('Error saving voice conversation log', error, {
      callId: data.callId,
      userId: data.userId,
    });
    throw error;
  }
}

/**
 * Update voice conversation log (for call ended events)
 */
export async function updateVoiceConversationLog(
  callId: string,
  updates: {
    transcript?: Array<{
      speaker: 'agent' | 'user';
      text: string;
      timestamp: string;
    }>;
    status?: 'started' | 'ended' | 'failed';
    metadata?: any;
  }
): Promise<void> {
  try {
    // Find the conversation log by callId in metadata
    const existingLog = await prisma.conversationLog.findFirst({
      where: {
        platform: 'voice',
        metadata: {
          path: ['callId'],
          equals: callId,
        },
      },
    });

    if (!existingLog) {
      logger.warn('Voice conversation log not found for update', { callId });
      return;
    }

    // Prepare updates
    const updateData: any = {
      updatedAt: new Date(),
    };

    if (updates.transcript) {
      const messages = updates.transcript.map((msg) => ({
        role: msg.speaker === 'agent' ? 'assistant' : 'user',
        content: msg.text,
        timestamp: msg.timestamp,
      }));
      updateData.messages = messages;
    }

    if (updates.status) {
      updateData.status = updates.status === 'ended' ? 'resolved' : 'open';
    }

    if (updates.metadata) {
      updateData.metadata = {
        ...((existingLog.metadata as any) || {}),
        ...updates.metadata,
      };
    }

    // Update in Prisma
    await prisma.conversationLog.update({
      where: { id: existingLog.id },
      data: updateData,
    });

    logger.info('Updated voice conversation log', {
      logId: existingLog.id,
      callId,
    });
  } catch (error) {
    logger.error('Error updating voice conversation log', error, { callId });
    throw error;
  }
}

/**
 * Get voice conversation logs for a user
 */
export async function getUserVoiceConversations(
  userId: string,
  options?: {
    limit?: number;
    offset?: number;
    status?: 'open' | 'resolved' | 'archived';
  }
): Promise<any[]> {
  try {
    const where: any = {
      userId,
      platform: 'voice',
    };

    if (options?.status) {
      where.status = options.status;
    }

    const conversations = await prisma.conversationLog.findMany({
      where,
      orderBy: { createdAt: 'desc' },
      take: options?.limit || 50,
      skip: options?.offset || 0,
    });

    return conversations;
  } catch (error) {
    logger.error('Error getting user voice conversations', error, { userId });
    throw error;
  }
}

/**
 * Find user by voice agent ID
 */
export async function findUserByVoiceAgentId(agentId: string): Promise<string | null> {
  try {
    const user = await prisma.users.findFirst({
      where: { voiceAgentId: agentId },
      select: { id: true },
    });

    return user?.id || null;
  } catch (error) {
    logger.error('Error finding user by voice agent ID', error, { agentId });
    return null;
  }
}
