import { PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { v4 as uuidv4 } from "uuid";
import { s3Client, S3_BUCKET, getPublicUrl } from "./s3";

const MAX_FILE_SIZE = 5 * 1024 * 1024;
const ALLOWED_TYPES = ["image/jpeg", "image/png", "image/webp"] as const;
const MAX_FILES = 3;

export { MAX_FILE_SIZE, ALLOWED_TYPES, MAX_FILES, getPublicUrl };

export type AllowedImageType = (typeof ALLOWED_TYPES)[number];

const MAGIC_BYTES: Record<AllowedImageType, Array<(buf: Buffer) => boolean>> = {
  "image/jpeg": [(b) => b.length >= 3 && b[0] === 0xff && b[1] === 0xd8 && b[2] === 0xff],
  "image/png": [(b) => b.length >= 8 && b[0] === 0x89 && b[1] === 0x50 && b[2] === 0x4e && b[3] === 0x47 && b[4] === 0x0d && b[5] === 0x0a && b[6] === 0x1a && b[7] === 0x0a],
  "image/webp": [(b) => b.length >= 12 && b.slice(0, 4).toString("ascii") === "RIFF" && b.slice(8, 12).toString("ascii") === "WEBP"],
};

export function detectImageType(buf: Buffer): AllowedImageType | null {
  for (const type of ALLOWED_TYPES) {
    if (MAGIC_BYTES[type].some((check) => check(buf))) return type;
  }
  return null;
}

export function sanitizeUploadKey(key: string): string {
  if (!/^uploads\/[a-zA-Z0-9_-]+\/[a-f0-9-]+\.(jpe?g|png|webp)$/i.test(key)) {
    throw new Error("Invalid key format");
  }
  return key;
}

export async function generatePresignedUrl(
  contentType: string,
  userId: string
): Promise<{ url: string; key: string; publicUrl: string }> {
  if (!ALLOWED_TYPES.includes(contentType as AllowedImageType)) {
    throw new Error(`Invalid content type: ${contentType}`);
  }

  const ext = contentType.split("/")[1];
  const key = `uploads/${userId}/${uuidv4()}.${ext}`;

  const command = new PutObjectCommand({
    Bucket: S3_BUCKET,
    Key: key,
    ContentType: contentType,
  });

  const url = await getSignedUrl(s3Client, command, { expiresIn: 3600 });

  return {
    url,
    key,
    publicUrl: getPublicUrl(key),
  };
}
