/**
 * Integration test: GET /api/v1/documents/[id]/download/[...slug]
 *
 * Verifies the slug truth-check and tenancy isolation on the path-style
 * download route. The storage backend is swapped for a real FilesystemBackend
 * rooted in a tempdir so the byte-streaming path is exercised end-to-end.
 */

import { mkdtemp, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import * as path from 'node:path';

import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';

import { db } from '@/lib/db';
import { documents, files } from '@/lib/db/schema/documents';
import { user } from '@/lib/db/schema/users';
import { createFolder } from '@/lib/services/document-folders.service';
import { makeMockCtx } from '../helpers/route-tester';
import { makeFullPermissions, makePort } from '../helpers/factories';

let testUserId: string;

beforeAll(async () => {
  const [u] = await db.select({ id: user.id }).from(user).limit(1);
  testUserId = u!.id;
});

describe('GET /api/v1/documents/[id]/download/[...slug]', () => {
  let storageRoot: string;
  let backend: import('@/lib/storage/filesystem').FilesystemBackend;

  beforeEach(async () => {
    storageRoot = await mkdtemp(path.join(tmpdir(), 'pn-doc-dl-'));
    const { FilesystemBackend } = await import('@/lib/storage/filesystem');
    backend = await FilesystemBackend.create({
      root: storageRoot,
      proxyHmacSecretEncrypted: null,
    });
    vi.doMock('@/lib/storage', async () => {
      const real = await vi.importActual<typeof import('@/lib/storage')>('@/lib/storage');
      return { ...real, getStorageBackend: vi.fn(async () => backend) };
    });
  });

  afterEach(async () => {
    vi.doUnmock('@/lib/storage');
    await rm(storageRoot, { recursive: true, force: true });
  });

  async function setupDoc(opts: {
    portId: string;
    folderId: string | null;
    filename: string;
    body: Buffer;
    storagePath: string;
  }) {
    await backend.put(opts.storagePath, opts.body, {
      contentType: 'application/pdf',
      sizeBytes: opts.body.length,
    });
    const [fileRow] = await db
      .insert(files)
      .values({
        portId: opts.portId,
        filename: opts.filename,
        originalName: opts.filename,
        mimeType: 'application/pdf',
        sizeBytes: String(opts.body.length),
        storagePath: opts.storagePath,
        uploadedBy: testUserId,
      })
      .returning();
    const [docRow] = await db
      .insert(documents)
      .values({
        portId: opts.portId,
        documentType: 'other',
        title: opts.filename,
        createdBy: testUserId,
        folderId: opts.folderId,
        fileId: fileRow!.id,
      })
      .returning();
    return { fileRow: fileRow!, docRow: docRow! };
  }

  it('streams the file when the slug matches the current folder path + filename', async () => {
    const port = await makePort();
    const folder = await createFolder(port.id, testUserId, { name: 'Deals 2026', parentId: null });
    const sub = await createFolder(port.id, testUserId, { name: 'Q1', parentId: folder.id });
    const body = Buffer.from('hello world');
    const { docRow } = await setupDoc({
      portId: port.id,
      folderId: sub.id,
      filename: 'contract.pdf',
      body,
      storagePath: 'test/contract.pdf',
    });

    const { downloadHandler } =
      await import('@/app/api/v1/documents/[id]/download/[...slug]/handlers');
    const ctx = makeMockCtx({ portId: port.id, permissions: makeFullPermissions() });
    const req = new Request('http://localhost/api/v1/documents/x/download/whatever') as never;
    const res = await downloadHandler(req, ctx, {
      id: docRow.id,
      slug: ['Deals 2026', 'Q1', 'contract.pdf'],
    });
    expect(res.status).toBe(200);
    const buf = Buffer.from(await res.arrayBuffer());
    expect(buf.toString()).toBe('hello world');
    expect(res.headers.get('content-type')).toBe('application/pdf');
  });

  it('404s when the folder-path segments do not match current state', async () => {
    const port = await makePort();
    const folder = await createFolder(port.id, testUserId, { name: 'Real Folder', parentId: null });
    const { docRow } = await setupDoc({
      portId: port.id,
      folderId: folder.id,
      filename: 'spec.pdf',
      body: Buffer.from('x'),
      storagePath: 'test/spec.pdf',
    });

    const { downloadHandler } =
      await import('@/app/api/v1/documents/[id]/download/[...slug]/handlers');
    const ctx = makeMockCtx({ portId: port.id, permissions: makeFullPermissions() });
    const req = new Request('http://localhost/x') as never;
    const res = await downloadHandler(req, ctx, {
      id: docRow.id,
      slug: ['Wrong Folder', 'spec.pdf'],
    });
    expect(res.status).toBe(404);
  });

  it('404s when the filename segment does not match current state', async () => {
    const port = await makePort();
    const folder = await createFolder(port.id, testUserId, { name: 'F', parentId: null });
    const { docRow } = await setupDoc({
      portId: port.id,
      folderId: folder.id,
      filename: 'real.pdf',
      body: Buffer.from('x'),
      storagePath: 'test/real.pdf',
    });

    const { downloadHandler } =
      await import('@/app/api/v1/documents/[id]/download/[...slug]/handlers');
    const ctx = makeMockCtx({ portId: port.id, permissions: makeFullPermissions() });
    const req = new Request('http://localhost/x') as never;
    const res = await downloadHandler(req, ctx, {
      id: docRow.id,
      slug: ['F', 'wrong.pdf'],
    });
    expect(res.status).toBe(404);
  });

  it('404s when the document has no attached file (orphaned doc)', async () => {
    const port = await makePort();
    const [docRow] = await db
      .insert(documents)
      .values({
        portId: port.id,
        documentType: 'other',
        title: 'No file',
        createdBy: testUserId,
        folderId: null,
      })
      .returning();

    const { downloadHandler } =
      await import('@/app/api/v1/documents/[id]/download/[...slug]/handlers');
    const ctx = makeMockCtx({ portId: port.id, permissions: makeFullPermissions() });
    const req = new Request('http://localhost/x') as never;
    const res = await downloadHandler(req, ctx, {
      id: docRow!.id,
      slug: ['anything.pdf'],
    });
    expect(res.status).toBe(404);
  });

  it('404s when the document belongs to another port (tenant isolation)', async () => {
    const portA = await makePort();
    const portB = await makePort();
    const folder = await createFolder(portA.id, testUserId, {
      name: 'Cross',
      parentId: null,
    });
    const { docRow } = await setupDoc({
      portId: portA.id,
      folderId: folder.id,
      filename: 'a.pdf',
      body: Buffer.from('x'),
      storagePath: 'test/a.pdf',
    });

    const { downloadHandler } =
      await import('@/app/api/v1/documents/[id]/download/[...slug]/handlers');
    const ctx = makeMockCtx({ portId: portB.id, permissions: makeFullPermissions() });
    const req = new Request('http://localhost/x') as never;
    const res = await downloadHandler(req, ctx, {
      id: docRow.id,
      slug: ['Cross', 'a.pdf'],
    });
    expect(res.status).toBe(404);
  });
});
