import "server-only";
import { S3Client, PutObjectCommand, DeleteObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import fs from "fs/promises";
import path from "path";

const isR2Configured =
  process.env.R2_ACCOUNT_ID &&
  process.env.R2_ACCOUNT_ID !== "your_cloudflare_account_id";

// ── R2 (production) ──────────────────────────────────────────────────────────

const r2 = isR2Configured
  ? new S3Client({
      region: "auto",
      endpoint: `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,
      credentials: {
        accessKeyId: process.env.R2_ACCESS_KEY_ID!,
        secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
      },
    })
  : null;

// ── Local fallback (dev) ─────────────────────────────────────────────────────

const LOCAL_UPLOAD_DIR = path.join(process.cwd(), "public", "uploads");

async function uploadLocal(key: string, body: Buffer | Uint8Array): Promise<string> {
  const filePath = path.join(LOCAL_UPLOAD_DIR, key);
  await fs.mkdir(path.dirname(filePath), { recursive: true });
  await fs.writeFile(filePath, body);
  return `/uploads/${key}`;
}

async function deleteLocal(key: string): Promise<void> {
  const filePath = path.join(LOCAL_UPLOAD_DIR, key);
  await fs.unlink(filePath).catch(() => { /* already gone */ });
}

async function downloadLocal(key: string): Promise<Buffer> {
  const filePath = path.join(LOCAL_UPLOAD_DIR, key);
  return fs.readFile(filePath);
}

// ── Public API ───────────────────────────────────────────────────────────────

export async function uploadFile(
  key: string,
  body: Buffer | Uint8Array,
  contentType: string
): Promise<string> {
  if (!isR2Configured) {
    console.log("[storage] R2 not configured — using local fallback");
    return uploadLocal(key, body);
  }

  await r2!.send(
    new PutObjectCommand({
      Bucket: process.env.R2_BUCKET_NAME!,
      Key: key,
      Body: body,
      ContentType: contentType,
    })
  );
  return `${process.env.R2_PUBLIC_URL}/${key}`;
}

export async function downloadFile(key: string): Promise<Buffer> {
  if (!isR2Configured) {
    console.log("[storage] R2 not configured — using local fallback");
    return downloadLocal(key);
  }

  const response = await r2!.send(
    new GetObjectCommand({
      Bucket: process.env.R2_BUCKET_NAME!,
      Key: key,
    })
  );

  const chunks: Uint8Array[] = [];
  const readable = response.Body as any;
  
  for await (const chunk of readable) {
    chunks.push(chunk);
  }

  return Buffer.concat(chunks);
}

export async function deleteFile(key: string): Promise<void> {
  if (!isR2Configured) {
    return deleteLocal(key);
  }
  await r2!.send(new DeleteObjectCommand({ Bucket: process.env.R2_BUCKET_NAME!, Key: key }));
}
