/**
 * Server-side logging utilities
 * 
 * Logs project events to Firestore for monitoring, debugging, and analytics.
 */

import { getAdminDb } from '@/lib/firebase/admin';
import { FieldValue } from 'firebase-admin/firestore';
import type { CreateProjectLogInput, ProjectLogEntry, ProjectLogFilters, ProjectLogStats } from '@/lib/types/logs';

/**
 * Log a project-related event
 * 
 * This is a fire-and-forget operation - errors are logged but not thrown
 * to avoid impacting the main request flow.
 * 
 * @param input - Log entry data
 * 
 * @example
 * ```typescript
 * await logProjectEvent({
 *   projectId: 'proj123',
 *   userId: 'user456',
 *   eventType: 'chat_interaction',
 *   mode: 'vision_mode',
 *   phase: 'vision_ready',
 *   artifactsUsed: ['Product Model', '5 Vector Chunks'],
 *   usedVectorSearch: true,
 *   vectorChunkCount: 5,
 *   promptVersion: '1.0',
 *   modelUsed: 'gemini-2.0-flash-exp',
 *   success: true,
 *   errorMessage: null,
 * });
 * ```
 */
export async function logProjectEvent(input: CreateProjectLogInput): Promise<void> {
  try {
    const adminDb = getAdminDb();
    const docRef = adminDb.collection('project_logs').doc();

    await docRef.set({
      ...input,
      id: docRef.id,
      createdAt: FieldValue.serverTimestamp(),
    });

    // Silent success
  } catch (error) {
    // Log to console but don't throw - logging should never break the main flow
    console.error('[Logs] Failed to log project event:', error);
  }
}

/**
 * Query project logs with filters
 * 
 * @param filters - Query filters
 * @returns Array of log entries
 */
export async function queryProjectLogs(
  filters: ProjectLogFilters
): Promise<ProjectLogEntry[]> {
  try {
    const adminDb = getAdminDb();
    let query = adminDb.collection('project_logs').orderBy('createdAt', 'desc');

    // Apply filters
    if (filters.projectId) {
      query = query.where('projectId', '==', filters.projectId) as any;
    }

    if (filters.userId) {
      query = query.where('userId', '==', filters.userId) as any;
    }

    if (filters.eventType) {
      query = query.where('eventType', '==', filters.eventType) as any;
    }

    if (filters.mode) {
      query = query.where('mode', '==', filters.mode) as any;
    }

    if (filters.phase) {
      query = query.where('phase', '==', filters.phase) as any;
    }

    if (filters.success !== undefined) {
      query = query.where('success', '==', filters.success) as any;
    }

    if (filters.startDate) {
      query = query.where('createdAt', '>=', filters.startDate) as any;
    }

    if (filters.endDate) {
      query = query.where('createdAt', '<=', filters.endDate) as any;
    }

    if (filters.limit) {
      query = query.limit(filters.limit) as any;
    }

    const snapshot = await query.get();

    return snapshot.docs.map((doc) => {
      const data = doc.data();
      return {
        ...data,
        createdAt: data.createdAt?.toDate?.() ?? data.createdAt,
      } as ProjectLogEntry;
    });
  } catch (error) {
    console.error('[Logs] Failed to query project logs:', error);
    return [];
  }
}

/**
 * Get aggregated stats for a project
 * 
 * @param projectId - Project ID to analyze
 * @param since - Optional date to filter from
 * @returns Aggregated statistics
 */
export async function getProjectLogStats(
  projectId: string,
  since?: Date
): Promise<ProjectLogStats> {
  try {
    const filters: ProjectLogFilters = { projectId, limit: 1000 };
    if (since) {
      filters.startDate = since;
    }

    const logs = await queryProjectLogs(filters);

    const stats: ProjectLogStats = {
      totalLogs: logs.length,
      successCount: 0,
      errorCount: 0,
      byEventType: {},
      byMode: {},
      avgVectorChunks: 0,
      vectorSearchUsageRate: 0,
    };

    let totalVectorChunks = 0;
    let vectorSearchCount = 0;

    logs.forEach((log) => {
      // Success/error counts
      if (log.success) {
        stats.successCount++;
      } else {
        stats.errorCount++;
      }

      // By event type
      stats.byEventType[log.eventType] = (stats.byEventType[log.eventType] ?? 0) + 1;

      // By mode
      if (log.mode) {
        stats.byMode[log.mode] = (stats.byMode[log.mode] ?? 0) + 1;
      }

      // Vector search stats
      if (log.usedVectorSearch) {
        vectorSearchCount++;
        if (log.vectorChunkCount) {
          totalVectorChunks += log.vectorChunkCount;
        }
      }
    });

    // Calculate averages
    if (vectorSearchCount > 0) {
      stats.avgVectorChunks = totalVectorChunks / vectorSearchCount;
      stats.vectorSearchUsageRate = vectorSearchCount / logs.length;
    }

    return stats;
  } catch (error) {
    console.error('[Logs] Failed to get project log stats:', error);
    return {
      totalLogs: 0,
      successCount: 0,
      errorCount: 0,
      byEventType: {},
      byMode: {},
      avgVectorChunks: 0,
      vectorSearchUsageRate: 0,
    };
  }
}

/**
 * Delete old logs (for maintenance/cleanup)
 * 
 * @param before - Delete logs older than this date
 * @returns Number of logs deleted
 */
export async function deleteOldLogs(before: Date): Promise<number> {
  try {
    const adminDb = getAdminDb();
    const snapshot = await adminDb
      .collection('project_logs')
      .where('createdAt', '<', before)
      .limit(500) // Process in batches to avoid overwhelming Firestore
      .get();

    if (snapshot.empty) {
      return 0;
    }

    const batch = adminDb.batch();
    snapshot.docs.forEach((doc) => {
      batch.delete(doc.ref);
    });

    await batch.commit();

    console.log(`[Logs] Deleted ${snapshot.size} old logs`);

    return snapshot.size;
  } catch (error) {
    console.error('[Logs] Failed to delete old logs:', error);
    return 0;
  }
}

