import 'dart:io';

import '../editor/persistence/sidecar_repository.dart';
import '../models/note.dart';
import '../models/pen_tool.dart';
import 'database_service.dart';
import 'ocr_engine.dart';
import 'stroke_rasterizer.dart';

/// Runs OCR locally: typed text from strokes + handwriting via platform OCR.
class OcrService {
  /// Extract searchable text from [note] and persist it for search. The text is
  /// written to the note's `*.badnote.json` sidecar `ocrText` field — the
  /// vault-scan source of truth the Phase 6 search index reads — and also
  /// appended to the (rebuildable) SQLite FTS cache so legacy callers keep
  /// working. [note.id] is the synthetic note path, which is exactly the
  /// `sourceFilePath` the editor opened its [SidecarRepository] with.
  Future<void> processNote(Note note) async {
    final parts = <String>[];

    for (final stroke in note.strokes) {
      if (stroke.tool == PenTool.text &&
          stroke.textContent != null &&
          stroke.textContent!.trim().isNotEmpty) {
        parts.add(stroke.textContent!.trim());
      }
    }

    final handwritingStrokes = note.strokes
        .where(
          (s) =>
              s.tool != PenTool.eraser &&
              s.tool != PenTool.text &&
              s.points.isNotEmpty,
        )
        .toList();

    if (handwritingStrokes.isNotEmpty) {
      final png = await StrokeRasterizer.render(handwritingStrokes);
      if (png != null) {
        final recognized = await OcrEngine.recognizeImage(png);
        if (recognized != null && recognized.isNotEmpty) {
          parts.add(recognized);
        }
      }
    }

    final combined = parts.join(' ').trim();
    if (combined.isEmpty) return;

    // Persist into the note's sidecar so the vault-scan search index finds it.
    // Prefer the editor's already-open repo (same in-memory sidecar — no race);
    // if the note is closed, open/flush/dispose a transient handle.
    final open = SidecarRepositoryRegistry.forPath(note.id);
    if (open != null) {
      open.scheduleOcrTextSave(combined);
      await open.flush();
    } else if (await File('${note.id}$kSidecarSuffix').exists()) {
      final repo = await SidecarRepository.open(note.id, docType: 'notebook');
      repo.scheduleOcrTextSave(combined);
      await repo.flush();
      repo.dispose();
    }

    // Also keep the legacy SQLite FTS cache warm (rebuildable; not the source
    // of truth). Harmless if the row is never read.
    final db = await DatabaseService.getInstance();
    await db.appendOcrToFts(note.id, combined);
  }
}
