import { v2 as cloudinary } from "cloudinary";

type AvatarTarget = "user" | "team";

interface UploadAvatarImageArgs {
  buffer: Buffer;
  contentType: string;
  target: AvatarTarget;
  entityId: string;
  notificationUrl: string;
}

interface UploadSportIconArgs {
  buffer: Buffer;
  slug?: string | null;
}

function requireCloudinaryConfig() {
  const cloudName = process.env.CLOUDINARY_CLOUD_NAME;
  const apiKey = process.env.CLOUDINARY_API_KEY;
  const apiSecret = process.env.CLOUDINARY_API_SECRET;

  if (!cloudName || !apiKey || !apiSecret) {
    throw new Error("Cloudinary environment variables are not configured");
  }

  cloudinary.config({
    cloud_name: cloudName,
    api_key: apiKey,
    api_secret: apiSecret,
    secure: true,
  });
}

function toDataUri(buffer: Buffer, contentType: string): string {
  return `data:${contentType};base64,${buffer.toString("base64")}`;
}

export async function uploadAvatarImage({
  buffer,
  contentType,
  target,
  entityId,
  notificationUrl,
}: UploadAvatarImageArgs) {
  requireCloudinaryConfig();

  return await cloudinary.uploader.upload(toDataUri(buffer, contentType), {
    resource_type: "image",
    folder: "avatars",
    public_id: `${target}-${entityId}-${Date.now()}`,
    overwrite: true,
    moderation: "aws_rek",
    notification_url: notificationUrl,
    context: {
      avatar_target: target,
      entity_id: entityId,
    },
    transformation: [{ width: 256, height: 256, crop: "fill", gravity: "face" }],
  });
}

function normalizePublicIdPart(value: string | null | undefined): string {
  const normalized = value?.trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
  return normalized || "sport";
}

export async function uploadSportIcon({ buffer, slug }: UploadSportIconArgs) {
  requireCloudinaryConfig();

  return await cloudinary.uploader.upload(toDataUri(buffer, "image/svg+xml"), {
    resource_type: "image",
    folder: "sports-icons",
    public_id: `${normalizePublicIdPart(slug)}-${Date.now()}`,
    allowed_formats: ["svg"],
    overwrite: false,
  });
}

export function cloudinaryPublicIdFromUrl(url: string | null | undefined): string | null {
  if (!url) return null;
  if (!url.includes("res.cloudinary.com") || !url.includes("/image/upload/")) return null;
  const path = url.split("?")[0];
  const match = path.match(/\/(?:v\d+\/)?((?:avatars|sports-icons)\/[^.]+)/);
  return match?.[1] ?? null;
}

export function buildWebhookUrl(request: Request): string {
  const baseUrl = process.env.APP_URL ?? process.env.BETTER_AUTH_URL ?? new URL(request.url).origin;
  return new URL("/api/webhooks/cloudinary", baseUrl).toString();
}

export async function deleteCloudinaryImageByUrl(url: string | null | undefined): Promise<void> {
  const publicId = cloudinaryPublicIdFromUrl(url);
  if (!publicId) return;

  requireCloudinaryConfig();
  await cloudinary.uploader.destroy(publicId, { resource_type: "image", invalidate: true });
}

export function verifyCloudinaryWebhookSignature({
  body,
  signature,
  timestamp,
}: {
  body: string;
  signature: string | null;
  timestamp: string | null;
}): boolean {
  requireCloudinaryConfig();

  if (!signature || !timestamp) return false;
  const parsedTimestamp = Number(timestamp);
  if (!Number.isFinite(parsedTimestamp)) return false;

  return cloudinary.utils.verifyNotificationSignature(body, parsedTimestamp, signature);
}
