"use strict";
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 });
exports.checkScanState = checkScanState;
exports.checkWatchState = checkWatchState;
exports.checkMcpState = checkMcpState;
exports.detectProject = detectProject;
exports.isDaemonRunning = isDaemonRunning;
exports.runSetup = runSetup;
const fs = __importStar(require("fs"));
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const mcp_config_1 = require("../../../core/mcp-config");
function checkScanState(cwd) {
    const personalDir = path.join(cwd, '.cell', 'personal');
    const agentsMd = path.join(cwd, 'AGENTS.md');
    if (fs.existsSync(personalDir)) {
        let files = [];
        try {
            files = fs.readdirSync(personalDir);
        }
        catch {
            // ignore
        }
        if (files.length > 0) {
            let mtime = '';
            try {
                const stat = fs.statSync(personalDir);
                mtime = stat.mtime.toISOString();
            }
            catch {
                // ignore
            }
            return {
                done: true,
                reason: `.cell/personal/ has ${files.length} files`,
                personalDir,
                scannedAt: mtime,
            };
        }
    }
    if (fs.existsSync(agentsMd)) {
        let mtime = '';
        try {
            mtime = fs.statSync(agentsMd).mtime.toISOString();
        }
        catch {
            // ignore
        }
        return {
            done: true,
            reason: 'AGENTS.md exists (idempotent — kept user file)',
            scannedAt: mtime,
        };
    }
    return { done: false, reason: 'no .cell/personal/ or AGENTS.md found' };
}
function checkWatchState(project) {
    try {
        const Database = require('better-sqlite3');
        const dbPath = path.join(os.homedir(), '.fivo', 'cell', 'cell.db');
        if (!fs.existsSync(dbPath)) {
            return { done: false, reason: 'cell DB not found (run cell start first)' };
        }
        const db = new Database(dbPath);
        const row = db
            .prepare(`SELECT dir_path, active, event_count, last_event_at, started_at
         FROM watcher_state WHERE project = ?`)
            .get(project);
        db.close();
        if (!row) {
            return { done: false, reason: `no watcher registered for "${project}"` };
        }
        if (row.active === 0) {
            return {
                done: false,
                reason: `watcher for "${project}" is inactive (was on ${row.dir_path})`,
                dirPath: row.dir_path,
                eventCount: row.event_count,
            };
        }
        return {
            done: true,
            reason: `watcher LIVE on ${row.dir_path} (${row.event_count} events)`,
            dirPath: row.dir_path,
            eventCount: row.event_count,
            startedAt: row.started_at,
        };
    }
    catch (e) {
        return { done: false, reason: 'daemon DB not reachable: ' + String(e) };
    }
}
function checkMcpState(homedir = os.homedir()) {
    const targets = (0, mcp_config_1.getMcpTargets)(homedir);
    let done = 0;
    let skipped = 0;
    const needsWrite = [];
    for (const t of targets) {
        if (!fs.existsSync(t.configPath)) {
            needsWrite.push(t.name);
            continue;
        }
        try {
            const cfg = (0, mcp_config_1.readConfigFile)(t.configPath, t.format);
            const container = t.containerKey === 'mcp.servers'
                ? cfg.mcp?.servers || {}
                : cfg[t.containerKey] || {};
            if (container[t.cellKey]) {
                done++;
            }
            else {
                needsWrite.push(t.name);
            }
        }
        catch {
            skipped++;
        }
    }
    return { done, skipped, total: targets.length, needsWrite, written: [] };
}
function detectProject(cwd, override) {
    if (override && override.trim().length > 0) {
        return { name: override, source: 'override' };
    }
    const pkgPath = path.join(cwd, 'package.json');
    if (fs.existsSync(pkgPath)) {
        try {
            const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
            if (pkg.name && typeof pkg.name === 'string' && pkg.name.trim().length > 0) {
                return { name: pkg.name, source: 'package.json', packageJsonPath: pkgPath };
            }
        }
        catch {
            // ignore
        }
    }
    const basename = path.basename(cwd);
    if (basename && basename !== '.' && basename !== '/') {
        return { name: basename, source: 'folder-basename' };
    }
    return { name: 'unnamed-project', source: 'no-project' };
}
function isDaemonRunning(port = 9876, timeoutMs = 1000) {
    return new Promise((resolve) => {
        try {
            const http = require('http');
            const req = http.request({
                hostname: '127.0.0.1',
                port,
                path: '/health',
                method: 'GET',
                timeout: timeoutMs,
            }, (res) => {
                resolve(res.statusCode === 200);
            });
            req.on('error', () => resolve(false));
            req.on('timeout', () => {
                req.destroy();
                resolve(false);
            });
            req.end();
        }
        catch {
            resolve(false);
        }
    });
}
async function runSetup(opts = {}) {
    const cwd = opts.cwd || process.cwd();
    const homedir = opts.homedir || os.homedir();
    const project = detectProject(cwd, opts.projectName);
    const errors = [];
    const warnings = [];
    // ─── Scan ──────────────────────────────────────────────────────────────
    let scan = opts.skipScan
        ? { done: true, reason: 'skipped via --skip-scan' }
        : checkScanState(cwd);
    if (!scan.done && !opts.skipScan) {
        if (opts.dryRun) {
            scan = { done: false, reason: '[dry-run] would run cell scan' };
        }
        else {
            try {
                const { scanCodebase } = require('../../02-scanner/blindspots/code-scanner');
                const result = scanCodebase(cwd, project.name);
                const { populateAllLayers } = require('../../05-community/stats/layers');
                populateAllLayers({
                    profile: result.profile,
                    patterns: result.patterns,
                    project: project.name,
                });
                if (!opts.noRules) {
                    const { writeCellRules } = require('../../01-context/context/agents-md');
                    writeCellRules(cwd, { overwrite: opts.forceRules });
                }
                scan = {
                    done: true,
                    reason: `scanned ${result.filesScanned} files, ${result.totalLines.toLocaleString()} lines`,
                };
            }
            catch (e) {
                const msg = e instanceof Error ? e.message : String(e);
                errors.push('scan: ' + msg);
                scan = { done: false, reason: 'scan failed: ' + msg };
            }
        }
    }
    // ─── .cell folder init ────────────────────────────────────────────────
    if (!opts.dryRun) {
        try {
            const cellDir = path.join(cwd, '.cell');
            const dirs = [
                cellDir,
                path.join(cellDir, 'handoff'),
                path.join(cellDir, 'handoff', 'history'),
                path.join(cellDir, 'memory', 'summaries', 'daily'),
                path.join(cellDir, 'memory', 'summaries', 'weekly'),
                path.join(cellDir, 'memory', 'summaries', 'monthly'),
                path.join(cellDir, 'memory', 'patterns'),
                path.join(cellDir, 'memory', 'style'),
                path.join(cellDir, 'memory', 'context'),
                path.join(cellDir, 'memory', 'archive'),
                path.join(cellDir, 'private'),
            ];
            for (const d of dirs) {
                if (!fs.existsSync(d))
                    fs.mkdirSync(d, { recursive: true });
            }
            const { initDefaultStyle } = require('../../06-memory/style/style-memory');
            initDefaultStyle(cwd);
            const { initCellFolders } = require('../../01-context/context/agents-md');
            try {
                initCellFolders(cwd);
            }
            catch { }
            warnings.push('[.cell] memory system initialized');
        }
        catch (e) {
            const msg = e instanceof Error ? e.message : String(e);
            warnings.push('[.cell] init failed: ' + msg);
        }
    }
    // ─── Watch ──────────────────────────────────────────────────────────────
    let watch = opts.skipWatch
        ? { done: true, reason: 'skipped via --skip-watch' }
        : checkWatchState(project.name);
    if (!watch.done && !opts.skipWatch) {
        if (opts.dryRun) {
            watch = { done: false, reason: '[dry-run] would start watcher' };
        }
        else {
            const dir = opts.dir || cwd;
            if (!fs.existsSync(dir)) {
                const msg = `watch dir does not exist: ${dir}`;
                errors.push('watch: ' + msg);
                watch = { done: false, reason: msg };
            }
            else {
                const daemonUp = await isDaemonRunning();
                if (!daemonUp) {
                    warnings.push('watch: daemon not running, will start it');
                }
                // Watch start goes through the daemon (cell_watch_start MCP tool).
                // We call the daemon via HTTP; if it's not up, the user must run cell start.
                // For the setup flow, we attempt and report. The CLI wrapper will show
                // the result and offer next steps.
                try {
                    const ok = await startWatcherViaDaemon(project.name, dir);
                    if (ok.ok) {
                        watch = {
                            done: true,
                            reason: `watcher started on ${dir}`,
                            dirPath: dir,
                        };
                    }
                    else {
                        watch = { done: false, reason: ok.message };
                        if (ok.message.includes('daemon')) {
                            warnings.push('watch: run `cell start` first, then re-run `cell setup`');
                        }
                    }
                }
                catch (e) {
                    const msg = e instanceof Error ? e.message : String(e);
                    errors.push('watch: ' + msg);
                    watch = { done: false, reason: 'watch start failed: ' + msg };
                }
            }
        }
    }
    // ─── MCP ────────────────────────────────────────────────────────────────
    let mcp = opts.skipMcp
        ? { done: 0, skipped: 0, total: 0, needsWrite: [], written: [] }
        : checkMcpState(homedir);
    if (mcp.needsWrite.length > 0 && !opts.skipMcp) {
        if (opts.dryRun) {
            mcp.needsWrite = [`[dry-run] ${mcp.needsWrite.length} IDEs`];
        }
        else {
            try {
                const result = (0, mcp_config_1.writeMcpConfig)(homedir);
                mcp.written = result.written;
                mcp.skipped = result.skipped.length;
                // Re-check state
                mcp = checkMcpState(homedir);
                mcp.written = result.written;
            }
            catch (e) {
                const msg = e instanceof Error ? e.message : String(e);
                errors.push('mcp: ' + msg);
            }
        }
    }
    const success = errors.length === 0;
    return { success, project, scan, watch, mcp, errors, warnings };
}
function startWatcherViaDaemon(project, dir) {
    return new Promise((resolve) => {
        try {
            const http = require('http');
            const body = JSON.stringify({
                method: 'tools/call',
                params: {
                    name: 'cell_watch_start',
                    arguments: { project, dir },
                },
            });
            const req = http.request({
                hostname: '127.0.0.1',
                port: 9876,
                path: '/mcp',
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Content-Length': Buffer.byteLength(body),
                },
                timeout: 3000,
            }, (res) => {
                let data = '';
                res.on('data', (chunk) => {
                    data += chunk ? chunk.toString() : '';
                });
                res.on('end', () => {
                    try {
                        const parsed = JSON.parse(data);
                        const r = parsed?.result || {};
                        if (r.started) {
                            resolve({ ok: true, message: r.message || 'watcher started' });
                        }
                        else {
                            resolve({ ok: false, message: r.message || 'watcher start returned false' });
                        }
                    }
                    catch (e) {
                        resolve({ ok: false, message: 'daemon response parse error' });
                    }
                });
            });
            req.on('error', (e) => {
                resolve({ ok: false, message: 'daemon not reachable: ' + e.message });
            });
            req.on('timeout', () => {
                req.destroy();
                resolve({ ok: false, message: 'daemon timeout' });
            });
            req.write(body);
            req.end();
        }
        catch (e) {
            resolve({ ok: false, message: String(e) });
        }
    });
}
//# sourceMappingURL=setup.js.map