import { S3Client } from "@aws-sdk/client-s3";
import { Upload } from "@aws-sdk/lib-storage";
import dotenv from "dotenv";
import fs from "fs";
import path from "path";

dotenv.config();

const accountId = process.env.R2_ACCOUNT_ID;
const accessKeyId = process.env.R2_ACCESS_KEY_ID;
const secretAccessKey = process.env.R2_SECRET_ACCESS_KEY;
const bucketName = process.env.R2_BUCKET_NAME;
const publicDomain = process.env.R2_PUBLIC_URL?.replace(/\/$/, "");

if (!accountId || !accessKeyId || !secretAccessKey || !bucketName || !publicDomain) {
  throw new Error("Missing R2 credentials or Public Domain in .env");
}

export const r2Client = new S3Client({
  region: "auto",
  endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
  credentials: {
    accessKeyId,
    secretAccessKey,
  },
});

export const uploadFileToR2 = async (file: Express.Multer.File) => {
  const fileKey = `${Date.now()}-${encodeURIComponent(file.originalname.replace(/\s+/g, '-'))}`;

  try {
    // Use Upload from @aws-sdk/lib-storage for safer streaming
    const upload = new Upload({
      client: r2Client,
      params: {
        Bucket: bucketName,
        Key: fileKey,
        Body: fs.createReadStream(file.path), // read from temp file
        ContentType: file.mimetype,
      },
      queueSize: 4,
      partSize: 5 * 1024 * 1024, // 5 MB
    });

    await upload.done(); // completes the upload

    // Delete the temp file from server
    fs.unlink(file.path, (err) => {
      if (err) console.error("Failed to delete temp file:", err);
    });

    const publicUrl = `${publicDomain}/${fileKey}`;
    return {
      success: true,
      key: fileKey,
      url: publicUrl,
    };
  } catch (error) {
    console.error("R2 Upload Error:", error);

    // Delete temp file on error as well
    fs.unlink(file.path, (err) => {
      if (err) console.error("Failed to delete temp file:", err);
    });

    throw new Error("Failed to upload file to R2");
  }
};
