import assert from 'node:assert/strict';
import { EventEmitter } from 'node:events';
import path from 'node:path';
import { PassThrough } from 'node:stream';
import test from 'node:test';
import { startCloneProject } from '../../../modules/projects/services/project-clone.service.js';
import { AppError } from '../../../shared/utils.js';
function buildDependencies(overrides = {}) {
    return {
        validatePath: async () => ({ valid: true, resolvedPath: '/workspace/root' }),
        ensureDirectory: async () => undefined,
        resolveUserWorkspaceRoot: async () => '/workspace/root',
        pathExists: async () => false,
        removePath: async () => undefined,
        getGithubTokenById: async () => ({ github_token: 'token-value' }),
        spawnGitClone: () => {
            throw new Error('spawnGitClone should be overridden in this test');
        },
        registerProject: async () => ({ project: { projectId: 'project-1' } }),
        logError: () => undefined,
        ...overrides,
    };
}
function createMockGitProcess() {
    const emitter = new EventEmitter();
    emitter.stdout = new PassThrough();
    emitter.stderr = new PassThrough();
    emitter.kill = () => {
        emitter.emit('close', null);
    };
    return emitter;
}
test('startCloneProject rejects when workspace path is missing', async () => {
    await assert.rejects(async () => startCloneProject({
        workspacePath: '',
        githubUrl: 'https://github.com/example/repo',
        userId: 1,
        username: 'tester',
    }, {
        onProgress: () => undefined,
        onComplete: () => undefined,
    }, buildDependencies()), (error) => {
        assert.ok(error instanceof AppError);
        assert.equal(error.code, 'WORKSPACE_PATH_REQUIRED');
        return true;
    });
});
test('startCloneProject rejects when github URL is missing', async () => {
    await assert.rejects(async () => startCloneProject({
        workspacePath: '/workspace/root',
        githubUrl: '',
        userId: 1,
        username: 'tester',
    }, {
        onProgress: () => undefined,
        onComplete: () => undefined,
    }, buildDependencies()), (error) => {
        assert.ok(error instanceof AppError);
        assert.equal(error.code, 'GITHUB_URL_REQUIRED');
        return true;
    });
});
test('startCloneProject rejects github URL values that begin with option prefixes', async () => {
    await assert.rejects(async () => startCloneProject({
        workspacePath: '/workspace/root',
        githubUrl: '--upload-pack=malicious',
        userId: 1,
        username: 'tester',
    }, {
        onProgress: () => undefined,
        onComplete: () => undefined,
    }, buildDependencies()), (error) => {
        assert.ok(error instanceof AppError);
        assert.equal(error.code, 'INVALID_GITHUB_URL');
        return true;
    });
});
test('startCloneProject rejects when selected github token does not exist', async () => {
    await assert.rejects(async () => startCloneProject({
        workspacePath: '/workspace/root',
        githubUrl: 'https://github.com/example/repo',
        githubTokenId: 12,
        userId: 1,
        username: 'tester',
    }, {
        onProgress: () => undefined,
        onComplete: () => undefined,
    }, buildDependencies({
        getGithubTokenById: async () => null,
    })), (error) => {
        assert.ok(error instanceof AppError);
        assert.equal(error.code, 'GITHUB_TOKEN_NOT_FOUND');
        return true;
    });
});
test('startCloneProject completes and emits complete payload when git exits successfully', async () => {
    const gitProcess = createMockGitProcess();
    const progressMessages = [];
    let completePayload = null;
    let capturedUserId = 0;
    let capturedProjectPath = '';
    let capturedCustomName = '';
    let capturedUsername = '';
    const operation = await startCloneProject({
        workspacePath: '/workspace/root',
        githubUrl: 'https://github.com/example/repo.git',
        userId: 1,
        username: 'tester',
    }, {
        onProgress: (message) => {
            progressMessages.push(message);
        },
        onComplete: (payload) => {
            completePayload = payload;
        },
    }, buildDependencies({
        spawnGitClone: () => gitProcess,
        registerProject: async (userId, username, projectPath, customName) => {
            capturedUserId = userId;
            capturedUsername = username;
            capturedProjectPath = projectPath;
            capturedCustomName = customName;
            return { project: { projectId: 'project-1', path: projectPath } };
        },
    }));
    gitProcess.emit('close', 0);
    await operation.waitForCompletion;
    assert.ok(progressMessages.some((message) => message.includes("Cloning into 'repo'")));
    assert.equal(capturedUserId, 1);
    assert.equal(capturedUsername, 'tester');
    assert.equal(capturedCustomName, 'repo');
    assert.equal(path.basename(capturedProjectPath), 'repo');
    assert.notEqual(completePayload, null);
    const resolvedCompletePayload = completePayload;
    assert.equal(resolvedCompletePayload.message, 'Repository cloned successfully');
    assert.equal(resolvedCompletePayload.project.projectId || '', 'project-1');
});
//# sourceMappingURL=project-clone.service.test.js.map