import type { DrillPoint } from './kriging-idw';

export type MarketSnapshot = {
  goldUsdPerOz: number;
  tzsPerUsd: number;
};

export type CostModel = {
  processingCostPerTonTzs: number;
  transportPerTonTzs: number;
  chemicalsPerTonTzs: number;
  /** 0–1 mass recovery to concentrate */
  recovery: number;
};

export type BlockCandidate = {
  block_x: number;
  block_y: number;
  block_z: number;
  tons: number;
  ppm: number;
};

export function getMarketFromEnv(): MarketSnapshot {
  const goldUsdPerOz = Number(process.env.MODULE_B_GOLD_USD_OZ ?? '2650');
  const tzsPerUsd = Number(process.env.MODULE_B_TZS_PER_USD ?? '2600');
  return { goldUsdPerOz, tzsPerUsd };
}

export function defaultCostModel(): CostModel {
  return {
    processingCostPerTonTzs: Number(process.env.MODULE_B_PROCESSING_TZS_TON ?? '75000'),
    transportPerTonTzs: Number(process.env.MODULE_B_TRANSPORT_TZS_TON ?? '15000'),
    chemicalsPerTonTzs: Number(process.env.MODULE_B_CHEMICALS_TZS_TON ?? '8000'),
    recovery: Number(process.env.MODULE_B_RECOVERY ?? '0.92'),
  };
}

/** Very simplified: profit TZS ≈ revenue from gold in ore minus cash costs. PPM treated as g Au / ton (spec-style). */
export function estimateProfitTzs(
  tons: number,
  ppm: number,
  market: MarketSnapshot,
  costs: CostModel
): number {
  const gramsAu = tons * ppm;
  const ozAu = gramsAu / 31.1035;
  const revenueTzs = ozAu * market.goldUsdPerOz * market.tzsPerUsd * costs.recovery;
  const costTzs =
    tons *
    (costs.processingCostPerTonTzs + costs.transportPerTonTzs + costs.chemicalsPerTonTzs);
  return revenueTzs - costTzs;
}

/**
 * Pick block(s) from candidates whose estimated profit is closest above target (greedy scan).
 */
export function findBlocksForTargetProfit(
  candidates: BlockCandidate[],
  targetProfitTzs: number,
  market: MarketSnapshot,
  costs: CostModel
): { best: BlockCandidate; profitTzs: number; narrative: string } | null {
  let best: BlockCandidate | null = null;
  let bestProfit = -Infinity;
  for (const c of candidates) {
    const p = estimateProfitTzs(c.tons, c.ppm, market, costs);
    if (p >= targetProfitTzs && p > bestProfit) {
      bestProfit = p;
      best = c;
    }
  }
  if (!best) {
    // fallback: max profit
    for (const c of candidates) {
      const p = estimateProfitTzs(c.tons, c.ppm, market, costs);
      if (p > bestProfit) {
        bestProfit = p;
        best = c;
      }
    }
  }
  if (!best) return null;
  const narrative = `Excavator to [${best.block_x.toFixed(1)}, ${best.block_y.toFixed(1)}], depth ${best.block_z.toFixed(1)}. Dig ${best.tons.toFixed(0)} tons at ${best.ppm.toFixed(2)} PPM. Est. profit: TZS ${(bestProfit / 1e6).toFixed(0)}M`;
  return { best, profitTzs: bestProfit, narrative };
}

/** Map lat/lon to block search key: use as x/y if no projection (MVP). */
export function latLonToSearchCoords(lat: number, lon: number): DrillPoint {
  return { x: lon, y: lat, z: 0, ppm: 0 };
}
