import { createClient as createSupabaseClient } from "@supabase/supabase-js";
import type { Attachment } from "@/types";

function getSupabaseAdmin() {
  return createSupabaseClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.SUPABASE_SERVICE_ROLE_KEY!
  );
}

export function sanitizeAttachmentFileName(name: string) {
  return name.replace(/[^a-zA-Z0-9._-]/g, "-");
}

export async function ensureAttachmentsBucket() {
  const supabase = getSupabaseAdmin();
  const { data, error } = await supabase.storage.getBucket("attachments");

  if (!error && data) {
    return;
  }

  const { error: createError } = await supabase.storage.createBucket("attachments", {
    public: true,
  });

  if (createError && !/already exists/i.test(createError.message)) {
    throw createError;
  }
}

export async function uploadAttachmentBuffer(input: {
  userId: string;
  teamId: string | null;
  projectId: string | null;
  entityType: Attachment["entity_type"];
  entityId: string;
  fileName: string;
  mimeType: string | null;
  buffer: Buffer;
}) {
  await ensureAttachmentsBucket();

  const admin = getSupabaseAdmin();
  const safeFileName = sanitizeAttachmentFileName(input.fileName);
  const path = `${input.userId}/${input.entityType}/${input.entityId}/${Date.now()}-${safeFileName}`;

  const { error: uploadError } = await admin.storage
    .from("attachments")
    .upload(path, input.buffer, {
      contentType: input.mimeType || undefined,
      upsert: false,
    });

  if (uploadError) {
    throw uploadError;
  }

  const {
    data: { publicUrl },
  } = admin.storage.from("attachments").getPublicUrl(path);

  const { data, error } = await admin
    .from("attachments")
    .insert({
      user_id: input.userId,
      team_id: input.teamId,
      project_id: input.projectId,
      entity_type: input.entityType,
      entity_id: input.entityId,
      file_name: input.fileName,
      storage_path: path,
      public_url: publicUrl,
      mime_type: input.mimeType,
      size_bytes: input.buffer.byteLength,
    })
    .select("*")
    .single();

  if (error) {
    await admin.storage.from("attachments").remove([path]);
    throw error;
  }

  return data as Attachment;
}
