/**
 * Full-stack backup smoke: API seeds submit (Postgres + MinIO), browser downloads ZIP as admin.
 *
 * Prerequisites (same as be0/tests/test_backup_e2e.py):
 *   - docker compose: postgres, minio, be0, fe0 (or host services on expected ports)
 *   - DB migrated through 009; MinIO buckets exist
 *   - DB migration 013 (email verification): Playwright cannot capture verify tokens; either
 *     use API/integration path for full coverage or extend this spec with a token source.
 *
 * be0 must be started with AUTH_ADMIN_EMAILS containing the same address as E2E_ADMIN_EMAIL.
 *
 * Run:
 *   export E2E_BACKUP=1
 *   export E2E_BASE_URL=http://localhost:8081
 *   export E2E_ADMIN_EMAIL=e2e-backup-admin@ump.edu.vn
 *   # In docker-compose be0 environment: AUTH_ADMIN_EMAILS=e2e-backup-admin@ump.edu.vn
 *   cd fe0 && npm install && npx playwright install chromium
 *   npm run test:e2e -- e2e/backup-admin-download.spec.ts
 */

import { test, expect } from "@playwright/test";
import { randomUUID } from "node:crypto";

const PASSWORD = "Testpass1!";
const MIN_PDF = Buffer.concat([
  Buffer.from("%PDF-1.4\n%\xe2\xe3\xcf\xd3\n1 0 obj<<>>endobj\ntrailer<<>>\n%%EOF\n"),
  Buffer.alloc(120, 0x30),
]);

function registerStaffFields(): Record<string, string> {
  const suffix = randomUUID().replace(/-/g, "").slice(0, 8).toUpperCase();
  return {
    employeeId: `CB-${suffix}`,
    academicTitleCode: "master",
    unitNameFreetext: "Khoa kiểm thử",
    jobTitle: "Cán bộ",
  };
}

const stackEnabled = process.env.E2E_BACKUP === "1";
const adminEmail = process.env.E2E_ADMIN_EMAIL?.trim() ?? "";

test.describe("Admin backup ZIP (frontend → API → DB → MinIO)", () => {
  test("admin can download backup after applicant submits PDF", async ({ page, request }) => {
    test.skip(!stackEnabled, "Set E2E_BACKUP=1");
    test.skip(!adminEmail, "Set E2E_ADMIN_EMAIL and list it in be0 AUTH_ADMIN_EMAILS");

    const applicantEmail = `e2e-fe-app-${randomUUID().slice(0, 10)}@ump.edu.vn`;

    const registerJson = (body: object) =>
      request.post("/api/v1/auth/register", {
        headers: { "Content-Type": "application/json" },
        data: JSON.stringify(body),
      });

    const loginJson = (email: string) =>
      request.post("/api/v1/auth/login", {
        headers: { "Content-Type": "application/json" },
        data: JSON.stringify({ email, password: PASSWORD }),
      });

    let r = await registerJson({
      fullName: "E2E Applicant",
      email: applicantEmail,
      password: PASSWORD,
      passwordConfirm: PASSWORD,
      ...registerStaffFields(),
    });
    expect(r.ok(), await r.text()).toBeTruthy();

    r = await loginJson(applicantEmail);
    expect(r.ok(), await r.text()).toBeTruthy();
    const applicantToken = (await r.json()) as { accessToken: string };
    expect(applicantToken.accessToken).toBeTruthy();

    r = await request.post("/api/applications/new", {
      headers: {
        Authorization: `Bearer ${applicantToken.accessToken}`,
        "Content-Type": "application/json",
      },
      data: JSON.stringify({ name: "E2E FE backup" }),
    });
    expect(r.ok(), await r.text()).toBeTruthy();
    const created = (await r.json()) as { id?: string; application?: { draft_case_id?: string; id?: string } };
    const caseId = String(created.application?.draft_case_id ?? "").trim();
    let applicationId = String(created.id ?? created.application?.id ?? "").trim();
    expect(caseId, JSON.stringify(created)).toBeTruthy();
    expect(applicationId).toBeTruthy();

    const meta = {
      initiativeCaseId: caseId,
      initiativeName: "E2E FE Backup",
      authorName: "Applicant",
      authorEmail: applicantEmail,
      subjectId: "s1",
      groupId: "g1",
      topicType: "Hồ sơ PDF",
    };
    r = await request.post("/api/applications/submit", {
      headers: { Authorization: `Bearer ${applicantToken.accessToken}` },
      multipart: {
        file: {
          name: "e2e.pdf",
          mimeType: "application/pdf",
          buffer: MIN_PDF,
        },
        metadata: JSON.stringify(meta),
      },
    });
    expect(r.ok(), await r.text()).toBeTruthy();
    const submitted = (await r.json()) as { id?: string };
    applicationId = String(submitted.id ?? applicationId);

    r = await registerJson({
      fullName: "E2E Admin",
      email: adminEmail,
      password: PASSWORD,
      passwordConfirm: PASSWORD,
      ...registerStaffFields(),
    });
    if (r.ok()) {
      const regBody = (await r.json()) as { user?: { roles?: string[] } };
      expect(regBody.user?.roles).toContain("admin");
    } else {
      expect([400, 409, 422]).toContain(r.status());
    }

    r = await loginJson(adminEmail);
    expect(r.ok(), await r.text()).toBeTruthy();

    await page.goto("/login");
    await page.locator("#login-email").fill(adminEmail);
    await page.locator("#login-password").fill(PASSWORD);
    await page.getByRole("button", { name: "Đăng nhập" }).click();
    await page.waitForURL(/\/dashboard/u, { timeout: 30_000 });

    await page.goto(`/dashboard/admin/applications/review?applicationId=${encodeURIComponent(applicationId)}`);
    await expect(page.getByRole("heading", { name: /Xem hồ sơ đã nộp \(quản trị\)/u })).toBeVisible({
      timeout: 30_000,
    });

    const backupBtn = page.getByRole("button", { name: /Tải bản sao lưu/u });
    await expect(backupBtn).toBeVisible();

    const [download] = await Promise.all([page.waitForEvent("download"), backupBtn.click()]);
    expect(download.suggestedFilename()).toMatch(/\.zip$/i);
    const path = await download.path();
    expect(path).toBeTruthy();
    const fs = await import("node:fs/promises");
    const buf = await fs.readFile(path!);
    expect(buf.length).toBeGreaterThan(100);
    expect(buf[0]).toBe(0x50);
    expect(buf[1]).toBe(0x4b);
  });
});
