import { ApiError } from "../utils/ApiError.js";
import * as rpnRepo from "../repositories/rpnRepository.js";

function numOrThrow(v, field) {
  const n = Number(v);
  if (!Number.isFinite(n)) {
    throw new ApiError(400, `${field} must be a number`);
  }
  return n;
}

function strOrThrow(v, field) {
  if (v == null || typeof v !== "string") {
    throw new ApiError(400, `${field} must be a string`);
  }
  const s = v.trim();
  if (!s) {
    throw new ApiError(400, `${field} must be non-empty`);
  }
  return s;
}

export async function getLikelihoodList(_req, res, next) {
  try {
    const rows = await rpnRepo.listLikelihood();
    res.json(rows);
  } catch (e) {
    next(e);
  }
}

export async function getSeverityList(_req, res, next) {
  try {
    const rows = await rpnRepo.listSeverity();
    res.json(rows);
  } catch (e) {
    next(e);
  }
}

export async function postLikelihood(req, res, next) {
  try {
    const label = strOrThrow(req.body?.likelihood_of_harm, "likelihood_of_harm");
    const value = numOrThrow(req.body?.value, "value");
    await rpnRepo.insertLikelihood(label, value);
    res.status(201).json({ message: "Created", likelihood_of_harm: label, value });
  } catch (e) {
    next(e);
  }
}

export async function putLikelihood(req, res, next) {
  try {
    const label = strOrThrow(req.body?.likelihood_of_harm, "likelihood_of_harm");
    const value = numOrThrow(req.body?.value, "value");
    const n = await rpnRepo.updateLikelihood(label, value);
    if (!n) {
      throw new ApiError(404, "Likelihood row not found");
    }
    res.json({ message: "Updated", likelihood_of_harm: label, value });
  } catch (e) {
    next(e);
  }
}

export async function deleteLikelihood(req, res, next) {
  try {
    const raw = req.params?.likelihood_of_harm;
    const label =
      raw == null ? "" : typeof raw === "string" ? decodeURIComponent(raw) : String(raw);
    if (!label.trim()) {
      throw new ApiError(400, "likelihood_of_harm param required");
    }
    const n = await rpnRepo.deleteLikelihood(label);
    if (!n) {
      throw new ApiError(404, "Likelihood row not found");
    }
    res.json({ message: "Deleted" });
  } catch (e) {
    next(e);
  }
}

export async function postSeverity(req, res, next) {
  try {
    const label = strOrThrow(req.body?.severity_of_harm, "severity_of_harm");
    const value = numOrThrow(req.body?.value, "value");
    await rpnRepo.insertSeverity(label, value);
    res.status(201).json({ message: "Created", severity_of_harm: label, value });
  } catch (e) {
    next(e);
  }
}

export async function putSeverity(req, res, next) {
  try {
    const label = strOrThrow(req.body?.severity_of_harm, "severity_of_harm");
    const value = numOrThrow(req.body?.value, "value");
    const n = await rpnRepo.updateSeverity(label, value);
    if (!n) {
      throw new ApiError(404, "Severity row not found");
    }
    res.json({ message: "Updated", severity_of_harm: label, value });
  } catch (e) {
    next(e);
  }
}

export async function deleteSeverity(req, res, next) {
  try {
    const raw = req.params?.severity_of_harm;
    const label =
      raw == null ? "" : typeof raw === "string" ? decodeURIComponent(raw) : String(raw);
    if (!label.trim()) {
      throw new ApiError(400, "severity_of_harm param required");
    }
    const n = await rpnRepo.deleteSeverity(label);
    if (!n) {
      throw new ApiError(404, "Severity row not found");
    }
    res.json({ message: "Deleted" });
  } catch (e) {
    next(e);
  }
}
