import { Request, Response } from 'express';
import { prisma } from '../models';
import {
  getMarketFromEnv,
  defaultCostModel,
  findBlocksForTargetProfit,
  estimateProfitTzs,
  type BlockCandidate,
} from '../lib/module-b';

export const reverseEconomicsController = {
  async targetProfit(req: Request, res: Response) {
    const b = req.body as { license_id?: string; target_profit_tzs?: number };
    if (!b.license_id || b.target_profit_tzs == null) {
      res.status(400).json({ success: false, error: 'license_id and target_profit_tzs required' });
      return;
    }
    const blocks = await prisma.blockModel.findMany({
      where: { license_id: b.license_id },
      take: 10000,
    });
    if (blocks.length === 0) {
      res.status(404).json({ success: false, error: 'No block model for license' });
      return;
    }
    const candidates: BlockCandidate[] = blocks.map((r) => ({
      block_x: r.block_x,
      block_y: r.block_y,
      block_z: r.block_z,
      tons: r.tons_estimate,
      ppm: r.ppm_estimate,
    }));
    const market = getMarketFromEnv();
    const costs = defaultCostModel();
    const result = findBlocksForTargetProfit(candidates, b.target_profit_tzs, market, costs);
    if (!result) {
      res.status(404).json({ success: false, error: 'No suitable block' });
      return;
    }
    res.json({
      success: true,
      data: {
        narrative: result.narrative,
        profit_tzs: result.profitTzs,
        target_profit_tzs: b.target_profit_tzs,
        block: result.best,
        market,
        costs,
      },
    });
  },

  async coordinates(req: Request, res: Response) {
    const lat = Number(String(req.params.lat));
    const lon = Number(String(req.params.lon));
    if (Number.isNaN(lat) || Number.isNaN(lon)) {
      res.status(400).json({ success: false, error: 'Invalid lat/lon' });
      return;
    }
    const license_id = req.query.license_id as string;
    if (!license_id) {
      res.status(400).json({ success: false, error: 'license_id query required' });
      return;
    }
    const blocks = await prisma.blockModel.findMany({ where: { license_id } });
    if (blocks.length === 0) {
      res.status(404).json({ success: false, error: 'No blocks' });
      return;
    }
    let best = blocks[0];
    let bestD = Infinity;
    for (const b of blocks) {
      const d = Math.pow(b.block_y - lat, 2) + Math.pow(b.block_x - lon, 2);
      if (d < bestD) {
        bestD = d;
        best = b;
      }
    }
    const market = getMarketFromEnv();
    const costs = defaultCostModel();
    const profitTzs = estimateProfitTzs(best.tons_estimate, best.ppm_estimate, market, costs);
    res.json({
      success: true,
      data: {
        matched_block: best,
        profit_tzs_estimate: profitTzs,
        lat,
        lon,
        market,
      },
    });
  },
};
