import fs from "node:fs/promises";
import path from "node:path";
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { config } from "../config.js";

export type UploadResult = {
  outputPath: string;
  thumbnailPath: string;
};

function buildOutputPaths(generationId: string, renderJobId: string): UploadResult {
  const base = `workspaces/${generationId}/renders/${renderJobId}`;

  return {
    outputPath: `${base}.mp4`,
    thumbnailPath: `${base}.jpg`,
  };
}

async function uploadLocal(
  sourceFile: string,
  storagePath: string,
): Promise<void> {
  const destination = path.join(config.localAssetsRoot, storagePath);
  await fs.mkdir(path.dirname(destination), { recursive: true });
  await fs.copyFile(sourceFile, destination);
}

async function uploadS3(sourceFile: string, storagePath: string, contentType: string): Promise<void> {
  const client = new S3Client({
    region: config.s3.region,
    endpoint: config.s3.endpoint,
    credentials: {
      accessKeyId: config.s3.accessKeyId,
      secretAccessKey: config.s3.secretAccessKey,
    },
    forcePathStyle: true,
  });

  const body = await fs.readFile(sourceFile);

  await client.send(
    new PutObjectCommand({
      Bucket: config.s3.bucket,
      Key: storagePath,
      Body: body,
      ContentType: contentType,
    }),
  );
}

export async function uploadRenderOutputs(
  generationId: string,
  renderJobId: string,
  videoFile: string,
  thumbnailFile: string,
): Promise<UploadResult> {
  const paths = buildOutputPaths(generationId, renderJobId);

  if (config.storageDriver === "local") {
    await uploadLocal(videoFile, paths.outputPath);
    await uploadLocal(thumbnailFile, paths.thumbnailPath);
  } else {
    await uploadS3(videoFile, paths.outputPath, "video/mp4");
    await uploadS3(thumbnailFile, paths.thumbnailPath, "image/jpeg");
  }

  return paths;
}
