import "server-only";

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

import { env } from "@/lib/env";
import type { StorageDriver } from "@/lib/storage";

export function createS3Storage(): StorageDriver {
  const config = env();
  const { S3_BUCKET, S3_PUBLIC_URL } = config;
  if (!S3_BUCKET || !S3_PUBLIC_URL) {
    throw new Error(
      "STORAGE_DRIVER=s3 needs S3_BUCKET and S3_PUBLIC_URL (plus credentials).",
    );
  }

  const client = new S3Client({
    region: config.S3_REGION ?? "auto",
    endpoint: config.S3_ENDPOINT,
    forcePathStyle: Boolean(config.S3_ENDPOINT),
    credentials:
      config.S3_ACCESS_KEY_ID && config.S3_SECRET_ACCESS_KEY
        ? {
            accessKeyId: config.S3_ACCESS_KEY_ID,
            secretAccessKey: config.S3_SECRET_ACCESS_KEY,
          }
        : undefined,
  });
  const publicBase = S3_PUBLIC_URL.replace(/\/+$/, "");

  return {
    async put(key, body, contentType) {
      await client.send(
        new PutObjectCommand({
          Bucket: S3_BUCKET,
          Key: key,
          Body: body,
          ContentType: contentType,
          // Keys are unique per upload, so the object never changes.
          CacheControl: "public, max-age=31536000, immutable",
        }),
      );
      return { url: `${publicBase}/${key}` };
    },
    async delete(key) {
      await client.send(new DeleteObjectCommand({ Bucket: S3_BUCKET, Key: key }));
    },
  };
}
