/**
 * Map domain / HTTP errors to consistent JSON responses.
 */
import type { FastifyReply } from "fastify";
import { FeishuReadinessError } from "../connections/feishuReadiness.js";
import { ProviderReadinessError } from "../connections/providerReadiness.js";
import { HttpError, sendError } from "./auth/guards.js";

export async function handleRouteError(reply: FastifyReply, err: unknown): Promise<void> {
  if (err instanceof HttpError) {
    await sendError(reply, err.statusCode, err.code, err.message);
    return;
  }
  if (err instanceof ProviderReadinessError) {
    await sendError(
      reply,
      err.code === "provider_readiness_unreachable" ? 502 : 400,
      err.code === "provider_readiness_unreachable" ? "provider_unavailable" : "provider_credential_rejected",
      err.message,
    );
    return;
  }
  if (err instanceof FeishuReadinessError) {
    await sendError(
      reply,
      err.code === "feishu_readiness_unreachable" ? 502 : 400,
      err.code === "feishu_readiness_unreachable" ? "feishu_unavailable" : "feishu_credential_rejected",
      err.message,
    );
    return;
  }
  if (err instanceof Error) {
    const mapped = mapDomainError(err.message);
    if (mapped !== null) {
      await sendError(reply, mapped.statusCode, mapped.code, mapped.message);
      return;
    }
    reply.log.error({ err }, "unmapped route error");
    await sendError(reply, 500, "internal_error", "internal error");
    return;
  }
  reply.log.error({ err }, "unmapped route error");
  await sendError(reply, 500, "internal_error", "internal error");
}

function mapDomainError(message: string): { statusCode: number; code: string; message: string } | null {
  const lower = message.toLowerCase();
  if (lower.includes("provider credential readiness check could not reach provider")) {
    return { statusCode: 502, code: "provider_unavailable", message };
  }
  if (lower.includes("provider credential readiness check failed")) {
    return { statusCode: 400, code: "provider_credential_rejected", message };
  }
  if (lower.includes("feishu application readiness check could not reach provider")) {
    return { statusCode: 502, code: "feishu_unavailable", message };
  }
  if (lower.includes("feishu application readiness check") || lower.includes("feishu application credentials were rejected")) {
    return { statusCode: 400, code: "feishu_credential_rejected", message };
  }
  if (lower.includes("not found")) {
    return { statusCode: 404, code: "not_found", message };
  }
  if (
    lower.includes("requires") ||
    lower.includes("forbidden") ||
    lower.includes("cannot") ||
    lower.includes("not an active member") ||
    lower.includes("refused")
  ) {
    return { statusCode: 403, code: "forbidden", message };
  }
  if (
    lower.includes("is required") ||
    lower.includes("already") ||
    lower.includes("invalid") ||
    lower.includes("accepts only") ||
    lower.includes("must be")
  ) {
    return { statusCode: 400, code: "bad_request", message };
  }
  return null;
}
