import { NextRequest, NextResponse } from "next/server";
import path from "path";
import { promises as fs } from "fs";
import { randomUUID } from "crypto";
import { getSession } from "@/lib/auth";
import { readStorageConfig } from "@/lib/backup-config";

import { pgGetSettings } from "@/lib/postgres/data-access";

async function resolveStorageDir() {
  const settings = await pgGetSettings();
  const deploymentMode = String(settings.deploymentMode || "local").trim().toLowerCase();
  const customPath = String(settings.documentStoragePath || "").trim();
  const configuredDocumentsPath = String(readStorageConfig().documentsPath || "").trim();

  if (deploymentMode === "local" && customPath) {
    return path.resolve(customPath);
  }

  if (configuredDocumentsPath) {
    return path.resolve(configuredDocumentsPath, "purchase-documents");
  }

  return path.join(process.cwd(), "uploads", "purchase-documents");
}

function toSafeFileName(originalName: string) {
  const baseName = path.basename(originalName || "document");
  const sanitized = baseName.replace(/[^a-zA-Z0-9._-]/g, "_");
  return sanitized || `document-${Date.now()}`;
}

export async function POST(request: NextRequest) {
  const session = await getSession();
  if (!session?.user || session.user.role !== "admin") {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const formData = await request.formData();
  const file = formData.get("file");

  if (!(file instanceof File)) {
    return NextResponse.json({ error: "No file provided" }, { status: 400 });
  }

  const storageDir = await resolveStorageDir();
  await fs.mkdir(storageDir, { recursive: true });

  const ext = path.extname(file.name || "");
  const safeBase = toSafeFileName(path.basename(file.name || "document", ext));
  const finalName = `${Date.now()}-${safeBase}-${randomUUID().slice(0, 8)}${ext}`;
  const targetPath = path.join(storageDir, finalName);

  const buffer = Buffer.from(await file.arrayBuffer());
  await fs.writeFile(targetPath, buffer);

  return NextResponse.json({
    success: true,
    document: {
      id: randomUUID(),
      name: file.name || finalName,
      filePath: targetPath,
      mimeType: file.type || undefined,
      size: file.size,
      uploadedAt: new Date().toISOString(),
      uploadedBy: session.user.name || session.user.id,
    },
  });
}

export async function GET(request: NextRequest) {
  const session = await getSession();
  if (!session?.user || session.user.role !== "admin") {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const params = request.nextUrl.searchParams;
  const filePath = String(params.get("filePath") || "").trim();
  const downloadName = String(params.get("name") || "").trim();

  if (!filePath) {
    return NextResponse.json({ error: "filePath is required" }, { status: 400 });
  }

  const tryDecode = (value: string) => {
    try {
      return decodeURIComponent(value);
    } catch {
      return value;
    }
  };

  const normalizedRaw = filePath.replace(/^['"]|['"]$/g, "").trim();
  const normalizedDecoded = tryDecode(normalizedRaw).replace(/^['"]|['"]$/g, "").trim();
  const normalizedInput = normalizedDecoded || normalizedRaw;
  const absolutePath = path.resolve(normalizedInput);
  const storageDir = await resolveStorageDir();
  const legacyUploadsDir = path.join(process.cwd(), "uploads", "purchase-documents");

  const allowedRoots = [path.resolve(storageDir), path.resolve(legacyUploadsDir)];
  const allowed = allowedRoots.some((root) => absolutePath.startsWith(root));
  if (!allowed) {
    return NextResponse.json({ error: "Access denied" }, { status: 403 });
  }

  const fileExists = async (targetPath: string) => {
    try {
      await fs.access(targetPath);
      return true;
    } catch {
      return false;
    }
  };

  let readablePath = absolutePath;
  if (!(await fileExists(readablePath))) {
    const fileName = path.basename(normalizedInput || absolutePath);
    const fallbackCandidates = [
      path.join(storageDir, fileName),
      path.join(legacyUploadsDir, fileName),
    ];
    const found = await Promise.all(fallbackCandidates.map(async (candidate) => ({ candidate, ok: await fileExists(candidate) })));
    const winner = found.find((entry) => entry.ok)?.candidate;
    if (winner) {
      readablePath = winner;
    }
  }

  try {
    const fileBuffer = await fs.readFile(readablePath);
    const contentType =
      readablePath.endsWith(".pdf")
        ? "application/pdf"
        : readablePath.endsWith(".png")
          ? "image/png"
          : readablePath.endsWith(".jpg") || readablePath.endsWith(".jpeg")
            ? "image/jpeg"
            : readablePath.endsWith(".webp")
              ? "image/webp"
              : "application/octet-stream";

    return new NextResponse(fileBuffer, {
      status: 200,
      headers: {
        "Content-Type": contentType,
        "Content-Disposition": `inline; filename="${downloadName || path.basename(readablePath)}"`,
      },
    });
  } catch {
    return NextResponse.json({ error: "File not found" }, { status: 404 });
  }
}
