import { v4 as uuidv4 } from 'uuid';
import { logger } from '../utils/logger';
import { getSupabaseServiceClient } from '../config/supabase';

export interface DocumentChunk {
  id: string;
  documentId: string;
  content: string;
  metadata: Record<string, any>;
  embedding: number[];
  chunkIndex: number;
  section?: string;
  pageNumber?: number;
  createdAt: Date;
  updatedAt: Date;
}

export interface VectorSearchResult {
  documentId: string;
  similarityScore: number;
  chunkContent: string;
  metadata: Record<string, any>;
}

export class VectorDatabaseModel {
  static async storeDocumentChunks(chunks: Omit<DocumentChunk, 'id' | 'createdAt' | 'updatedAt'>[]): Promise<void> {
    const supabase = getSupabaseServiceClient();
    const { error } = await supabase
      .from('document_chunks')
      .insert(chunks.map(chunk => ({
        ...chunk,
        embedding: `[${chunk.embedding.join(',')}]`
      })));

    if (error) {
      logger.error('Failed to store document chunks', error);
      throw error;
    }

    logger.info(`Stored ${chunks.length} document chunks in vector database`);
  }

  static async getDocumentChunks(documentId: string): Promise<DocumentChunk[]> {
    const supabase = getSupabaseServiceClient();
    const { data, error } = await supabase
      .from('document_chunks')
      .select('*')
      .eq('document_id', documentId)
      .order('chunk_index');

    if (error) {
      logger.error('Failed to get document chunks', error);
      throw error;
    }

    return data || [];
  }

  static async getAllChunks(): Promise<DocumentChunk[]> {
    const supabase = getSupabaseServiceClient();
    const { data, error } = await supabase
      .from('document_chunks')
      .select('*')
      .limit(1000);

    if (error) {
      logger.error('Failed to get all chunks', error);
      throw error;
    }

    return data || [];
  }

  static async getTotalChunkCount(): Promise<number> {
    const supabase = getSupabaseServiceClient();
    const { count, error } = await supabase
      .from('document_chunks')
      .select('*', { count: 'exact', head: true });

    if (error) {
      logger.error('Failed to get total chunk count', error);
      throw error;
    }

    return count || 0;
  }

  static async getTotalDocumentCount(): Promise<number> {
    const supabase = getSupabaseServiceClient();
    const { data, error } = await supabase.rpc('count_distinct_documents');

    if (error) {
      logger.error('Failed to get total document count', error);
      throw error;
    }

    return data || 0;
  }

  static async getAverageChunkSize(): Promise<number> {
    const supabase = getSupabaseServiceClient();
    const { data, error } = await supabase.rpc('average_chunk_size');

    if (error) {
      logger.error('Failed to get average chunk size', error);
      throw error;
    }

    return data || 0;
  }

  static async getSearchAnalytics(userId: string, days: number = 30): Promise<any[]> {
    const supabase = getSupabaseServiceClient();
    const { data, error } = await supabase.rpc('get_search_analytics', {
      user_id_param: userId,
      days_param: days
    });

    if (error) {
      logger.error('Failed to get search analytics', error);
      throw error;
    }

    return data || [];
  }

  static async getVectorDatabaseStats(): Promise<{
    totalChunks: number;
    totalDocuments: number;
    averageSimilarity: number;
  }> {
    const supabase = getSupabaseServiceClient();
    const { data, error } = await supabase.rpc('get_vector_database_stats');

    if (error) {
      logger.error('Failed to get vector database stats', error);
      throw error;
    }

    return data[0] || { totalChunks: 0, totalDocuments: 0, averageSimilarity: 0 };
  }
}