#!/usr/bin/env node
/**
 * multimodal/vision.mjs — Vision analysis capabilities.
 *
 * Provides image description via vision-capable LLMs with a
 * metadata-only fallback when no vision model is available.
 *
 * Pure ESM. No build step. Uses only Node.js standard APIs.
 */

import { askLLM, pickModel } from '../llm.mjs';
import { addCognitiveLog } from '../db.mjs';
import { readFileSync, existsSync, statSync } from 'fs';
import { extname, basename } from 'path';

const IMAGE_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp', '.svg'];

export function isVisionAvailable() {
  // Check if vision model exists in tier map - for now just return config check
  try {
    const model = pickModel('vision');
    return !!model;
  } catch {
    return false;
  }
}

export function isImageFile(filePath) {
  const ext = extname(filePath).toLowerCase();
  return IMAGE_EXTENSIONS.includes(ext);
}

export async function describeImage(filePath, prompt = 'Describe this image in detail.') {
  if (!existsSync(filePath)) throw new Error(`Image not found: ${filePath}`);
  if (!isImageFile(filePath)) throw new Error(`Not an image file: ${filePath}`);

  const stat = statSync(filePath);
  const metadata = {
    filename: basename(filePath),
    extension: extname(filePath),
    sizeBytes: stat.size,
    modified: stat.mtime.toISOString()
  };

  // If vision LLM is available, use it
  const start = Date.now();
  if (isVisionAvailable()) {
    try {
      const result = await askLLM(
        `${prompt}\n\nImage file: ${metadata.filename} (${metadata.extension}, ${metadata.sizeBytes} bytes)`,
        { model: pickModel('vision') }
      );
      const duration = Date.now() - start;
      addCognitiveLog('vision', `Describe: ${metadata.filename}`, result.slice(0, 500), 0, duration);
      return { description: result, metadata, method: 'vision-llm' };
    } catch (err) {
      // Fall through to metadata-only
    }
  }

  // Fallback: describe metadata only
  const fallback = `Image: ${metadata.filename}, Format: ${metadata.extension}, Size: ${(metadata.sizeBytes / 1024).toFixed(1)}KB, Modified: ${metadata.modified}`;
  const duration = Date.now() - start;
  addCognitiveLog('vision', `Metadata: ${metadata.filename}`, fallback, 0, duration);
  return { description: fallback, metadata, method: 'metadata-only' };
}

export function getImageMetadata(filePath) {
  if (!existsSync(filePath)) throw new Error(`File not found: ${filePath}`);
  const stat = statSync(filePath);
  return {
    filename: basename(filePath),
    extension: extname(filePath),
    sizeBytes: stat.size,
    modified: stat.mtime.toISOString(),
    isImage: isImageFile(filePath)
  };
}
