// Main panel detection service with fallback chain
// Priority: OpenCV → ML → Grid → Manual Editor
import { detectPanelsOpenCV } from "./panel-detection.opencv";
import { detectPanelsML } from "./panel-detection.ml";
import { detectPanelsGrid } from "./panel-detector";

interface DetectionResult {
  panels: Panel[];
  method: "opencv" | "ml" | "grid" | "manual";
  confidence: number;
}

interface Panel {
  id: string;
  x: number;
  y: number;
  width: number;
  height: number;
  reading_order: number;
}

async function detectPanels(
  imageData: ImageData,
  allowManual: boolean = true,
): Promise<DetectionResult> {
  // Tier 1: OpenCV Edge Detection
  try {
    const panels = await detectPanelsOpenCV(imageData);
    if (validatePanels(panels, imageData)) {
      return { panels, method: "opencv", confidence: 0.85 };
    }
  } catch (e) {
    console.warn("OpenCV detection failed:", e);
  }

  // Tier 2: ML Detection (COCO-SSD)
  try {
    const panels = await detectPanelsML(imageData);
    if (validatePanels(panels, imageData)) {
      return { panels, method: "ml", confidence: 0.9 };
    }
  } catch (e) {
    console.warn("ML detection failed:", e);
  }

  // Tier 3: Grid Detection (baseline)
  const panels = detectPanelsGrid(imageData);
  if (allowManual && panels.length === 0) {
    return {
      panels: [],
      method: "manual" as const,
      confidence: 0,
    };
  }
  return { panels, method: "grid", confidence: 0.5 };
}

function validatePanels(panels: Panel[], imageData: ImageData): boolean {
  // Must have at least 1 panel
  if (panels.length === 0) return false;
  // Should not have too many panels (probably noise)
  if (panels.length > 30) return false;
  // Panels should cover reasonable area (not all empty space)
  let totalArea = panels.reduce((sum, p) => sum + p.width * p.height, 0);
  if (totalArea < 10 || totalArea > 100) return false;
  // Check panel sizes are reasonable relative to image dimensions
  const minPanelSize = Math.min(imageData.width, imageData.height) * 0.02;
  const tooSmall = panels.some(
    (p) =>
      (p.width / 100) * imageData.width < minPanelSize ||
      (p.height / 100) * imageData.height < minPanelSize,
  );
  if (tooSmall) return false;
  return true;
}

export { detectPanels, DetectionResult, Panel };
