const { Worker } = require('worker_threads');

function multiplyMatricesSequential(A, B) {
    const n = A.length;
    const C = Array.from({ length: n }, () => Array(n).fill(0));
    
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            for (let k = 0; k < n; k++) {
                C[i][j] += A[i][k] * B[k][j];
            }
        }
    }
    return C;
}

function multiplyMatricesParallel(A, B, numThreads) {
    return new Promise((resolve, reject) => {
        const n = A.length;
        const step = Math.ceil(n / numThreads);
        const workers = [];
        const results = Array.from({ length: numThreads }, () => Array.from({ length: n }, () => Array(n).fill(0)));

        for (let i = 0; i < numThreads; i++) {
            const start = i * step;
            const end = Math.min(start + step, n);
            workers.push(
                new Promise((res, rej) => {
                    const worker = new Worker('./matrix.worker.js', {
                        workerData: { A, B, start, end }
                    });
                    worker.on('message', result => {
                        results[i] = result;
                        res();
                    });
                    worker.on('error', rej);
                    worker.on('exit', code => {
                        if (code !== 0) rej(new Error(`Worker stopped with exit code ${code}`));
                    });
                })
            );
        }

        Promise.all(workers)
            .then(() => {
                const C = Array.from({ length: n }, () => Array(n).fill(0));
                for (let i = 0; i < numThreads; i++) {
                    for (let j = 0; j < n; j++) {
                        for (let k = 0; k < n; k++) {
                            C[j][k] += results[i][j][k];
                        }
                    }
                }
                resolve(C);
            })
            .catch(reject);
    });
}

module.exports = { multiplyMatricesSequential, multiplyMatricesParallel };