/**
 * Custom Content Process Edge Function
 *
 * Asynchronous processing of uploaded PDF files:
 * 1. Download PDF from Storage
 * 2. Extract text using pdf-parse
 * 3. Save extracted text to Storage
 * 4. Chunk text if needed (hybrid strategy)
 * 5. Generate embeddings
 * 6. Store in Qdrant
 * 7. Update database with results
 *
 * POST /custom-content-process
 * Body: { content_id, store_id }
 *
 * Note: This function is triggered internally by custom-content-upload
 */

import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
import { extractTextFromPDF, sanitizeExtractedText } from '../_shared/pdf-processor.ts';
import { chunkText } from '../_shared/text-chunker.ts';
import { syncCustomContent } from '../_shared/qdrant-client.ts';
import { validatePDFText } from '../_shared/content-validator.ts';

const corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};

Deno.serve(async (req) => {
  // Handle CORS preflight
  if (req.method === 'OPTIONS') {
    return new Response(null, { headers: corsHeaders });
  }

  // Parse request body FIRST before any error handling
  let content_id: string | undefined;
  let store_id: string | undefined;

  try {
    const body = await req.json();
    content_id = body.content_id;
    store_id = body.store_id;
  } catch (parseError) {
    console.error('[Process] Failed to parse request body:', parseError);
    return new Response(
      JSON.stringify({ error: 'Invalid request body' }),
      { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    );
  }

  try {
    // Get Supabase client
    const supabaseUrl = Deno.env.get('SUPABASE_URL')!;
    const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
    const supabase = createClient(supabaseUrl, supabaseServiceKey);

    if (!content_id || !store_id) {
      return new Response(
        JSON.stringify({ error: 'Missing required fields: content_id, store_id' }),
        { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      );
    }

    console.log(`[Process] Starting processing for content ${content_id}`);

    // Get content record
    const { data: content, error: contentError } = await supabase
      .from('custom_content')
      .select('*, stores!inner(store_name)')
      .eq('id', content_id)
      .eq('store_id', store_id)
      .single();

    if (contentError || !content) {
      throw new Error(`Content not found: ${contentError?.message}`);
    }

    // Update status to processing
    await supabase
      .from('custom_content')
      .update({
        sync_status: 'processing',
        sync_started_at: new Date().toISOString(),
        sync_error: null,
      })
      .eq('id', content_id);

    // Download PDF from Storage
    console.log(`[Process] Downloading PDF from storage: ${content.storage_path_pdf}`);
    const { data: pdfData, error: downloadError } = await supabase.storage
      .from('custom-content')
      .download(content.storage_path_pdf);

    if (downloadError || !pdfData) {
      throw new Error(`Failed to download PDF: ${downloadError?.message}`);
    }

    // Convert Blob to ArrayBuffer
    const pdfBuffer = await pdfData.arrayBuffer();
    const pdfUint8Array = new Uint8Array(pdfBuffer);

    // Extract text from PDF
    console.log(`[Process] Extracting text from PDF...`);
    const { text, pageCount, metadata } = await extractTextFromPDF(pdfUint8Array);

    if (!text || text.trim().length === 0) {
      throw new Error('No text could be extracted from the PDF');
    }

    console.log(`[Process] Extracted ${text.length} characters from ${pageCount} pages`);

    // Sanitize extracted text
    const cleanText = sanitizeExtractedText(text);

    // Validate PDF content (reject code/structured data)
    const validationResult = validatePDFText(cleanText);
    if (!validationResult.isValid) {
      throw new Error(
        `Invalid PDF content: ${validationResult.reason}. ` +
        `Detected format: ${validationResult.detectedFormat}. ` +
        `Only plain text and Markdown PDFs are allowed.`
      );
    }

    // Save extracted text to Storage
    const txtStoragePath = `${store_id}/${content_id}.txt`;
    console.log(`[Process] Saving extracted text to: ${txtStoragePath}`);

    const txtBlob = new Blob([cleanText], { type: 'text/plain' });
    const { error: txtUploadError } = await supabase.storage
      .from('custom-content')
      .upload(txtStoragePath, txtBlob, {
        contentType: 'text/plain',
        upsert: true,
      });

    if (txtUploadError) {
      console.error('[Process] Failed to upload text file:', txtUploadError);
    }

    // Chunk text using hybrid strategy
    console.log(`[Process] Chunking text...`);
    const chunkResult = chunkText(cleanText);
    console.log(`[Process] Created ${chunkResult.chunks.length} chunks using ${chunkResult.strategy} strategy`);

    // Get Qdrant config from store
    const { data: storeConfig } = await supabase
      .from('stores')
      .select('qdrant_url, qdrant_api_key, store_name')
      .eq('id', store_id)
      .single();

    const qdrantConfig = storeConfig?.qdrant_url && storeConfig?.qdrant_api_key
      ? { url: storeConfig.qdrant_url, apiKey: storeConfig.qdrant_api_key }
      : undefined;

    // Sync to Qdrant
    console.log(`[Process] Syncing to Qdrant...`);
    const pointIds = await syncCustomContent(
      store_id,
      content_id,
      storeConfig?.store_name || store_id,
      chunkResult.chunks,
      {
        title: content.title,
        contentType: 'pdf_upload',
        originalFilename: content.original_filename,
        pageCount: pageCount,
        createdAt: content.created_at,
      },
      qdrantConfig
    );

    console.log(`[Process] Synced ${pointIds.length} points to Qdrant`);

    // Update database with success
    await supabase
      .from('custom_content')
      .update({
        content_text: cleanText,
        storage_path_txt: txtStoragePath,
        page_count: pageCount,
        chunk_count: chunkResult.chunks.length,
        qdrant_point_ids: pointIds,
        sync_status: 'completed',
        sync_completed_at: new Date().toISOString(),
        sync_error: null,
      })
      .eq('id', content_id);

    console.log(`[Process] Successfully processed content ${content_id}`);

    return new Response(
      JSON.stringify({
        success: true,
        contentId: content_id,
        pageCount: pageCount,
        chunkCount: chunkResult.chunks.length,
        strategy: chunkResult.strategy,
        qdrantPoints: pointIds.length,
        status: 'completed',
      }),
      { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    );

  } catch (error: any) {
    console.error('[Process] Error:', error);
    console.error('[Process] Error stack:', error.stack);

    // Try to update database with error (content_id is already parsed above)
    if (content_id) {
      try {
        const supabase = createClient(
          Deno.env.get('SUPABASE_URL')!,
          Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
        );

        await supabase
          .from('custom_content')
          .update({
            sync_status: 'failed',
            sync_completed_at: new Date().toISOString(),
            sync_error: error.message || error.toString(),
          })
          .eq('id', content_id);

        console.log('[Process] Updated database with error status for content:', content_id);
      } catch (updateError) {
        console.error('[Process] Failed to update error status:', updateError);
      }
    } else {
      console.error('[Process] Cannot update error status - content_id is undefined');
    }

    return new Response(
      JSON.stringify({
        error: error.message || 'Internal server error',
        details: error.toString(),
      }),
      { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    );
  }
});
