// src/lib/metadata-extractor.ts
// src/lib/metadata-extractor.ts
import * as PdfParse from 'pdf-parse-new';
import sharp from 'sharp';
import exifReader from 'exif-reader';
import EPub from 'epub2'; // New Import

/**
 * Converts EXIF DMS array to Decimal Degrees.
 */
function convertDMSToDD(dms: any, ref: string): string {
  if (!Array.isArray(dms) || dms.length < 3) return String(dms);
  const [degrees, minutes, seconds] = dms;
  let dd = degrees + (minutes / 60) + (seconds / 3600);
  if (ref === 'S' || ref === 'W') dd = dd * -1;
  return dd.toFixed(6);
}

/**
 * RECURSIVE SANITIZER
 */
function sanitizeMetadata(obj: any): any {
  if (obj === null || typeof obj !== 'object') return obj;
  if (obj instanceof Date) return obj.toISOString();
  if (Buffer.isBuffer(obj)) return `[Binary Data: ${obj.length} bytes]`;
  if (Array.isArray(obj)) return obj.map(sanitizeMetadata);

  const sanitized: any = {};
  for (const [key, value] of Object.entries(obj)) {
    const cleanKey = key.charAt(0).toLowerCase() + key.slice(1);

    if (cleanKey === 'gPSLatitude' && obj['gPSLatitudeRef']) {
      sanitized[cleanKey] = convertDMSToDD(value, obj['gPSLatitudeRef']);
      continue;
    }
    if (cleanKey === 'gPSLongitude' && obj['gPSLongitudeRef']) {
      sanitized[cleanKey] = convertDMSToDD(value, obj['gPSLongitudeRef']);
      continue;
    }

    sanitized[cleanKey] = sanitizeMetadata(value);
  }
  return sanitized;
}

export async function extractMetadata(buffer: Buffer, filename: string): Promise<any> {
  const extension = filename.split('.').pop()?.toLowerCase();

  try {
    // --- 1. PDF EXTRACTION ---
    if (extension === 'pdf') {
      const parser = new PdfParse.SmartPDFParser({ oversaturationFactor: 2.0, enableFastPath: true });
      const result = await parser.parse(buffer);
      return {
        type: 'PDF',
        title: filename,
        pageCount: result.numpages || 0,
        details: sanitizeMetadata(result.info || {}),
        textPreview: result.text ? result.text.substring(0, 200).replace(/\s+/g, ' ') : ""
      };
    }

    // --- 2. IMAGE EXTRACTION ---
    if (['jpg', 'jpeg', 'png', 'webp','heic'].includes(extension || '')) {
      const image = sharp(buffer);
      const metadata = await image.metadata();
      let details = {};
      if (metadata.exif) {
        try {
          const rawExif = exifReader(metadata.exif);
          details = sanitizeMetadata(rawExif);
        } catch (e) { console.warn("EXIF Parse failed"); }
      }
      return {
        type: `IMAGE (${metadata.format?.toUpperCase()})`,
        dimensions: `${metadata.width}x${metadata.height}`,
        title: filename,
        details: details 
      };
    }

    // --- 3. EPUB EXTRACTION (New Section) ---
    if (extension === 'epub') {
      return new Promise((resolve, reject) => {
        // We initialize the EPub instance with a null image path and use the buffer
        const epub = new EPub(buffer);
        
        epub.on('error', (err) => {
          console.error("EPUB Parser Error:", err);
          resolve({ type: 'EPUB', title: filename, error: "Failed to parse EPUB" });
        });

        epub.on('end', () => {
          // Standardizing the metadata for your UI
          resolve({
            type: 'EPUB',
            title: epub.metadata.title || filename,
            author: epub.metadata.creator || 'Unknown',
            details: sanitizeMetadata(epub.metadata),
            // Use the number of chapters/manifest items as a rough "page" guide
            pageCount: epub.spine.contents.length || 0,
            textPreview: epub.metadata.description 
              ? epub.metadata.description.substring(0, 200).replace(/<[^>]*>?/gm, '') 
              : ""
          });
        });

        epub.parse();
      });
    }

    return { type: 'FILE', title: filename };
  } catch (error: any) {
    console.error(`❌ Extraction failed for ${filename}:`, error.message);
    return { type: 'FILE', title: filename, error: error.message };
  }
}