// src/data-access/file-nodes.ts
import "server-only";

import { getOneDriveFileBuffer } from "@/services/onedrive";
import { extractMetadata } from "@/lib/metadata-extractor";
import { prisma } from "@/lib/prisma";


/**
 * FETCH: Retrieve all nodes for the dashboard.
 * Centralizing this here allows us to change sort order or filters 
 * in one place for the entire application.
 */
export async function getAllFileNodes() {
  return await prisma.fileNode.findMany({
    orderBy: {
      updatedAt: 'desc',
    },
  });
}

/**
 * FETCH: Get a single node by ID.
 * Used by the Download route and Update pages to verify a file exists.
 */
export async function getFileNodeById(id: string) {
  return await prisma.fileNode.findUnique({
    where: { id },
  });
}

/**
 * UPDATE: Modify metadata, name, or virtual location.
 * This function accepts the data object to keep the DAL flexible.
 */
export async function updateFileNode(id: string, data: any) {
  return await prisma.fileNode.update({
    where: { id },
    data: {
      ...data,
      updatedAt: new Date(),
    },
  });
}

/**
 * DELETE: Remove the record from the database.
 * Cloud deletion should be handled by the Service Layer before calling this.
 */
export async function deleteFileNode(id: string) {
  return await prisma.fileNode.delete({
    where: { id },
  });
}

/**
 * MASTER CREATE: Handles both standard uploads and virtual folders.
 * If no ID is provided, it generates a fresh UUID.
 */
export async function createFileNode(data: {
  id?: string;             // Optional: used for virtual folders/UUID storage
  oneDriveId: string | null;
  name: string;
  description?: string;
  isFolder: boolean;
  path: string;
  ownerId: string;
  parentId?: string | null; // Optional: for nested structures
  size?: bigint;
  metadata: any;
}) {
  return await prisma.fileNode.create({
    data: {
      ...data,
      id: data.id ?? crypto.randomUUID(), // Use provided ID or generate new one
    }
  });
}


// ... other functions (getAllFileNodes, etc)

/**
 * UPSERT: Create or Update a file node based on OneDrive ID
 * Moved here because it interacts with the Database.
 */
export async function upsertFileNode(oneDriveId: string, data: any) {
  return await prisma.fileNode.upsert({
    where: { oneDriveId },
    update: {
      name: data.name,
      size: data.size,
      isFolder: data.isFolder,
      path: data.path,
      updatedAt: new Date(),
    },
    create: {
      id: crypto.randomUUID(),
      oneDriveId: oneDriveId,
      name: data.name,
      size: data.size,
      isFolder: data.isFolder,
      path: data.path,
      ownerId: data.ownerId,
      metadata: data.metadata,
    }
  });
}



/**
 * Logic to coordinate getting a file from the cloud and extracting its data.
 * This is the "Brain" function for your metadata enrichment.
 */
export async function getEnrichedMetadataFromCloud(fileId: string) {
  // 1. Get the record from our DB so we know the filename (needed for extension logic)
  const node = await prisma.fileNode.findUnique({
    where: { id: fileId }
  });

  if (!node) throw new Error("File not found in database.");

  // 2. Fetch the bytes using the service we just created
  const buffer = await getOneDriveFileBuffer(fileId);

  // 3. Extract internal metadata (Title, Author, or GPS coordinates)
  const deepMetadata = await extractMetadata(buffer, node.name);

  return deepMetadata;
}