const test = require("node:test");
const assert = require("node:assert/strict");
const fs = require("fs");
const os = require("os");
const path = require("path");
const request = require("supertest");

const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "dws-test-"));
process.env.DATABASE_PATH = path.join(testRoot, "site.sqlite");
process.env.UPLOAD_DIR = path.join(testRoot, "uploads");
process.env.BACKUP_DIR = path.join(testRoot, "backups");
process.env.SESSION_SECRET = "test-session-secret-with-more-than-thirty-two-characters";
process.env.SETUP_TOKEN = "test-setup-token-with-enough-length";

const { app } = require("../src/server");

function csrfFrom(html) {
  return /name="_csrf" value="([^"]+)"/.exec(html)?.[1] || "";
}

test("public pages load", async () => {
  for (const path of ["/", "/items", "/services", "/about-contact", "/healthz"]) {
    const response = await request(app).get(path);
    assert.equal(response.status < 500, true, `${path} returned ${response.status}`);
  }
});

test("admin redirects to setup or login", async () => {
  const response = await request(app).get("/admin");
  assert.equal([302, 303].includes(response.status), true);
});

test("owner setup requires the private setup token", async () => {
  const agent = request.agent(app);

  const locked = await agent.get("/admin/setup");
  assert.equal(locked.status, 403);

  const setupPage = await agent.get("/admin/setup?token=test-setup-token-with-enough-length");
  assert.equal(setupPage.status, 200);
  const token = csrfFrom(setupPage.text);

  const takeover = await agent
    .post("/admin/setup")
    .type("form")
    .send({
      _csrf: token,
      name: "Attacker",
      email: "attacker@example.com",
      password: "attacker-password"
    });
  assert.equal(takeover.status, 403);

  const created = await agent
    .post("/admin/setup")
    .type("form")
    .send({
      _csrf: token,
      setup_token: "test-setup-token-with-enough-length",
      name: "Owner",
      email: "owner@example.com",
      password: "owner-password-123"
    });
  assert.equal(created.status, 302);
  assert.equal(created.headers.location, "/admin/dashboard");

  const dashboard = await agent.get("/admin/dashboard");
  assert.equal(dashboard.status, 200);

  const setupAfterClaim = await agent.get("/admin/setup?token=test-setup-token-with-enough-length");
  assert.equal(setupAfterClaim.status, 302);
  assert.equal(setupAfterClaim.headers.location, "/admin/login");
});

test("multipart admin uploads pass CSRF after form parsing", async () => {
  const agent = request.agent(app);
  const loginPage = await agent.get("/admin/login");
  const loginToken = csrfFrom(loginPage.text);
  const login = await agent
    .post("/admin/login")
    .type("form")
    .send({
      _csrf: loginToken,
      email: "owner@example.com",
      password: "owner-password-123"
    });
  assert.equal(login.status, 302);

  const mediaPage = await agent.get("/admin/media");
  const uploadToken = csrfFrom(mediaPage.text);
  const sampleImage = path.join(__dirname, "..", "public", "uploads", "sample-hero.png");
  const upload = await agent
    .post("/admin/media")
    .field("_csrf", uploadToken)
    .field("title", "Test upload")
    .field("alt", "Test upload")
    .attach("images", sampleImage);
  assert.equal(upload.status, 302);
  assert.equal(upload.headers.location, "/admin/media");
});

test("contact form requires complete fields", async () => {
  const agent = request.agent(app);
  const page = await agent.get("/about-contact");
  const token = csrfFrom(page.text);
  const response = await agent
    .post("/contact")
    .send(`_csrf=${encodeURIComponent(token || "")}&name=&email=bad&subject=&message=`);
  assert.equal(response.status, 400);
});
