import assert from "node:assert/strict";
import { mkdtemp, readFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import test from "node:test";
import { DatabaseClient, normalizeSqlForMysql } from "../lib/database.ts";
import { LocalObjectStore, normalizeObjectKey } from "../lib/object-store.ts";
import { requestUsesHttps } from "../lib/user-auth.ts";

test("normalizes the limited SQLite syntax still used by business queries", () => {
  assert.match(
    normalizeSqlForMysql("INSERT OR IGNORE INTO collection_runs (id) VALUES (?)"),
    /^INSERT IGNORE INTO/,
  );
  const upsert = normalizeSqlForMysql(
    "INSERT INTO accounts (id, nickname) VALUES (?, ?) ON CONFLICT(id) DO UPDATE SET nickname = excluded.nickname",
  );
  assert.match(upsert, /ON DUPLICATE KEY UPDATE/);
  assert.match(upsert, /nickname = VALUES\(nickname\)/);
  assert.equal(
    normalizeSqlForMysql("SELECT datetime(publish_time, '+7 days')"),
    "SELECT DATE_ADD(publish_time, INTERVAL 7 DAY)",
  );
});

test("normalizes ISO timestamps before binding to MySQL DATETIME", async () => {
  let receivedParams;
  const database = new DatabaseClient({
    async execute(_sql, params) {
      receivedParams = params;
      return [{ affectedRows: 1, insertId: 0 }];
    },
  });
  await database
    .prepare("INSERT INTO auth_sessions (expires_at) VALUES (?)")
    .bind("2026-08-11T02:03:04.567Z")
    .run();
  assert.deepEqual(receivedParams, ["2026-08-11 02:03:04.567"]);
});

test("marks login cookies secure behind the Nginx HTTPS proxy", () => {
  assert.equal(
    requestUsesHttps(
      new Request("http://app:3000/api/auth/login", {
        headers: { "x-forwarded-proto": "https" },
      }),
    ),
    true,
  );
  assert.equal(requestUsesHttps(new Request("http://localhost/login")), false);
});

test("stores uploaded objects under a safe persistent directory", async () => {
  const directory = await mkdtemp(path.join(os.tmpdir(), "koc-object-store-"));
  const store = new LocalObjectStore(directory);
  await store.put("creator-center/dist-1/shot.png", Uint8Array.from([1, 2, 3]), {
    httpMetadata: { contentType: "image/png" },
  });
  const object = await store.get("creator-center/dist-1/shot.png");
  assert.ok(object);
  assert.deepEqual([...new Uint8Array(await object.arrayBuffer())], [1, 2, 3]);
  const headers = new Headers();
  object.writeHttpMetadata(headers);
  assert.equal(headers.get("Content-Type"), "image/png");
  assert.equal(
    JSON.parse(
      await readFile(
        path.join(directory, "creator-center/dist-1/shot.png.metadata.json"),
        "utf8",
      ),
    ).contentType,
    "image/png",
  );
  assert.throws(() => normalizeObjectKey("../secret"), /不安全/);
});
