// lib/tools/adapters/mines/assumption-validate.js
//
// mines_assumption_validate — check the data required for a T1 (in-situ) or T2
// (DCF) valuation and return a gap list + recommended tier. Read + compute only;
// no writes, no external calls. See engineering-design §6 (tier selection).

import { getDb } from '../../../db.js';

/**
 * @param {object} input - { project_id, target_tier? ('t1_in_situ'|'t2_dcf'|'auto') }
 * @returns {Promise<object>} { status, recommended_tier, t1_ready, t2_ready, gaps, data_completeness, inputs }
 */
export async function minesAssumptionValidate(input, options = {}) {
  const project_id = input?.project_id;
  if (!project_id) return { status: 'error', error: 'project_id_required' };
  const target = input?.target_tier || 'auto';

  const db = getDb();
  const proj = db.prepare('SELECT id, asset_stage, commodity FROM mines_projects WHERE id = ?').get(project_id);
  if (!proj) return { status: 'error', error: 'not_found' };

  const assayRow = db.prepare(`
    SELECT COUNT(*) AS n,
           SUM(CASE WHEN au_ppm IS NOT NULL THEN 1 ELSE 0 END) AS au_n,
           SUM(CASE WHEN cu_pct IS NOT NULL THEN 1 ELSE 0 END) AS cu_n,
           SUM(CASE WHEN ag_ppm IS NOT NULL THEN 1 ELSE 0 END) AS ag_n
    FROM mines_assay_samples WHERE project_id = ?
  `).get(project_id);
  const drillRow = db.prepare('SELECT COUNT(*) AS n FROM mines_drill_holes WHERE project_id = ?').get(project_id);
  const factTypes = new Set(
    db.prepare('SELECT DISTINCT fact_type FROM mines_extracted_facts WHERE project_id = ?')
      .all(project_id).map(r => r.fact_type)
  );

  const hasAssays = (assayRow?.n || 0) > 0;
  const hasGrade = (assayRow?.au_n || 0) + (assayRow?.cu_n || 0) + (assayRow?.ag_n || 0) > 0;
  const hasDrill = (drillRow?.n || 0) > 0;
  const hasResource = factTypes.has('resource_estimate');
  const hasReserve = factTypes.has('reserve_estimate');
  const hasOpex = factTypes.has('opex');
  const hasProduction = factTypes.has('production_schedule');

  // T1 in-situ needs a resource tonnage source (resource_estimate fact, or
  // estimable from assays) and at least one grade column.
  const t1_ready = hasResource || (hasAssays && hasGrade);
  // T2 DCF needs production schedule + opex + reserve estimate (§6).
  const t2_ready = hasReserve && hasOpex && hasProduction;

  const gaps = [];
  if (!t1_ready) {
    if (!hasResource && !hasAssays) {
      gaps.push({ field: 'resource_or_assays', message: 'No resource_estimate fact and no assay samples — cannot estimate in-situ value.' });
    } else if (!hasGrade) {
      gaps.push({ field: 'grade_data', message: 'Assay samples present but no Au/Ag/Cu grade columns populated.' });
    }
  }
  if (!t2_ready) {
    if (!hasReserve) gaps.push({ field: 'reserve_estimate', message: 'Missing reserve_estimate ExtractedFact (required for DCF).' });
    if (!hasOpex) gaps.push({ field: 'opex', message: 'Missing opex ExtractedFact (required for DCF).' });
    if (!hasProduction) gaps.push({ field: 'production_schedule', message: 'Missing production_schedule ExtractedFact (required for DCF).' });
  }

  let recommended_tier = null;
  if (target === 't2_dcf') recommended_tier = t2_ready ? 't2_dcf' : null;
  else if (target === 't1_in_situ') recommended_tier = t1_ready ? 't1_in_situ' : null;
  else recommended_tier = t2_ready ? 't2_dcf' : (t1_ready ? 't1_in_situ' : null);

  const signals = [hasAssays, hasDrill, hasResource, hasReserve, hasOpex, hasProduction];
  const data_completeness = Math.round((signals.filter(Boolean).length / signals.length) * 100) / 100;

  return {
    status: 'ok',
    recommended_tier,
    t1_ready,
    t2_ready,
    gaps,
    data_completeness,
    inputs: {
      asset_stage: proj.asset_stage,
      assay_count: assayRow?.n || 0,
      drill_hole_count: drillRow?.n || 0,
      fact_types: [...factTypes],
    },
  };
}
