import Fastify from "fastify";
import pg from "pg";
import zlib from "node:zlib";

const { Pool } = pg;
const fastify = Fastify({ logger: true });

// IMPORTANT: permettre le raw body (pour gzip)
fastify.addContentTypeParser("*", { parseAs: "buffer" }, (req, body, done) => done(null, body));

const PORT = Number(process.env.PORT || 3000);
const DATABASE_URL = process.env.DATABASE_URL;
const IMPORT_TOKEN = process.env.BM_IMPORT_TOKEN || "";

let pool = null;
if (DATABASE_URL) pool = new Pool({ connectionString: DATABASE_URL });

fastify.get("/", async () => ({ ok: true, service: "bm-api" }));
fastify.get("/health", async () => ({ ok: true }));

fastify.get("/db", async () => {
  if (!pool) return { ok: false, error: "DATABASE_URL not set" };
  const r = await pool.query("select now() as now, current_database() as db");
  return { ok: true, ...r.rows[0] };
});

fastify.get("/stats", async () => {
  if (!pool) return { ok: false, error: "DATABASE_URL not set" };
  const r = await pool.query(`select (select count(*)::int from bands) as bands`);
  return { ok: true, ...r.rows[0], updated_at: new Date().toISOString() };
});

fastify.post("/admin/import", async (req, reply) => {
  const auth = String(req.headers.authorization || "");
  const token = auth.startsWith("Bearer ") ? auth.slice(7) : "";

  if (!IMPORT_TOKEN || token !== IMPORT_TOKEN) {
    return reply.code(401).send({ ok: false, error: "unauthorized" });
  }
  if (!pool) return reply.code(500).send({ ok: false, error: "DATABASE_URL not set" });

  const ct = String(req.headers["content-type"] || "");
  let payload;

  // req.body est Buffer (grâce au parser "*")
  const buf = Buffer.isBuffer(req.body) ? req.body : Buffer.from(req.body || "");

  try {
    if (ct.includes("application/json")) {
      payload = JSON.parse(buf.toString("utf-8"));
    } else if (ct.includes("application/gzip") || ct.includes("application/x-gzip")) {
      payload = JSON.parse(zlib.gunzipSync(buf).toString("utf-8"));
    } else {
      // fallback: tenter JSON direct
      payload = JSON.parse(buf.toString("utf-8"));
    }
  } catch (e) {
    req.log.error(e);
    return reply.code(400).send({ ok: false, error: "invalid body/json" });
  }

  if (!payload || !Array.isArray(payload.bands)) {
    return reply.code(400).send({ ok: false, error: "expected { bands: [...] }" });
  }

  const client = await pool.connect();
  try {
    await client.query("begin");
    let upserted = 0;

    for (const b of payload.bands) {
      if (!b?.ma_id || !b?.name) continue;

      await client.query(
        `
        insert into bands (ma_id, name, country, location_text, status, genre, data)
        values ($1,$2,$3,$4,$5,$6,$7::jsonb)
        on conflict (ma_id) do update set
          name=excluded.name,
          country=excluded.country,
          location_text=excluded.location_text,
          status=excluded.status,
          genre=excluded.genre,
          data=excluded.data
        `,
        [
          b.ma_id,
          b.name,
          b.country || null,
          b.location_text || null,
          b.status || null,
          b.genre || null,
          JSON.stringify(b.data || {}),
        ]
      );

      upserted++;
    }

    await client.query("commit");
    return { ok: true, upserted };
  } catch (e) {
    await client.query("rollback");
    req.log.error(e);
    return reply.code(500).send({ ok: false, error: "import failed" });
  } finally {
    client.release();
  }
});

fastify.listen({ port: PORT, host: "0.0.0.0" });
