import "server-only";

import { ChatTokenBuilder } from "agora-token";

// Server-only — mints Agora Chat tokens and provisions Chat users.
// Never import this from a client component; `server-only` throws a
// build error if that ever happens by mistake.
//
// Confirmed live (see conversation history, not guessed): this Agora
// project's Chat feature has "Open Registration" turned OFF, so a
// user must be created via this REST call before they can log into
// Chat with a user token — logging in as a never-created username
// fails with a real `{"type":204,"message":"User not found"}`.

function getAppId(): string {
  const appId = process.env.NEXT_PUBLIC_AGORA_APP_ID;
  if (!appId) throw new Error("NEXT_PUBLIC_AGORA_APP_ID is not configured.");
  return appId;
}

function getAppCertificate(): string {
  const cert = process.env.AGORA_APP_CERTIFICATE;
  if (!cert) throw new Error("AGORA_APP_CERTIFICATE is not configured.");
  return cert;
}

function getRestBase(): string {
  const host = process.env.AGORA_CHAT_REST_HOST;
  const org = process.env.AGORA_CHAT_ORG_NAME;
  const app = process.env.AGORA_CHAT_APP_NAME;

  if (!host || !org || !app) {
    throw new Error(
      "AGORA_CHAT_REST_HOST / AGORA_CHAT_ORG_NAME / AGORA_CHAT_APP_NAME are not configured."
    );
  }

  return `https://${host}/${org}/${app}`;
}

export function mintChatAppToken(expireSeconds = 3600): string {
  return ChatTokenBuilder.buildAppToken(getAppId(), getAppCertificate(), expireSeconds);
}

export function mintChatUserToken(username: string, expireSeconds = 3600): string {
  return ChatTokenBuilder.buildUserToken(getAppId(), getAppCertificate(), username, expireSeconds);
}

// Idempotent — a username that already exists is treated as success
// (Agora's REST API 400s with a "duplicate_unique_property_exists"
// style error for that case, not a distinct "already exists" status
// code, so this checks the response body rather than just the HTTP
// status).
export async function ensureChatUserExists(username: string): Promise<void> {
  const appToken = mintChatAppToken();

  const response = await fetch(`${getRestBase()}/users`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${appToken}`,
    },
    // Agora's REST "create user" requires a password field even
    // though every real login in this app uses token auth — it's
    // never used to authenticate anyone, so a random throwaway value
    // is fine here.
    body: JSON.stringify({
      username,
      password: `unused-${Math.random().toString(36).slice(2)}`,
    }),
  });

  if (response.ok) return;

  const text = await response.text();

  if (/duplicate|already/i.test(text)) return;

  throw new Error(`Unable to provision Chat user "${username}": ${text}`);
}
