import { pool } from "../db/pool.js";
import { ApiError } from "../utils/ApiError.js";

const cleanString = (value) => String(value ?? "").trim();
const nullableString = (value) => {
  const cleaned = cleanString(value);
  return cleaned || null;
};

const resolveActorUserId = (req) =>
  req.user?.accountType === "mgx_mobile_account" ? null : req.user?.sub || null;
const nullableNumber = (value) => {
  if (value === "" || value === null || value === undefined) return null;
  const parsed = Number(value);
  return Number.isFinite(parsed) ? parsed : null;
};
const toNumber = (value, fallback = 0) => {
  const parsed = Number(value);
  return Number.isFinite(parsed) ? parsed : fallback;
};

const formatDzdAmount = (value) => {
  const amount = toNumber(value);
  const sign = amount < 0 ? "-" : "";
  const [integerPart, decimalPart] = Math.abs(amount).toFixed(2).split(".");
  return `${sign}${integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, " ")},${decimalPart} DZD`;
};

const getCompanyId = (req) => {
  const companyId = Number(req.query.company_id || req.body.company_id || req.user?.companyId);
  if (!companyId) {
    throw new ApiError(400, "Société requise.");
  }
  return companyId;
};

const logMgxAudit = async (db, req, { companyId, action, entityType, entityId, oldData, newData }) => {
  await db.query(
    `
      INSERT INTO mgx_audit_log (
        company_id, user_id, action, entity_type, entity_id,
        old_data, new_data, ip_address
      )
      VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
    `,
    [
      companyId,
      resolveActorUserId(req),
      action,
      entityType,
      entityId,
      oldData ? JSON.stringify(oldData) : null,
      newData ? JSON.stringify(newData) : null,
      req.ip,
    ],
  );
};

const mapRef = (prefix, row) => row[`${prefix}_id`] ? ({
  id: Number(row[`${prefix}_id`]),
  code: row[`${prefix}_code`],
  label: row[`${prefix}_label`],
  color: row[`${prefix}_color`],
  icon: row[`${prefix}_icon`],
  metadata: row[`${prefix}_metadata`] || {},
}) : null;

const fuelSelect = `
  SELECT
    f.*,
    v.reference AS vehicle_reference,
    v.plate_number,
    v.brand AS vehicle_brand,
    v.model AS vehicle_model,
    v.km_current AS vehicle_km_current,
    d.id AS depot_ref_id,
    d.code AS depot_code,
    d.label AS depot_label,
    d.city AS depot_city,
    fuel.id AS fuel_ref_id,
    fuel.code AS fuel_code,
    fuel.label AS fuel_label,
    fuel.color AS fuel_color,
    fuel.icon AS fuel_icon,
    fuel.metadata AS fuel_metadata
  FROM mgx_fuel_entries f
  LEFT JOIN mgx_vehicles v ON v.id = f.vehicle_id
  LEFT JOIN mgx_depots d ON d.id = f.depot_id
  LEFT JOIN mgx_referentiels fuel ON fuel.id = f.fuel_type_ref_id
`;

const mapFuelEntry = (row) => ({
  id: Number(row.id),
  company_id: Number(row.company_id),
  vehicle_id: row.vehicle_id ? Number(row.vehicle_id) : null,
  vehicle: row.vehicle_id ? {
    id: Number(row.vehicle_id),
    reference: row.vehicle_reference,
    plate_number: row.plate_number,
    brand: row.vehicle_brand,
    model: row.vehicle_model,
    km_current: toNumber(row.vehicle_km_current),
  } : null,
  depot_id: row.depot_id ? Number(row.depot_id) : null,
  depot: row.depot_ref_id ? {
    id: Number(row.depot_ref_id),
    code: row.depot_code,
    label: row.depot_label,
    city: row.depot_city,
  } : null,
  fuel_type_ref_id: row.fuel_type_ref_id ? Number(row.fuel_type_ref_id) : null,
  fuel_type: mapRef("fuel", row),
  entry_date: row.entry_date,
  quantity: toNumber(row.quantity),
  unit_price: toNumber(row.unit_price),
  total_amount: toNumber(row.total_amount),
  total_amount_formatted: formatDzdAmount(row.total_amount),
  km_at_fillup: row.km_at_fillup === null ? null : toNumber(row.km_at_fillup),
  km_since_last: row.km_since_last === null ? null : toNumber(row.km_since_last),
  consumption_per_100: row.consumption_per_100 === null ? null : toNumber(row.consumption_per_100),
  station_supplier: row.station_supplier,
  station_depot_id: row.station_depot_id ? Number(row.station_depot_id) : null,
  receipt_number: row.receipt_number,
  file_url: row.file_url,
  is_anomaly: row.is_anomaly,
  anomaly_reason: row.anomaly_reason,
  notes: row.notes,
  created_at: row.created_at,
});

const fetchFuelEntry = async (db, id, companyId) => {
  const { rows } = await db.query(
    `
      ${fuelSelect}
      WHERE f.id = $1
        AND f.company_id = $2
      LIMIT 1
    `,
    [id, companyId],
  );

  return rows[0] ? mapFuelEntry(rows[0]) : null;
};

const buildPayload = (body) => {
  const quantity = toNumber(body.quantity);
  const unitPrice = toNumber(body.unit_price);
  const totalAmount = body.total_amount === "" || body.total_amount === undefined || body.total_amount === null
    ? quantity * unitPrice
    : toNumber(body.total_amount);

  return {
    company_id: Number(body.company_id),
    vehicle_id: nullableNumber(body.vehicle_id),
    depot_id: nullableNumber(body.depot_id),
    fuel_type_ref_id: nullableNumber(body.fuel_type_ref_id),
    entry_date: nullableString(body.entry_date) || new Date().toISOString().slice(0, 10),
    quantity,
    unit_price: unitPrice,
    total_amount: totalAmount,
    km_at_fillup: nullableNumber(body.km_at_fillup),
    station_supplier: nullableString(body.station_supplier),
    station_depot_id: nullableNumber(body.station_depot_id),
    receipt_number: nullableString(body.receipt_number),
    file_url: nullableString(body.file_url),
    notes: nullableString(body.notes),
  };
};

const getAnomalyThreshold = async (db, companyId) => {
  const { rows } = await db.query(
    `
      SELECT fuel_anomaly_threshold_pct
      FROM mgx_settings
      WHERE company_id = $1
      LIMIT 1
    `,
    [companyId],
  );

  return toNumber(rows[0]?.fuel_anomaly_threshold_pct, 30);
};

const getPreviousKmReading = async (db, vehicleId, entryDate, excludeEntryId = null) => {
  const params = [vehicleId, entryDate];
  let excludeClause = "";
  if (excludeEntryId) {
    params.push(excludeEntryId);
    excludeClause = `AND id <> $${params.length}`;
  }

  const { rows } = await db.query(
    `
      SELECT km_at_fillup
      FROM mgx_fuel_entries
      WHERE vehicle_id = $1
        AND entry_date <= $2
        AND km_at_fillup IS NOT NULL
        ${excludeClause}
      ORDER BY entry_date DESC, id DESC
      LIMIT 1
    `,
    params,
  );

  return rows[0]?.km_at_fillup === undefined ? null : toNumber(rows[0].km_at_fillup);
};

const validateFuelPayload = async (db, payload, excludeEntryId = null) => {
  if (payload.total_amount < 0) {
    throw new ApiError(400, "Le montant total du plein doit être positif.");
  }

  if (payload.km_at_fillup < 0) {
    throw new ApiError(400, "Le kilométrage ne peut pas être négatif.");
  }

  const previousKm = await getPreviousKmReading(db, payload.vehicle_id, payload.entry_date, excludeEntryId);
  if (previousKm !== null && payload.km_at_fillup < previousKm) {
    throw new ApiError(
      400,
      `Le kilométrage du plein doit être supérieur ou égal au dernier relevé (${previousKm.toLocaleString("fr-DZ")} km).`,
    );
  }
};

const computeFuelMetrics = async (db, payload, excludeEntryId = null) => {
  if (!payload.vehicle_id || payload.km_at_fillup === null) {
    return {
      km_since_last: null,
      consumption_per_100: null,
      is_anomaly: false,
      anomaly_reason: null,
      normal_consumption: null,
      anomaly_gap_pct: null,
    };
  }

  const previousKm = await getPreviousKmReading(db, payload.vehicle_id, payload.entry_date, excludeEntryId);
  const kmSinceLast = previousKm === null ? null : payload.km_at_fillup - previousKm;

  if (!kmSinceLast || kmSinceLast <= 0) {
    return {
      km_since_last: kmSinceLast > 0 ? kmSinceLast : null,
      consumption_per_100: null,
      is_anomaly: false,
      anomaly_reason: null,
      normal_consumption: null,
      anomaly_gap_pct: null,
    };
  }

  const consumption = (payload.quantity / kmSinceLast) * 100;

  const avgParams = [payload.vehicle_id];
  let avgExclude = "";
  if (excludeEntryId) {
    avgParams.push(excludeEntryId);
    avgExclude = `AND id <> $${avgParams.length}`;
  }
  const { rows: avgRows } = await db.query(
    `
      SELECT AVG(consumption_per_100)::numeric AS average_consumption
      FROM (
        SELECT consumption_per_100
        FROM mgx_fuel_entries
        WHERE vehicle_id = $1
          AND consumption_per_100 IS NOT NULL
          AND consumption_per_100 > 0
          ${avgExclude}
        ORDER BY entry_date DESC, id DESC
        LIMIT 5
      ) last_entries
    `,
    avgParams,
  );

  const averageConsumption = avgRows[0]?.average_consumption === null
    ? null
    : toNumber(avgRows[0]?.average_consumption);
  const thresholdPct = await getAnomalyThreshold(db, payload.company_id);

  if (!averageConsumption) {
    return {
      km_since_last: kmSinceLast,
      consumption_per_100: consumption,
      is_anomaly: false,
      anomaly_reason: null,
      normal_consumption: null,
      anomaly_gap_pct: null,
    };
  }

  const limit = averageConsumption * (1 + thresholdPct / 100);
  const isAnomaly = consumption > limit;
  const gapPct = averageConsumption ? ((consumption - averageConsumption) / averageConsumption) * 100 : null;

  return {
    km_since_last: kmSinceLast,
    consumption_per_100: consumption,
    is_anomaly: isAnomaly,
    anomaly_reason: isAnomaly
      ? `Consommation ${consumption.toFixed(2)} L/100km supérieure à la moyenne ${averageConsumption.toFixed(2)} L/100km (+${gapPct.toFixed(1)}%, seuil ${thresholdPct}%).`
      : null,
    normal_consumption: averageConsumption,
    anomaly_gap_pct: gapPct,
  };
};

const emitFuelAnomaly = (req, companyId, entry) => {
  if (!entry?.is_anomaly) return;
  req.app.get("io")?.to(`company:${companyId}`).emit("fuel:anomaly_detected", {
    entry_id: entry.id,
    vehicle: entry.vehicle?.plate_number || entry.vehicle?.reference,
    consumption_per_100: entry.consumption_per_100,
    message: entry.anomaly_reason,
  });
};

export const mgxFuelController = {
  async listFuel(req, res) {
    const companyId = getCompanyId(req);
    const conditions = ["f.company_id = $1"];
    const values = [companyId];

    const filterMap = [
      ["vehicle_id", "f.vehicle_id"],
      ["depot_id", "f.depot_id"],
      ["fuel_type_ref_id", "f.fuel_type_ref_id"],
    ];

    for (const [queryKey, column] of filterMap) {
      const value = nullableNumber(req.query[queryKey]);
      if (value) {
        values.push(value);
        conditions.push(`${column} = $${values.length}`);
      }
    }

    if (req.query.from) {
      values.push(req.query.from);
      conditions.push(`f.entry_date >= $${values.length}`);
    }
    if (req.query.to) {
      values.push(req.query.to);
      conditions.push(`f.entry_date <= $${values.length}`);
    }
    if (String(req.query.anomaly_only || "") === "true") {
      conditions.push("f.is_anomaly = true");
    }

    const { rows } = await pool.query(
      `
        ${fuelSelect}
        WHERE ${conditions.join(" AND ")}
        ORDER BY f.entry_date DESC, f.id DESC
        LIMIT 500
      `,
      values,
    );

    res.json({ items: rows.map(mapFuelEntry) });
  },

  async getFuelEntry(req, res) {
    const companyId = getCompanyId(req);
    const item = await fetchFuelEntry(pool, req.params.id, companyId);
    if (!item) {
      throw new ApiError(404, "Saisie carburant introuvable.");
    }
    res.json({ item });
  },

  async createFuelEntry(req, res) {
    const companyId = getCompanyId(req);
    const payload = buildPayload({ ...req.body, company_id: companyId });

    if (!payload.vehicle_id || !payload.fuel_type_ref_id || payload.quantity <= 0 || payload.unit_price < 0 || payload.km_at_fillup === null) {
      throw new ApiError(400, "Véhicule, type carburant, quantité, prix et kilométrage sont obligatoires.");
    }

    const client = await pool.connect();
    try {
      await client.query("BEGIN");
      await validateFuelPayload(client, payload);
      const metrics = await computeFuelMetrics(client, payload);
      const { rows } = await client.query(
        `
          INSERT INTO mgx_fuel_entries (
            company_id, vehicle_id, depot_id, fuel_type_ref_id, entry_date,
            quantity, unit_price, total_amount, km_at_fillup, km_since_last,
            consumption_per_100, station_supplier, station_depot_id,
            receipt_number, file_url, is_anomaly, anomaly_reason, notes, created_by
          )
          VALUES (
            $1, $2, $3, $4, $5,
            $6, $7, $8, $9, $10,
            $11, $12, $13,
            $14, $15, $16, $17, $18, $19
          )
          RETURNING *
        `,
        [
          payload.company_id,
          payload.vehicle_id,
          payload.depot_id,
          payload.fuel_type_ref_id,
          payload.entry_date,
          payload.quantity,
          payload.unit_price,
          payload.total_amount,
          payload.km_at_fillup,
          metrics.km_since_last,
          metrics.consumption_per_100,
          payload.station_supplier,
          payload.station_depot_id,
          payload.receipt_number,
          payload.file_url,
          metrics.is_anomaly,
          metrics.anomaly_reason,
          payload.notes,
          resolveActorUserId(req),
        ],
      );

      await client.query(
        `
          UPDATE mgx_vehicles
          SET km_current = GREATEST(COALESCE(km_current, 0), $1), updated_at = NOW()
          WHERE id = $2
            AND company_id = $3
        `,
        [payload.km_at_fillup, payload.vehicle_id, companyId],
      );

      await logMgxAudit(client, req, {
        companyId,
        action: "CREATE",
        entityType: "mgx_fuel_entry",
        entityId: rows[0].id,
        newData: rows[0],
      });
      await client.query("COMMIT");

      const item = await fetchFuelEntry(pool, rows[0].id, companyId);
      emitFuelAnomaly(req, companyId, item);
      res.status(201).json({ item, metrics });
    } catch (error) {
      await client.query("ROLLBACK");
      throw error;
    } finally {
      client.release();
    }
  },

  async updateFuelEntry(req, res) {
    const companyId = getCompanyId(req);
    const payload = buildPayload({ ...req.body, company_id: companyId });
    const client = await pool.connect();

    try {
      await client.query("BEGIN");
      const oldEntry = await fetchFuelEntry(client, req.params.id, companyId);
      if (!oldEntry) {
        throw new ApiError(404, "Saisie carburant introuvable.");
      }

      await validateFuelPayload(client, payload, req.params.id);
      const metrics = await computeFuelMetrics(client, payload, req.params.id);
      const { rows } = await client.query(
        `
          UPDATE mgx_fuel_entries
          SET
            vehicle_id = $1,
            depot_id = $2,
            fuel_type_ref_id = $3,
            entry_date = $4,
            quantity = $5,
            unit_price = $6,
            total_amount = $7,
            km_at_fillup = $8,
            km_since_last = $9,
            consumption_per_100 = $10,
            station_supplier = $11,
            station_depot_id = $12,
            receipt_number = $13,
            file_url = $14,
            is_anomaly = $15,
            anomaly_reason = $16,
            notes = $17
          WHERE id = $18
            AND company_id = $19
          RETURNING *
        `,
        [
          payload.vehicle_id,
          payload.depot_id,
          payload.fuel_type_ref_id,
          payload.entry_date,
          payload.quantity,
          payload.unit_price,
          payload.total_amount,
          payload.km_at_fillup,
          metrics.km_since_last,
          metrics.consumption_per_100,
          payload.station_supplier,
          payload.station_depot_id,
          payload.receipt_number,
          payload.file_url,
          metrics.is_anomaly,
          metrics.anomaly_reason,
          payload.notes,
          req.params.id,
          companyId,
        ],
      );

      await client.query(
        `
          UPDATE mgx_vehicles
          SET km_current = GREATEST(COALESCE(km_current, 0), $1), updated_at = NOW()
          WHERE id = $2
            AND company_id = $3
        `,
        [payload.km_at_fillup, payload.vehicle_id, companyId],
      );

      await logMgxAudit(client, req, {
        companyId,
        action: "UPDATE",
        entityType: "mgx_fuel_entry",
        entityId: req.params.id,
        oldData: oldEntry,
        newData: rows[0],
      });
      await client.query("COMMIT");

      const item = await fetchFuelEntry(pool, req.params.id, companyId);
      emitFuelAnomaly(req, companyId, item);
      res.json({ item, metrics });
    } catch (error) {
      await client.query("ROLLBACK");
      throw error;
    } finally {
      client.release();
    }
  },

  async deleteFuelEntry(req, res) {
    const companyId = getCompanyId(req);
    const client = await pool.connect();

    try {
      await client.query("BEGIN");
      const oldEntry = await fetchFuelEntry(client, req.params.id, companyId);
      if (!oldEntry) {
        throw new ApiError(404, "Saisie carburant introuvable.");
      }
      await client.query("DELETE FROM mgx_fuel_entries WHERE id = $1 AND company_id = $2", [req.params.id, companyId]);
      await logMgxAudit(client, req, {
        companyId,
        action: "DELETE",
        entityType: "mgx_fuel_entry",
        entityId: req.params.id,
        oldData: oldEntry,
      });
      await client.query("COMMIT");
      res.json({ ok: true });
    } catch (error) {
      await client.query("ROLLBACK");
      throw error;
    } finally {
      client.release();
    }
  },

  async getReports(req, res) {
    const companyId = getCompanyId(req);
    const from = req.query.from || new Date(new Date().getFullYear(), 0, 1).toISOString().slice(0, 10);
    const to = req.query.to || new Date().toISOString().slice(0, 10);
    const depotId = nullableNumber(req.query.depot_id);
    const vehicleId = nullableNumber(req.query.vehicle_id);
    const fuelTypeId = nullableNumber(req.query.fuel_type_ref_id);

    const conditions = ["f.company_id = $1", "f.entry_date BETWEEN $2 AND $3"];
    const values = [companyId, from, to];
    if (depotId) {
      values.push(depotId);
      conditions.push(`f.depot_id = $${values.length}`);
    }
    if (vehicleId) {
      values.push(vehicleId);
      conditions.push(`f.vehicle_id = $${values.length}`);
    }
    if (fuelTypeId) {
      values.push(fuelTypeId);
      conditions.push(`f.fuel_type_ref_id = $${values.length}`);
    }
    const whereSql = conditions.join(" AND ");

    const [summaryResult, byVehicleResult, monthlyDepotResult, byTypeResult, anomaliesResult] = await Promise.all([
      pool.query(
        `
          SELECT
            COALESCE(SUM(f.quantity), 0) AS total_quantity,
            COALESCE(SUM(f.total_amount), 0) AS total_amount,
            COALESCE(AVG(NULLIF(f.unit_price, 0)), 0) AS average_price,
            COUNT(DISTINCT f.vehicle_id)::int AS vehicles_count,
            COUNT(*) FILTER (WHERE f.is_anomaly)::int AS anomalies_count
          FROM mgx_fuel_entries f
          WHERE ${whereSql}
        `,
        values,
      ),
      pool.query(
        `
          SELECT
            v.id,
            v.reference,
            v.plate_number,
            v.brand,
            v.model,
            COALESCE(SUM(f.km_since_last), 0) AS km_total,
            COALESCE(SUM(f.quantity), 0) AS quantity_total,
            COALESCE(SUM(f.total_amount), 0) AS amount_total,
            COALESCE(AVG(f.consumption_per_100) FILTER (WHERE f.consumption_per_100 IS NOT NULL), 0) AS avg_consumption,
            COALESCE(MIN(f.consumption_per_100) FILTER (WHERE f.consumption_per_100 IS NOT NULL), 0) AS min_consumption,
            COALESCE(MAX(f.consumption_per_100) FILTER (WHERE f.consumption_per_100 IS NOT NULL), 0) AS max_consumption,
            COUNT(*) FILTER (WHERE f.is_anomaly)::int AS anomalies_count
          FROM mgx_fuel_entries f
          JOIN mgx_vehicles v ON v.id = f.vehicle_id
          WHERE ${whereSql}
          GROUP BY v.id, v.reference, v.plate_number, v.brand, v.model
          ORDER BY amount_total DESC
        `,
        values,
      ),
      pool.query(
        `
          SELECT
            date_trunc('month', f.entry_date)::date AS month_start,
            COALESCE(d.label, 'Sans dépôt') AS depot_label,
            COALESCE(SUM(f.total_amount), 0) AS amount
          FROM mgx_fuel_entries f
          LEFT JOIN mgx_depots d ON d.id = f.depot_id
          WHERE ${whereSql}
          GROUP BY month_start, depot_label
          ORDER BY month_start ASC, depot_label ASC
        `,
        values,
      ),
      pool.query(
        `
          SELECT
            fuel.id,
            fuel.label,
            fuel.color,
            COALESCE(SUM(f.quantity), 0) AS quantity,
            COALESCE(SUM(f.total_amount), 0) AS amount,
            COUNT(*)::int AS entries_count
          FROM mgx_fuel_entries f
          LEFT JOIN mgx_referentiels fuel ON fuel.id = f.fuel_type_ref_id
          WHERE ${whereSql}
          GROUP BY fuel.id, fuel.label, fuel.color
          ORDER BY amount DESC
        `,
        values,
      ),
      pool.query(
        `
          SELECT
            fuel_rows.*,
            normal.normal_consumption,
            CASE
              WHEN normal.normal_consumption IS NULL OR normal.normal_consumption = 0 THEN NULL
              ELSE ((fuel_rows.consumption_per_100 - normal.normal_consumption) / normal.normal_consumption) * 100
            END AS anomaly_gap_pct
          FROM (
            ${fuelSelect}
            WHERE ${whereSql}
              AND f.is_anomaly = true
          ) fuel_rows
          LEFT JOIN LATERAL (
            SELECT AVG(consumption_per_100)::numeric AS normal_consumption
            FROM (
              SELECT consumption_per_100
              FROM mgx_fuel_entries previous_entries
              WHERE previous_entries.vehicle_id = fuel_rows.vehicle_id
                AND previous_entries.id <> fuel_rows.id
                AND previous_entries.consumption_per_100 IS NOT NULL
                AND previous_entries.consumption_per_100 > 0
              ORDER BY previous_entries.entry_date DESC, previous_entries.id DESC
              LIMIT 5
            ) last_entries
          ) normal ON true
          ORDER BY fuel_rows.entry_date DESC, fuel_rows.id DESC
        `,
        values,
      ),
    ]);

    const summaryRow = summaryResult.rows[0] || {};
    const months = {};
    const depots = new Set();
    for (const row of monthlyDepotResult.rows) {
      const key = row.month_start.toISOString().slice(0, 7);
      depots.add(row.depot_label);
      months[key] ||= {
        month: row.month_start,
        label: new Intl.DateTimeFormat("fr-DZ", { month: "short", year: "2-digit" }).format(row.month_start),
      };
      months[key][row.depot_label] = toNumber(row.amount);
    }

    res.json({
      summary: {
        total_quantity: toNumber(summaryRow.total_quantity),
        total_amount: toNumber(summaryRow.total_amount),
        total_amount_formatted: formatDzdAmount(summaryRow.total_amount),
        average_price: toNumber(summaryRow.average_price),
        average_price_formatted: formatDzdAmount(summaryRow.average_price),
        vehicles_count: Number(summaryRow.vehicles_count || 0),
        anomalies_count: Number(summaryRow.anomalies_count || 0),
      },
      by_vehicle: byVehicleResult.rows.map((row) => ({
        ...row,
        id: Number(row.id),
        km_total: toNumber(row.km_total),
        quantity_total: toNumber(row.quantity_total),
        amount_total: toNumber(row.amount_total),
        amount_total_formatted: formatDzdAmount(row.amount_total),
        avg_consumption: toNumber(row.avg_consumption),
        min_consumption: toNumber(row.min_consumption),
        max_consumption: toNumber(row.max_consumption),
        anomalies_count: Number(row.anomalies_count || 0),
      })),
      monthly_by_depot: Object.values(months),
      depot_keys: Array.from(depots),
      by_type: byTypeResult.rows.map((row) => ({
        id: row.id ? Number(row.id) : null,
        name: row.label || "Non défini",
        color: row.color || "#F59E0B",
        quantity: toNumber(row.quantity),
        value: toNumber(row.amount),
        amount_formatted: formatDzdAmount(row.amount),
        entries_count: Number(row.entries_count || 0),
      })),
      anomalies: anomaliesResult.rows.map((row) => ({
        ...mapFuelEntry(row),
        normal_consumption: row.normal_consumption === null ? null : toNumber(row.normal_consumption),
        anomaly_gap_pct: row.anomaly_gap_pct === null ? null : toNumber(row.anomaly_gap_pct),
      })),
    });
  },

  async getAnomalies(req, res) {
    req.query.anomaly_only = "true";
    return mgxFuelController.listFuel(req, res);
  },
};
