const assert = require("assert");
const fs = require("fs");
const os = require("os");
const path = require("path");

const {
  cleanupUploadedFiles,
  safeDownloadFilename,
  validateUploadedFile,
  validateUploadedFiles
} = require("../src/services/upload-security");

const sandbox = fs.mkdtempSync(path.join(os.tmpdir(), "lumi-upload-security-"));

function upload(name, mime, bytes) {
  const filePath = path.join(sandbox, `${Date.now()}-${Math.random()}`);
  fs.writeFileSync(filePath, bytes);
  return { path: filePath, originalname: name, mimetype: mime, size: bytes.length };
}

try {
  const png = upload("icon.png", "image/png", Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00]));
  validateUploadedFile(png, { allowedTypes: ["png"], maxBytes: 1024, requireExtension: true });
  assert.equal(png.detectedType, "png");

  const disguised = upload("not-really.png", "image/png", Buffer.from("not an image"));
  assert.throws(() => validateUploadedFiles([disguised], { allowedTypes: ["png"], maxBytes: 1024 }), /contents/);
  assert.equal(fs.existsSync(disguised.path), false);

  const mismatch = upload("photo.jpg", "image/jpeg", Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]));
  assert.throws(() => validateUploadedFiles([mismatch], { allowedTypes: ["png", "jpeg"] }), /browser|extension/);
  assert.equal(fs.existsSync(mismatch.path), false);

  const unsafeSvg = upload("icon.svg", "image/svg+xml", Buffer.from('<svg xmlns="http://www.w3.org/2000/svg"><script>alert(1)</script></svg>'));
  assert.throws(() => validateUploadedFiles([unsafeSvg], { allowedTypes: ["svg"] }), /contents/);
  assert.equal(fs.existsSync(unsafeSvg.path), false);

  const safeSvg = upload("icon.svg", "image/svg+xml", Buffer.from('<svg xmlns="http://www.w3.org/2000/svg"><path d="M0 0h1v1z"/></svg>'));
  validateUploadedFile(safeSvg, { allowedTypes: ["svg"], requireExtension: true });

  const oversized = upload("large.txt", "text/plain", Buffer.from("12345"));
  assert.throws(() => validateUploadedFiles([oversized], { allowedTypes: ["text"], maxBytes: 4 }), /larger/);
  assert.equal(fs.existsSync(oversized.path), false);

  assert.equal(safeDownloadFilename('../../bad\r\n"name.txt'), "badname.txt");
  assert.equal(safeDownloadFilename("..\\..\\secret.txt"), "secret.txt");

  const serverSource = fs.readFileSync(path.join(__dirname, "..", "src", "web", "server.js"), "utf8");
  const moderationSource = fs.readFileSync(path.join(__dirname, "..", "plugins", "moderation", "index.js"), "utf8");
  const economySource = fs.readFileSync(path.join(__dirname, "..", "plugins", "economy-framework", "index.js"), "utf8");
  assert(serverSource.includes('allowedTypes: ["zip"]'));
  assert(serverSource.includes('allowedTypes: ["png", "svg"]'));
  assert(serverSource.includes('safeDownloadFilename(attachment.original_name'));
  assert(serverSource.includes('"X-Content-Type-Options", "nosniff"'));
  assert(moderationSource.includes("validateUploadedFiles(req.files"));
  assert(moderationSource.indexOf('router.post("/actions", (req, res, next)') < moderationSource.indexOf("evidenceUpload, async"));
  assert(economySource.includes("currencyIconUpload"));
  assert(economySource.indexOf('router.post("/settings/icon", (req, res, next)') < economySource.indexOf("currencyIconUpload, (req, res)"));

  cleanupUploadedFiles([png, safeSvg]);
  console.log("Upload security verification passed.");
} finally {
  fs.rmSync(sandbox, { recursive: true, force: true });
}
