"use strict";
// src/test_codebase_graph.ts
// v1.14.0 — Symbol + dependency extraction round-trip.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const DependencyExtractor_1 = require("./orchestrator/graph/DependencyExtractor");
const SymbolExtractor_1 = require("./orchestrator/graph/SymbolExtractor");
const GraphStore_1 = require("./orchestrator/graph/GraphStore");
function assert(cond, msg) {
    if (!cond)
        throw new Error(`assertion failed: ${msg}`);
}
const TS_SAMPLE = `
import { foo } from './foo';
import * as path from 'path';

export function alpha(x: number): number { return x * 2; }

export class Beta {
  do(n: number) { return n + 1; }
}

export const GAMMA = 42;
export interface Delta { id: string }
export type Eps = 'a' | 'b';

function privateFn(): void {}
`;
const PY_SAMPLE = `
import os
from typing import List

def public_fn(x: int) -> int:
    return x + 1

def _private_fn():
    pass

class PyClass:
    def method_a(self):
        pass
    def _internal(self):
        pass
`;
function main() {
    const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'graph-test-'));
    try {
        const tsFile = path.join(tmp, 'sample.ts');
        fs.writeFileSync(tsFile, TS_SAMPLE);
        const syms = (0, SymbolExtractor_1.extractSymbols)(tsFile, TS_SAMPLE);
        const names = syms.map(s => s.name);
        assert(names.includes('alpha'), 'should extract alpha function');
        assert(names.includes('Beta'), 'should extract Beta class');
        assert(names.includes('GAMMA'), 'should extract GAMMA const');
        assert(names.includes('Delta'), 'should extract Delta interface');
        assert(names.includes('Eps'), 'should extract Eps type');
        assert(names.includes('privateFn'), 'should extract privateFn (non-exported)');
        assert(names.some(n => n === 'Beta.do'), 'should extract Beta.do method');
        console.log(`✓ scenario 1: TS symbols (${syms.length}) include all expected names`);
        const exported = syms.filter(s => s.exported).map(s => s.name);
        assert(exported.includes('alpha') && exported.includes('Beta') && exported.includes('GAMMA'), 'export flags set');
        assert(!exported.includes('privateFn'), 'privateFn not flagged as exported');
        console.log(`✓ scenario 2: export flags propagate correctly`);
        // Write a sibling 'foo.ts' so the relative import resolves.
        fs.writeFileSync(path.join(tmp, 'foo.ts'), 'export const foo = 1;\n');
        const deps = (0, DependencyExtractor_1.extractDependencies)(tsFile, TS_SAMPLE);
        const importedModules = deps.map(d => d.toModule);
        assert(importedModules.includes('./foo'), 'should record ./foo import');
        assert(importedModules.includes('path'), 'should record bare path import');
        const fooDep = deps.find(d => d.toModule === './foo');
        assert(fooDep && fooDep.resolvedFile && fooDep.resolvedFile.endsWith('foo.ts'), 'should resolve ./foo to foo.ts');
        const pathDep = deps.find(d => d.toModule === 'path');
        assert(pathDep && !pathDep.resolvedFile, 'bare specifier should stay unresolved');
        console.log(`✓ scenario 3: TS deps (${deps.length}) resolve relative imports, leave bare bare`);
        // Python
        const pyFile = path.join(tmp, 'sample.py');
        fs.writeFileSync(pyFile, PY_SAMPLE);
        const pySyms = (0, SymbolExtractor_1.extractSymbols)(pyFile, PY_SAMPLE);
        const pyNames = pySyms.map(s => s.name);
        assert(pyNames.includes('public_fn'), 'should extract public_fn');
        assert(pyNames.includes('PyClass'), 'should extract PyClass');
        assert(pyNames.includes('PyClass.method_a'), 'should extract method_a as PyClass.method_a');
        const publicFn = pySyms.find(s => s.name === 'public_fn');
        const privateFn = pySyms.find(s => s.name === '_private_fn');
        assert(publicFn.exported, 'public_fn is "exported" (no leading underscore)');
        assert(privateFn && !privateFn.exported, '_private_fn is not exported');
        console.log(`✓ scenario 4: Python symbols (${pySyms.length}) with underscore-based export heuristic`);
        // GraphStore round-trip
        const dbPath = path.join(tmp, 'graph.db');
        const store = new GraphStore_1.GraphStore({ dbPath });
        store.putSymbols(syms);
        store.putEdges(deps);
        const sizeBefore = store.size();
        assert(sizeBefore.symbols === syms.length, `expected ${syms.length} symbols, got ${sizeBefore.symbols}`);
        assert(sizeBefore.edges === deps.length, `expected ${deps.length} edges, got ${sizeBefore.edges}`);
        const found = store.findSymbol('alpha');
        assert(found.length === 1 && found[0].file === tsFile, 'findSymbol returns the right hit');
        const fooImporters = store.findCallers('foo');
        // foo is defined in foo.ts; the only file that imports ./foo is sample.ts; so its symbols should appear.
        // But we didn't index foo.ts itself — so findCallers returns []. Acceptable.
        assert(Array.isArray(fooImporters), 'findCallers returns an array');
        const deps2 = store.findDependencies(tsFile);
        assert(deps2.length === deps.length, 'findDependencies returns all edges for the file');
        store.clearFile(tsFile);
        const sizeAfter = store.size();
        assert(sizeAfter.symbols === 0 && sizeAfter.edges === 0, 'clearFile removes everything for that file');
        store.close();
        console.log(`✓ scenario 5: GraphStore put/find/clear round-trip`);
        console.log('TEST_CODEBASE_GRAPH_OK');
    }
    finally {
        try {
            fs.rmSync(tmp, { recursive: true, force: true });
        }
        catch { /* ignore */ }
    }
}
try {
    main();
}
catch (err) {
    console.error(`TEST_CODEBASE_GRAPH_FAIL: ${err instanceof Error ? err.message : String(err)}`);
    process.exit(1);
}
