/**
 * Server-side form submission client for Strapi.
 *
 * Used only from Next.js Route Handlers (app/api/*). It forwards validated
 * form payloads to a Strapi collection type using the server-only
 * `STRAPI_TOKEN`, so the token never reaches the browser and Strapi's public
 * API can stay closed.
 */

import { strapiConfig } from "./config"

export type SubmissionOutcome =
  | { ok: true }
  | {
      ok: false
      reason: "duplicate" | "invalid" | "unconfigured" | "unreachable"
      message: string
    }

/**
 * Create a single entry in a Strapi collection type.
 *
 * @param pluralApiId - plural API id of the collection (e.g. "contact-submissions")
 * @param data        - validated attributes payload
 */
export async function submitToStrapi(
  pluralApiId: string,
  data: Record<string, unknown>,
): Promise<SubmissionOutcome> {
  if (!strapiConfig.url) {
    return {
      ok: false,
      reason: "unconfigured",
      message: "Strapi URL is not configured.",
    }
  }
  if (!strapiConfig.token) {
    return {
      ok: false,
      reason: "unconfigured",
      message: "STRAPI_TOKEN is not set on the server.",
    }
  }

  const url = `${strapiConfig.url}${strapiConfig.apiPrefix}/${pluralApiId}`

  try {
    const res = await fetch(url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${strapiConfig.token}`,
      },
      body: JSON.stringify({ data }),
      cache: "no-store",
    })

    if (res.ok) return { ok: true }

    let bodyText = ""
    try {
      bodyText = await res.text()
    } catch {
      // ignore body read errors
    }
    const lower = bodyText.toLowerCase()

    // Unique-constraint violation (e.g. newsletter email already subscribed)
    if (
      lower.includes("unique") ||
      lower.includes("already exist") ||
      lower.includes("already taken") ||
      lower.includes("already registered")
    ) {
      return {
        ok: false,
        reason: "duplicate",
        message: "This email is already registered.",
      }
    }

    if (res.status === 400 || res.status === 422) {
      return {
        ok: false,
        reason: "invalid",
        message: "Strapi rejected the submission as invalid.",
      }
    }

    if (res.status === 401 || res.status === 403) {
      return {
        ok: false,
        reason: "unconfigured",
        message: "The server token lacks permission to write to this collection.",
      }
    }

    return {
      ok: false,
      reason: "unreachable",
      message: `Strapi responded with ${res.status}.`,
    }
  } catch {
    return {
      ok: false,
      reason: "unreachable",
      message: "Could not reach Strapi.",
    }
  }
}

/** Map a failed-outcome reason to an HTTP status for Route Handlers. */
export function outcomeStatus(
  reason: "duplicate" | "invalid" | "unconfigured" | "unreachable",
): number {
  switch (reason) {
    case "duplicate":
      return 409
    case "invalid":
      return 400
    case "unconfigured":
      return 503
    case "unreachable":
      return 502
  }
}
