/**
 * Release smoke — metadata-only compliance checks
 *
 * Verifies the extension never persists PDF content to chrome.storage.
 * Run as part of `npm test` and `npm run smoke`.
 */

import * as fs from 'fs';
import * as path from 'path';

const SRC = path.join(__dirname, '..', 'src');

const PDF_CONTENT_FIELD_PATTERN =
  /\b(pdfContent|pdfBytes|contentBase64|base64Content|pdfData)\b/;

function readSourceFiles(dir: string): string[] {
  const files: string[] = [];
  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
    const full = path.join(dir, entry.name);
    if (entry.isDirectory()) {
      files.push(...readSourceFiles(full));
    } else if (entry.name.endsWith('.ts')) {
      files.push(full);
    }
  }
  return files;
}

describe('metadata-only storage compliance', () => {
  test('DocumentProxy queue does not define PDF content fields', () => {
    const queueSource = fs.readFileSync(
      path.join(SRC, 'utils', 'pdf-queue.ts'),
      'utf-8'
    );
    expect(queueSource).not.toMatch(PDF_CONTENT_FIELD_PATTERN);
    expect(queueSource).toContain('contentHash');
    expect(queueSource).not.toContain('pdfContent');
  });

  test('DetectedPDF interface is metadata-only', () => {
    const detectorSource = fs.readFileSync(
      path.join(SRC, 'utils', 'pdf-detector.ts'),
      'utf-8'
    );
    const interfaceMatch = detectorSource.match(
      /export interface DetectedPDF \{([^}]+)\}/
    );
    expect(interfaceMatch).not.toBeNull();
    const fields = interfaceMatch![1];
    expect(fields).toMatch(/filename/);
    expect(fields).toMatch(/url/);
    expect(fields).toMatch(/size/);
    expect(fields).not.toMatch(PDF_CONTENT_FIELD_PATTERN);
  });

  test('no source file persists PDF bytes via chrome.storage', () => {
    const offenders: string[] = [];
    for (const file of readSourceFiles(SRC)) {
      const content = fs.readFileSync(file, 'utf-8');
      if (!content.includes('chrome.storage')) {
        continue;
      }
      const lines = content.split('\n');
      for (let i = 0; i < lines.length; i++) {
        const line = lines[i];
        if (
          line.includes('chrome.storage') &&
          line.includes('.set') &&
          PDF_CONTENT_FIELD_PATTERN.test(line)
        ) {
          offenders.push(`${path.relative(SRC, file)}:${i + 1}`);
        }
      }
    }
    expect(offenders).toEqual([]);
  });

  test('upload path fetches bytes in-memory and delegates to Binect API', () => {
    const popupSource = fs.readFileSync(
      path.join(SRC, 'popup', 'popup.ts'),
      'utf-8'
    );
    expect(popupSource).toMatch(/fetchPDFBytes/);
    expect(popupSource).toMatch(/uploadPDF/);
    expect(popupSource).toMatch(/computeContentFingerprint/);
  });

  test('manifest declares required MV3 permissions', () => {
    const manifest = JSON.parse(
      fs.readFileSync(
        path.join(__dirname, '..', 'public', 'manifest.json'),
        'utf-8'
      )
    );
    expect(manifest.manifest_version).toBe(3);
    for (const perm of ['downloads', 'storage', 'alarms', 'activeTab']) {
      expect(manifest.permissions).toContain(perm);
    }
    expect(manifest.host_permissions).toEqual(
      expect.arrayContaining(['https://api.binect.de/*'])
    );
  });
});