/**
 * S3 storage helpers for {{titleCase name}}
 *
 * Environment variables (injected by mesh link()):
 * - UPLOADS_BUCKET: S3 bucket name
 * - UPLOADS_REGION: AWS region
 */

import {
  S3Client,
  PutObjectCommand,
  GetObjectCommand,
  DeleteObjectCommand,
  ListObjectsV2Command,
} from "@aws-sdk/client-s3";

if (!process.env.UPLOADS_BUCKET) {
  throw new Error("UPLOADS_BUCKET environment variable is required");
}
const BUCKET = process.env.UPLOADS_BUCKET;
const REGION = process.env.UPLOADS_REGION ?? "us-east-2";

const s3 = new S3Client({ region: REGION });

/**
 * Upload a file to S3
 */
export async function uploadFile(
  key: string,
  body: Buffer | string,
  contentType?: string
): Promise<{ key: string; bucket: string }> {
  await s3.send(
    new PutObjectCommand({
      Bucket: BUCKET,
      Key: key,
      Body: body,
      ContentType: contentType,
    })
  );
  return { key, bucket: BUCKET };
}

/**
 * Download a file from S3
 */
export async function downloadFile(key: string): Promise<Buffer> {
  const response = await s3.send(
    new GetObjectCommand({ Bucket: BUCKET, Key: key })
  );
  const chunks: Uint8Array[] = [];
  for await (const chunk of response.Body as AsyncIterable<Uint8Array>) {
    chunks.push(chunk);
  }
  return Buffer.concat(chunks);
}

/**
 * Delete a file from S3
 */
export async function deleteFile(key: string): Promise<void> {
  await s3.send(
    new DeleteObjectCommand({ Bucket: BUCKET, Key: key })
  );
}

/**
 * List files in a prefix
 */
export async function listFiles(
  prefix: string
): Promise<{ key: string; size: number; lastModified: Date }[]> {
  const response = await s3.send(
    new ListObjectsV2Command({ Bucket: BUCKET, Prefix: prefix })
  );
  return (response.Contents ?? []).map((obj) => ({
    key: obj.Key!,
    size: obj.Size!,
    lastModified: obj.LastModified!,
  }));
}
