/**
 * Conversation Tracker Service
 *
 * Tracks conversations across platforms (WhatsApp, Voice, Social) with analytics aggregation.
 * Provides daily statistics and customer insights for the workflow management system.
 *
 * Features:
 * - Multi-platform conversation logging
 * - Message appending for ongoing conversations
 * - Daily statistics aggregation
 * - Top customer identification
 * - Platform-specific analytics
 */

import { prisma } from '@/lib/db';
import { logger } from '@/lib/logger';
import { createId } from '@paralleldrive/cuid2';

export interface ConversationMessage {
  role: 'user' | 'agent' | 'system';
  content: string;
  timestamp: Date;
  metadata?: Record<string, any>;
}

export interface CreateConversationRequest {
  platform: 'whatsapp' | 'voice' | 'social';
  customerPhone?: string;
  customerName?: string;
  messages: ConversationMessage[];
  metadata?: Record<string, any>;
}

export interface DailyStats {
  date: Date;
  totalConversations: number;
  platforms: Record<string, number>;
  messagesReceived: number;
  messagesSent: number;
  topCustomers: Array<{ phone: string; name?: string; messageCount: number }>;
}

export interface GetConversationsOptions {
  platform?: string;
  status?: string;
  limit?: number;
  offset?: number;
}

export class ConversationTrackerService {
  private scopedLogger = logger.scope('ConversationTracker');

  /**
   * Log a new conversation
   */
  async createConversation(
    userId: string,
    data: CreateConversationRequest
  ): Promise<any> {
    try {
      const conversationId = createId();
      const now = new Date();

      // Validate platform
      if (!['whatsapp', 'voice', 'social'].includes(data.platform)) {
        throw new Error(`Invalid platform: ${data.platform}`);
      }

      // Validate messages
      if (!data.messages || data.messages.length === 0) {
        throw new Error('At least one message is required');
      }

      // Create conversation in Prisma
      const conversation = await prisma.conversationLog.create({
        data: {
          id: conversationId,
          userId,
          platform: data.platform,
          customerPhone: data.customerPhone || null,
          customerName: data.customerName || null,
          messages: JSON.stringify(data.messages),
          metadata: data.metadata ? JSON.stringify(data.metadata) : null,
          status: 'open',
          createdAt: now,
          updatedAt: now,
        },
      });

      this.scopedLogger.info('Conversation created', {
        conversationId,
        userId,
        platform: data.platform,
        messageCount: data.messages.length,
      });

      return conversation;
    } catch (error) {
      this.scopedLogger.error('Failed to create conversation', error);
      throw error;
    }
  }

  /**
   * Add messages to existing conversation
   */
  async appendMessages(
    conversationId: string,
    userId: string,
    newMessages: ConversationMessage[]
  ): Promise<any> {
    try {
      // Validate messages
      if (!newMessages || newMessages.length === 0) {
        throw new Error('At least one message is required');
      }

      // Get existing conversation
      const conversation = await prisma.conversationLog.findUnique({
        where: { id: conversationId },
      });

      if (!conversation) {
        throw new Error('Conversation not found');
      }

      // Verify ownership
      if (conversation.userId !== userId) {
        throw new Error('Unauthorized: Conversation does not belong to user');
      }

      // Parse existing messages
      const existingMessages: ConversationMessage[] = JSON.parse(
        conversation.messages as string
      );

      // Merge messages
      const allMessages = [...existingMessages, ...newMessages];

      // Update conversation
      const updated = await prisma.conversationLog.update({
        where: { id: conversationId },
        data: {
          messages: JSON.stringify(allMessages),
          updatedAt: new Date(),
        },
      });

      this.scopedLogger.info('Messages appended to conversation', {
        conversationId,
        userId,
        newMessageCount: newMessages.length,
        totalMessages: allMessages.length,
      });

      return updated;
    } catch (error) {
      this.scopedLogger.error('Failed to append messages', error);
      throw error;
    }
  }

  /**
   * Get conversations with pagination and filtering
   */
  async getUserConversations(
    userId: string,
    options: GetConversationsOptions = {}
  ): Promise<any[]> {
    try {
      const { platform, status, limit = 50, offset = 0 } = options;

      const where: any = { userId };

      if (platform) {
        where.platform = platform;
      }

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

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

      this.scopedLogger.info('Retrieved user conversations', {
        userId,
        count: conversations.length,
        platform,
        status,
      });

      return conversations;
    } catch (error) {
      this.scopedLogger.error('Failed to get user conversations', error);
      throw error;
    }
  }

  /**
   * Get daily conversation statistics
   */
  async getDailyStats(userId: string, date: Date): Promise<DailyStats> {
    try {
      // Get start and end of day
      const startOfDay = new Date(date);
      startOfDay.setHours(0, 0, 0, 0);

      const endOfDay = new Date(date);
      endOfDay.setHours(23, 59, 59, 999);

      // Get conversations for the day
      const conversations = await prisma.conversationLog.findMany({
        where: {
          userId,
          createdAt: {
            gte: startOfDay,
            lte: endOfDay,
          },
        },
      });

      // Calculate statistics
      const totalConversations = conversations.length;
      const platforms = this.groupByPlatform(conversations);
      const messagesReceived = this.countMessages(conversations, 'user');
      const messagesSent = this.countMessages(conversations, 'agent');
      const topCustomers = this.getTopCustomers(conversations, 5);

      const stats: DailyStats = {
        date,
        totalConversations,
        platforms,
        messagesReceived,
        messagesSent,
        topCustomers,
      };

      this.scopedLogger.info('Daily stats calculated', {
        userId,
        date: date.toISOString().split('T')[0],
        totalConversations,
      });

      return stats;
    } catch (error) {
      this.scopedLogger.error('Failed to calculate daily stats', error);
      throw error;
    }
  }

  /**
   * Update conversation status
   */
  async updateConversationStatus(
    conversationId: string,
    userId: string,
    status: 'open' | 'resolved' | 'archived'
  ): Promise<any> {
    try {
      // Get existing conversation
      const conversation = await prisma.conversationLog.findUnique({
        where: { id: conversationId },
      });

      if (!conversation) {
        throw new Error('Conversation not found');
      }

      // Verify ownership
      if (conversation.userId !== userId) {
        throw new Error('Unauthorized: Conversation does not belong to user');
      }

      // Update status
      const updated = await prisma.conversationLog.update({
        where: { id: conversationId },
        data: {
          status,
          updatedAt: new Date(),
        },
      });

      this.scopedLogger.info('Conversation status updated', {
        conversationId,
        userId,
        oldStatus: conversation.status,
        newStatus: status,
      });

      return updated;
    } catch (error) {
      this.scopedLogger.error('Failed to update conversation status', error);
      throw error;
    }
  }

  /**
   * Helper: Group conversations by platform
   */
  private groupByPlatform(conversations: any[]): Record<string, number> {
    const grouped: Record<string, number> = {
      whatsapp: 0,
      voice: 0,
      social: 0,
    };

    for (const conversation of conversations) {
      const platform = conversation.platform;
      if (grouped[platform] !== undefined) {
        grouped[platform]++;
      }
    }

    return grouped;
  }

  /**
   * Helper: Count messages by role
   */
  private countMessages(conversations: any[], role: 'user' | 'agent'): number {
    let count = 0;

    for (const conversation of conversations) {
      try {
        const messages: ConversationMessage[] = JSON.parse(
          conversation.messages as string
        );
        count += messages.filter(msg => msg.role === role).length;
      } catch (error) {
        this.scopedLogger.warn('Failed to parse messages for conversation', {
          conversationId: conversation.id,
        });
      }
    }

    return count;
  }

  /**
   * Helper: Get top customers by message count
   */
  private getTopCustomers(
    conversations: any[],
    limit: number
  ): Array<{ phone: string; name?: string; messageCount: number }> {
    // Group conversations by customer phone
    const customerMap = new Map<
      string,
      { phone: string; name?: string; messageCount: number }
    >();

    for (const conversation of conversations) {
      const phone = conversation.customerPhone;
      if (!phone) continue;

      try {
        const messages: ConversationMessage[] = JSON.parse(
          conversation.messages as string
        );
        const messageCount = messages.length;

        if (customerMap.has(phone)) {
          const existing = customerMap.get(phone)!;
          existing.messageCount += messageCount;
        } else {
          customerMap.set(phone, {
            phone,
            name: conversation.customerName || undefined,
            messageCount,
          });
        }
      } catch (error) {
        this.scopedLogger.warn('Failed to parse messages for top customers', {
          conversationId: conversation.id,
        });
      }
    }

    // Sort by message count and return top N
    return Array.from(customerMap.values())
      .sort((a, b) => b.messageCount - a.messageCount)
      .slice(0, limit);
  }
}

export const conversationTrackerService = new ConversationTrackerService();
