// lib/tools/adapters/mines/spatial-index.js
//
// mines_spatial_index — read GIS/CAD file metadata (kind, CRS, bounding box)
// from file HEADERS only (no geometry rendering) and write mines_spatial_assets
// rows. Also serves as the `mines.index_spatial` heartbeat-task handler.
//
// Two modes:
//   - { source_document_id } → index that single catalogued file
//   - { project_id }         → index all not-yet-indexed spatial files for the project
//
// Risk: low. Reads at most the first 100 bytes of each file. No network calls.

import path from 'node:path';
import { getDb, newId, nowIso } from '../../../db.js';
import { readSpatialMetadata } from '../../../mines/spatial-reader.js';

const SPATIAL_TYPES = new Set(['shp', 'gdb', 'mxd', 'dxf', 'dwg', 'dbf', 'shx', 'prj', 'adf', 'raster']);

function indexOne(db, doc) {
  // Skip if already indexed (idempotent on project_id + path).
  const existing = db.prepare(
    'SELECT id FROM mines_spatial_assets WHERE project_id = ? AND path = ? LIMIT 1'
  ).get(doc.project_id, doc.original_path);

  const meta = readSpatialMetadata(doc.original_path);

  if (!existing) {
    db.prepare(`
      INSERT OR IGNORE INTO mines_spatial_assets
        (id, project_id, kind, path, crs, bbox, file_size_bytes, indexed_at)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    `).run(
      newId('msa'), doc.project_id, meta.kind, doc.original_path,
      meta.crs, meta.bbox ? JSON.stringify(meta.bbox) : null,
      meta.file_size_bytes, nowIso()
    );
  }

  db.prepare('UPDATE mines_source_documents SET extraction_status = ?, updated_at = ? WHERE id = ?')
    .run('complete', nowIso(), doc.id);

  return Boolean(existing);
}

/**
 * @param {object} input - { project_id, source_document_id? }
 * @returns {Promise<object>} { status, assets_indexed, assets_skipped }
 */
export async function minesSpatialIndex(input, options = {}) {
  const db = getDb();

  if (input?.source_document_id) {
    const doc = db.prepare(
      'SELECT id, project_id, original_path, file_type FROM mines_source_documents WHERE id = ?'
    ).get(input.source_document_id);
    if (!doc) return { status: 'error', error: 'source_document_not_found' };
    const skipped = indexOne(db, doc);
    return { status: 'ok', assets_indexed: skipped ? 0 : 1, assets_skipped: skipped ? 1 : 0 };
  }

  const project_id = input?.project_id;
  if (!project_id) return { status: 'error', error: 'project_id_required' };

  const docs = db.prepare(
    'SELECT id, project_id, original_path, file_type FROM mines_source_documents WHERE project_id = ?'
  ).all(project_id).filter(d => SPATIAL_TYPES.has(String(d.file_type || '').toLowerCase()));

  let indexed = 0;
  let skipped = 0;
  for (const doc of docs) {
    try {
      if (indexOne(db, doc)) skipped++;
      else indexed++;
    } catch {
      skipped++;
    }
  }
  return { status: 'ok', assets_indexed: indexed, assets_skipped: skipped };
}
