import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { mkdtempSync, rmSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { randomUUID } from 'node:crypto';
import { Repository } from '../db/repository.js';
import { addPackageToSpace } from './space-python-packages-service.js';
import { resolvePythonPackagesConfig, parseAndValidateSpec } from '../engine/python-packages.js';

let repo: Repository;
let dir: string;
const cfg = resolvePythonPackagesConfig({ enabled: true, maxPackagesPerSpace: 30 });

beforeEach(() => {
  dir = mkdtempSync(join(tmpdir(), 'pkgsvc-'));
  repo = new Repository(join(dir, `${randomUUID()}.db`));
});
afterEach(() => {
  repo.close();
  rmSync(dir, { recursive: true, force: true });
});

async function seedSpaceWith(spec: string): Promise<string> {
  const owner = repo.createUser({ email: 'o@e.com', name: 'O', role: 'user', status: 'active' });
  const space = await repo.createSpace({ kind: 'case', title: 'T', ownerId: owner.id, visibility: 'private' });
  const p = parseAndValidateSpec(spec);
  repo.setSpacePythonPackages(space.id, JSON.stringify({ packages: [{ name: p.normalizedName, spec: p.spec, addedAt: 'x' }] }));
  return space.id;
}

describe('addPackageToSpace conflict detection (no install path)', () => {
  it('same name + same spec → conflict (idempotent, no install attempted)', async () => {
    const spaceId = await seedSpaceWith('requests==2.32.3');
    // bwrapAvailable:false would fail-close a real install; but conflict is
    // detected BEFORE install, so this stays hermetic.
    const out = await addPackageToSpace({
      repo, cfg, spaceId, ownerId: null,
      parsed: parseAndValidateSpec('requests==2.32.3'), bwrapAvailable: false,
    });
    expect(out).toEqual({ conflict: true });
  });

  it('same name + DIFFERENT spec → versionConflict with the existing spec', async () => {
    const spaceId = await seedSpaceWith('httpx==0.27.0');
    const out = await addPackageToSpace({
      repo, cfg, spaceId, ownerId: null,
      parsed: parseAndValidateSpec('httpx==0.28.0'), bwrapAvailable: false,
    });
    expect(out).toEqual({ versionConflict: 'httpx==0.27.0' });
  });
});
