import "server-only";

import { z } from "zod";

import { cmsTarget, laravelApiUrl } from "@/lib/laravel-cms/environment";

const httpUrl = z
  .url({ protocol: /^https?$/ })
  .transform((value) => value.replace(/\/+$/, ""));

const schema = z.object({
  /** Which Laravel CMS: "prod" or "dev" (staging). See lib/laravel-cms/environment.ts. */
  CMS_ENV: z.enum(["prod", "dev"]),
  /**
   * The Laravel blog CMS API (docs/laravel-blog-api.md), from CMS_ENV unless
   * LARAVEL_API_URL overrides it. Every page and action reads and writes through it.
   */
  LARAVEL_API_URL: httpUrl,
  /** The public website that renders the blog. Used for "View live" links and previews. */
  SITE_URL: httpUrl.optional(),
  /** Sent to the website's /api/revalidate as `x-revalidate-secret`, if the website requires one. */
  REVALIDATE_SECRET: z.string().optional(),
  /** Largest image the uploader accepts, in megabytes. Keep it in step with Laravel's limit. */
  MEDIA_MAX_UPLOAD_MB: z.coerce.number().positive().max(50).default(10),
  /**
   * Hosts the JSON import may download images from when it uploads them to
   * the media library (comma-separated). The CMS's own host is always allowed.
   */
  IMPORT_IMAGE_HOSTS: z
    .string()
    .default("wifi-calls-web.vercel.app")
    .transform((value) =>
      value
        .split(",")
        .map((host) => host.trim().toLowerCase())
        .filter(Boolean),
    ),
});

export type Env = z.infer<typeof schema>;

let cached: Env | undefined;

/**
 * Validated server environment. Parsed on first use rather than at import,
 * so `next build` works without runtime settings.
 */
export function env(): Env {
  if (cached) return cached;
  let resolved: { CMS_ENV: string; LARAVEL_API_URL: string };
  try {
    resolved = {
      CMS_ENV: cmsTarget(),
      LARAVEL_API_URL: laravelApiUrl(),
    };
  } catch (error) {
    throw new Error(
      `Invalid environment variables:\n  - ${error instanceof Error ? error.message : String(error)}`,
    );
  }
  const result = schema.safeParse({ ...process.env, ...resolved });
  if (!result.success) {
    const issues = result.error.issues
      .map((issue) => `  - ${issue.path.join(".")}: ${issue.message}`)
      .join("\n");
    throw new Error(`Invalid environment variables:\n${issues}`);
  }
  cached = result.data;
  return cached;
}

/** Origin of the Laravel server, e.g. https://secondphonenumber.worksqr.com. Uploads are served from it. */
export function cmsOrigin() {
  return new URL(env().LARAVEL_API_URL).origin;
}
