import fs from 'fs';
import path from 'path';
import os from 'os';
import { spawnSync } from 'child_process';
import { request } from 'node:http';
import net from 'node:net';
const DAEMON_SERVICE_NAME = 'pixcode.service';
const FRONTEND_DAEMON_SERVICE_NAME = 'pixcode-frontend.service';
const DAEMON_USER_SERVICE_PATH = path.join(os.homedir(), '.config', 'systemd', 'user', DAEMON_SERVICE_NAME);
const DAEMON_SYSTEM_SERVICE_PATH = path.join('/etc', 'systemd', 'system', DAEMON_SERVICE_NAME);
const FRONTEND_DAEMON_USER_SERVICE_PATH = path.join(os.homedir(), '.config', 'systemd', 'user', FRONTEND_DAEMON_SERVICE_NAME);
const FRONTEND_DAEMON_SYSTEM_SERVICE_PATH = path.join('/etc', 'systemd', 'system', FRONTEND_DAEMON_SERVICE_NAME);
const DEFAULT_FRONTEND_PORT = 5173;
const DAEMON_HEALTH_TIMEOUT_MS = 60000;
const DAEMON_HEALTH_REQUEST_TIMEOUT_MS = 4000;
const DAEMON_HEALTH_RETRY_INTERVAL_MS = 1000;
const DAEMON_SUBCOMMANDS = new Set([
    'install',
    'start',
    'stop',
    'restart',
    'status',
    'logs',
    'enable',
    'disable',
    'uninstall',
    'doctor',
    'help',
]);
const DAEMON_MODES = new Set(['auto', 'user', 'system']);
const SYSTEM_MUTATING_DAEMON_SUBCOMMANDS = new Set([
    'install',
    'start',
    'stop',
    'restart',
    'enable',
    'disable',
    'uninstall',
    'logs',
]);
let pixcodeBinaryAvailableCache = null;
function passthroughColor(text) {
    return text;
}
function getColorHelpers(color) {
    if (color) {
        return color;
    }
    return {
        info: passthroughColor,
        ok: passthroughColor,
        warn: passthroughColor,
        error: passthroughColor,
        tip: passthroughColor,
        bright: passthroughColor,
        dim: passthroughColor,
    };
}
function runCommand(bin, args, opts = {}) {
    const stdio = opts.inherit ? 'inherit' : 'pipe';
    return spawnSync(bin, args, {
        encoding: 'utf8',
        stdio,
    });
}
function extractCommandError(result, fallbackMessage) {
    if (!result)
        return fallbackMessage;
    const fromError = result.error?.message?.trim();
    if (fromError)
        return fromError;
    const fromStd = (result.stderr || result.stdout || '').trim();
    if (fromStd)
        return fromStd;
    return fallbackMessage;
}
function isRootUser() {
    return typeof process.getuid === 'function' && process.getuid() === 0;
}
function quoteShellArg(arg) {
    const value = String(arg);
    if (/^[A-Za-z0-9_./:=+-]+$/.test(value)) {
        return value;
    }
    return `'${value.replace(/'/g, `'\\''`)}'`;
}
function quoteSystemdArg(arg) {
    return `"${String(arg).replace(/(["\\$`])/g, '\\$1')}"`;
}
export function resolveDaemonCliEntryPath(context = {}) {
    const appRoot = context.appRoot || process.cwd();
    const explicitCliEntry = context.cliEntry ? path.resolve(context.cliEntry) : null;
    const argvCliEntry = process.argv[1] ? path.resolve(process.argv[1]) : null;
    const distCliEntry = path.join(appRoot, 'dist-server', 'server', 'cli.js');
    const sourceCliEntry = path.join(appRoot, 'server', 'cli.js');
    const normalizeCliCandidate = (candidate) => {
        if (!candidate)
            return null;
        const resolved = path.resolve(candidate);
        if (resolved === sourceCliEntry && fs.existsSync(distCliEntry)) {
            return distCliEntry;
        }
        return resolved;
    };
    const candidatePaths = [
        normalizeCliCandidate(explicitCliEntry),
        normalizeCliCandidate(argvCliEntry),
        distCliEntry,
        sourceCliEntry,
    ].filter(Boolean);
    const existingPath = candidatePaths.find(candidate => fs.existsSync(candidate));
    if (existingPath) {
        return existingPath;
    }
    return normalizeCliCandidate(explicitCliEntry) || normalizeCliCandidate(argvCliEntry) || distCliEntry;
}
function hasPixcodeBinary() {
    if (pixcodeBinaryAvailableCache !== null) {
        return pixcodeBinaryAvailableCache;
    }
    const probe = runCommand('pixcode', ['--version']);
    pixcodeBinaryAvailableCache = probe.status === 0;
    return pixcodeBinaryAvailableCache;
}
function getDaemonCommandPrefix(context = {}, { forceLocal = false } = {}) {
    if (!forceLocal && hasPixcodeBinary()) {
        return 'pixcode';
    }
    const nodeExec = context.nodeExecPath || process.execPath || 'node';
    const cliEntry = resolveDaemonCliEntryPath(context);
    return `${quoteShellArg(nodeExec)} ${quoteShellArg(cliEntry)}`;
}
export function buildDaemonCliCommand({ subcommand, mode = 'system', extraArgs = [] }, context = {}) {
    const normalizedSubcommand = String(subcommand || 'status').trim() || 'status';
    const normalizedMode = String(mode || 'system').trim() || 'system';
    const args = ['daemon', normalizedSubcommand, '--mode', normalizedMode, ...extraArgs.map(value => String(value))];
    const needsSudo = normalizedMode === 'system' &&
        SYSTEM_MUTATING_DAEMON_SUBCOMMANDS.has(normalizedSubcommand) &&
        !isRootUser();
    const prefix = getDaemonCommandPrefix(context, { forceLocal: needsSudo });
    const command = `${prefix} ${args.map(quoteShellArg).join(' ')}`;
    return needsSudo ? `sudo ${command}` : command;
}
function getDaemonServicePath(mode) {
    return mode === 'system' ? DAEMON_SYSTEM_SERVICE_PATH : DAEMON_USER_SERVICE_PATH;
}
function getFrontendServicePath(mode) {
    return mode === 'system' ? FRONTEND_DAEMON_SYSTEM_SERVICE_PATH : FRONTEND_DAEMON_USER_SERVICE_PATH;
}
function getSystemctlArgs(mode, commandArgs) {
    return mode === 'user' ? ['--user', ...commandArgs] : commandArgs;
}
function getJournalctlArgs(mode, commandArgs) {
    return mode === 'user' ? ['--user', ...commandArgs] : commandArgs;
}
function parseDaemonArgs(args) {
    const parsed = {
        subcommand: 'status',
        options: {
            mode: 'system',
        },
    };
    let i = 0;
    if (args[0] && DAEMON_SUBCOMMANDS.has(args[0])) {
        parsed.subcommand = args[0];
        i = 1;
    }
    for (; i < args.length; i++) {
        const arg = args[i];
        if (arg === '--port' || arg === '-p') {
            parsed.options.serverPort = args[++i];
        }
        else if (arg.startsWith('--port=')) {
            parsed.options.serverPort = arg.split('=')[1];
        }
        else if (arg === '--frontend-port') {
            parsed.options.frontendPort = args[++i];
        }
        else if (arg.startsWith('--frontend-port=')) {
            parsed.options.frontendPort = arg.split('=')[1];
        }
        else if (arg === '--no-frontend' || arg === '--single-port') {
            parsed.options.noFrontend = true;
        }
        else if (arg === '--mode' || arg === '-m') {
            parsed.options.mode = (args[++i] || '').toLowerCase();
        }
        else if (arg.startsWith('--mode=')) {
            parsed.options.mode = (arg.split('=')[1] || '').toLowerCase();
        }
        else if (arg === '--database-path') {
            parsed.options.databasePath = args[++i];
        }
        else if (arg.startsWith('--database-path=')) {
            parsed.options.databasePath = arg.split('=')[1];
        }
        else if (arg === '--help' || arg === '-h') {
            parsed.subcommand = 'help';
        }
        else {
            parsed.options.extraArgs = parsed.options.extraArgs || [];
            parsed.options.extraArgs.push(arg);
        }
    }
    return parsed;
}
function buildDaemonExecStart({ appRoot, serverPort, databasePath, nodeExecPath, cliEntry }) {
    const nodeExec = nodeExecPath || process.execPath || 'node';
    const resolvedCliEntry = resolveDaemonCliEntryPath({ appRoot, cliEntry });
    const args = [nodeExec, resolvedCliEntry, 'start', '--port', String(serverPort)];
    if (databasePath) {
        args.push('--database-path', databasePath);
    }
    return args.map(quoteSystemdArg).join(' ');
}
function buildDaemonServiceUnit({ appRoot, serverPort, databasePath, nodeExecPath, cliEntry }) {
    const execStart = buildDaemonExecStart({
        appRoot,
        serverPort,
        databasePath,
        nodeExecPath,
        cliEntry,
    });
    return `[Unit]
Description=Pixcode Server
After=network.target

[Service]
Type=simple
WorkingDirectory=${appRoot}
ExecStart=${execStart}
Environment=HOST=0.0.0.0
Environment=CI=true
Environment=PIXCODE_DAEMON_MANAGED=1
Restart=always
RestartSec=2

[Install]
WantedBy=default.target
`;
}
function resolveFrontendDaemonEntry(appRoot, cliEntry) {
    const cliCandidate = cliEntry
        ? path.resolve(cliEntry)
        : (process.argv[1] ? path.resolve(process.argv[1]) : '');
    const candidates = [];
    if (cliCandidate) {
        candidates.push(path.join(path.dirname(cliCandidate), 'vite-daemon.js'));
    }
    candidates.push(path.join(appRoot, 'dist-server', 'server', 'vite-daemon.js'));
    candidates.push(path.join(appRoot, 'server', 'vite-daemon.js'));
    const resolved = candidates.find(candidate => fs.existsSync(candidate));
    if (!resolved) {
        throw new Error(`Frontend daemon entry was not found. Checked: ${candidates.join(', ')}. ` +
            `Run "npm run build:server" or ensure server/vite-daemon.js exists.`);
    }
    return resolved;
}
function buildFrontendDaemonExecStart({ appRoot, frontendPort, nodeExecPath, cliEntry }) {
    const nodeExec = nodeExecPath || process.execPath || 'node';
    const frontendEntry = resolveFrontendDaemonEntry(appRoot, cliEntry);
    const args = [
        nodeExec,
        frontendEntry,
        '--host',
        '0.0.0.0',
        '--port',
        String(frontendPort),
        '--strictPort',
    ];
    return args.map(quoteSystemdArg).join(' ');
}
function buildFrontendDaemonServiceUnit({ appRoot, frontendPort, nodeExecPath, cliEntry }) {
    const execStart = buildFrontendDaemonExecStart({
        appRoot,
        frontendPort,
        nodeExecPath,
        cliEntry,
    });
    return `[Unit]
Description=Pixcode Frontend (Vite Dev Server)
After=network.target

[Service]
Type=simple
WorkingDirectory=${appRoot}
ExecStart=${execStart}
Environment=HOST=0.0.0.0
Environment=CI=true
Environment=PIXCODE_DAEMON_MANAGED=1
Restart=always
RestartSec=2

[Install]
WantedBy=default.target
`;
}
function normalizeState(value) {
    const text = (value || '').trim();
    if (!text)
        return 'unknown';
    if (/No such file or directory/i.test(text))
        return 'not-found';
    return text;
}
function getServiceState(mode, serviceName) {
    const activeRes = runCommand('systemctl', getSystemctlArgs(mode, ['is-active', serviceName]));
    const enabledRes = runCommand('systemctl', getSystemctlArgs(mode, ['is-enabled', serviceName]));
    return {
        active: normalizeState(activeRes.stdout || activeRes.stderr),
        enabled: normalizeState(enabledRes.stdout || enabledRes.stderr),
    };
}
function readLogs(mode, lines = 100, inherit = false, serviceNames = [DAEMON_SERVICE_NAME]) {
    const unitArgs = serviceNames.flatMap((serviceName) => ['-u', serviceName]);
    const args = [...getJournalctlArgs(mode, unitArgs), '-n', String(lines), '--no-pager'];
    return runCommand('journalctl', args, { inherit });
}
function getPortFromServiceUnit(servicePath) {
    if (!fs.existsSync(servicePath))
        return null;
    try {
        const content = fs.readFileSync(servicePath, 'utf8');
        const quoted = content.match(/"--port"\s+"(\d+)"/);
        if (quoted)
            return Number(quoted[1]);
        const plain = content.match(/--port(?:\s+|=)(\d+)/);
        if (plain)
            return Number(plain[1]);
    }
    catch {
        // Ignore parse errors and use fallback port.
    }
    return null;
}
function findLatestErrorLine(logText) {
    if (!logText)
        return '';
    const lines = logText.split('\n').map(line => line.trim()).filter(Boolean);
    const errorLine = [...lines].reverse().find(line => /(error|failed|exception|denied|cannot|traceback)/i.test(line));
    return errorLine || '';
}
function probeUserBus() {
    const result = runCommand('systemctl', ['--user', 'show-environment']);
    return {
        ok: result.status === 0,
        detail: extractCommandError(result, 'systemd user bus is not reachable'),
    };
}
function probeLinger() {
    const result = runCommand('loginctl', ['show-user', os.userInfo().username, '-p', 'Linger']);
    if (result.status !== 0) {
        return {
            value: 'unknown',
            detail: extractCommandError(result, 'Could not read linger status'),
        };
    }
    const output = (result.stdout || '').trim();
    const value = output.includes('=') ? output.split('=')[1].trim().toLowerCase() : output.toLowerCase();
    return {
        value: value || 'unknown',
        detail: '',
    };
}
function resolveDaemonMode({ requestedMode, subcommand, userBusAvailable }) {
    if (requestedMode !== 'auto') {
        return requestedMode;
    }
    // Auto mode is intentionally system-first to guarantee boot-time startup
    // even without an interactive user session.
    const systemUnitInstalled = fs.existsSync(getDaemonServicePath('system'));
    const userUnitInstalled = fs.existsSync(getDaemonServicePath('user'));
    if (systemUnitInstalled)
        return 'system';
    if (subcommand === 'install')
        return 'system';
    if (userUnitInstalled && userBusAvailable)
        return 'user';
    return 'system';
}
function runSystemctl(mode, commandArgs, opts = {}) {
    const result = runCommand('systemctl', getSystemctlArgs(mode, commandArgs), { inherit: opts.inherit });
    if (result.status !== 0 && !opts.allowFailure) {
        let errorText = extractCommandError(result, `systemctl ${commandArgs.join(' ')} failed`);
        if (mode === 'system' && /(access denied|permission denied|must be root|interactive authentication required|not permitted)/i.test(errorText)) {
            errorText += '\nTry rerunning this daemon operation with elevated privileges (sudo).';
        }
        throw new Error(errorText);
    }
    return result;
}
async function sleep(ms) {
    await new Promise(resolve => setTimeout(resolve, ms));
}
async function isPortReachable(port, timeoutMs = 1000) {
    return await new Promise(resolve => {
        const socket = net.createConnection({ host: '127.0.0.1', port: Number(port) });
        let settled = false;
        const done = (value) => {
            if (settled)
                return;
            settled = true;
            socket.destroy();
            resolve(value);
        };
        socket.setTimeout(timeoutMs);
        socket.once('connect', () => done(true));
        socket.once('timeout', () => done(false));
        socket.once('error', () => done(false));
    });
}
async function requestHealthOnce(port, timeoutMs = DAEMON_HEALTH_REQUEST_TIMEOUT_MS) {
    return await new Promise((resolve, reject) => {
        const req = request({
            host: '127.0.0.1',
            port: Number(port),
            method: 'GET',
            path: '/health',
            timeout: timeoutMs,
        }, (res) => {
            res.resume();
            resolve({ ok: true, statusCode: res.statusCode });
        });
        req.on('timeout', () => req.destroy(new Error(`Health check timed out after ${timeoutMs}ms`)));
        req.on('error', reject);
        req.end();
    });
}
async function waitForHealth(port, timeoutMs = DAEMON_HEALTH_TIMEOUT_MS) {
    const deadline = Date.now() + timeoutMs;
    let lastError = null;
    while (Date.now() < deadline) {
        try {
            return await requestHealthOnce(port);
        }
        catch (error) {
            lastError = error;
            if (await isPortReachable(port, 700)) {
                return { ok: true, statusCode: null, probe: 'tcp' };
            }
            await sleep(DAEMON_HEALTH_RETRY_INTERVAL_MS);
        }
    }
    throw new Error(lastError?.message || `Service did not become healthy on port ${port}`);
}
async function healthCheckOrThrow(mode, serviceName, port, c) {
    const state = getServiceState(mode, serviceName);
    if (state.active !== 'active' && state.active !== 'activating') {
        throw new Error(`Service ${serviceName} is not active (state: ${state.active})`);
    }
    try {
        const health = await waitForHealth(port);
        if (health.probe === 'tcp') {
            console.log(`${c.warn('[WARN]')} HTTP /health probe delayed; TCP port ${port} is already accepting connections.`);
        }
    }
    catch (healthError) {
        const logsResult = readLogs(mode, 50, false, [serviceName]);
        const logText = (logsResult.stdout || logsResult.stderr || '').trim();
        const lastErrorLine = findLatestErrorLine(logText);
        if (logText) {
            console.log(`\n${c.warn('[WARN]')} Last 50 log lines for ${serviceName}:`);
            console.log(logText);
        }
        if (lastErrorLine) {
            throw new Error(`Health check failed for ${serviceName}: ${healthError.message}\nLikely cause: ${lastErrorLine}`);
        }
        throw new Error(`Health check failed for ${serviceName}: ${healthError.message}`);
    }
}
function ensureLinux() {
    if (process.platform !== 'linux') {
        throw new Error('The daemon command is supported on Linux only.');
    }
}
function ensureSystemctl() {
    const probe = runCommand('systemctl', ['--version']);
    if (probe.status !== 0) {
        throw new Error(extractCommandError(probe, 'systemctl is not available in this environment'));
    }
}
function showDaemonHelp(c, context = {}) {
    const usagePrefix = getDaemonCommandPrefix(context);
    const installExample = buildDaemonCliCommand({
        subcommand: 'install',
        mode: 'system',
        extraArgs: ['--port', '3001', '--single-port'],
    }, context);
    const statusExample = buildDaemonCliCommand({ subcommand: 'status', mode: 'system' }, context);
    const doctorExample = buildDaemonCliCommand({ subcommand: 'doctor', mode: 'auto' }, context);
    const logsExample = buildDaemonCliCommand({ subcommand: 'logs', mode: 'system' }, context);
    console.log(`
${c.bright('Pixcode Daemon')} - Persistent Linux service manager

Usage:
  ${usagePrefix} daemon [subcommand] [options]

Subcommands:
  ${c.bright('install')}      Install/update unit, reload daemon, enable and start now
  ${c.bright('start')}        Start the service
  ${c.bright('stop')}         Stop the service (temporary; auto-start remains enabled)
  ${c.bright('restart')}      Restart the service
  ${c.bright('status')}       Show active/enabled state
  ${c.bright('logs')}         Show recent service logs
  ${c.bright('enable')}       Enable auto-start at boot
  ${c.bright('disable')}      Disable auto-start at boot
  ${c.bright('uninstall')}    Stop, disable, and remove the service unit
  ${c.bright('doctor')}       Run diagnostics (bus, linger, units, state, port, logs)
  ${c.bright('help')}         Show this help

Options:
  -p, --port <port>           Set service server port (default: 3001)
  --frontend-port <port>      Start a separate frontend Vite service on this port (legacy/dev)
  --single-port, --no-frontend
                              Serve the built UI from the backend port only (default)
  -m, --mode <mode>           Service mode: user | system | auto (default: system)
  --database-path <path>      Set service database path

Examples:
  $ ${installExample}
  $ ${statusExample}
  $ ${doctorExample}
  $ ${logsExample}
`);
}
export function hasInstalledDaemonUnit() {
    return (fs.existsSync(DAEMON_USER_SERVICE_PATH) ||
        fs.existsSync(DAEMON_SYSTEM_SERVICE_PATH) ||
        fs.existsSync(FRONTEND_DAEMON_USER_SERVICE_PATH) ||
        fs.existsSync(FRONTEND_DAEMON_SYSTEM_SERVICE_PATH));
}
export async function handleDaemonCommand(args, context = {}) {
    const c = getColorHelpers(context.color);
    const parsed = parseDaemonArgs(args);
    const appRoot = context.appRoot || process.cwd();
    const daemonCommandContext = {
        appRoot,
        cliEntry: context.cliEntry,
        nodeExecPath: context.nodeExecPath,
    };
    if (parsed.options.extraArgs?.length) {
        showDaemonHelp(c, daemonCommandContext);
        throw new Error(`Unknown daemon arguments: ${parsed.options.extraArgs.join(' ')}`);
    }
    if (parsed.subcommand === 'help') {
        showDaemonHelp(c, daemonCommandContext);
        return;
    }
    if (!DAEMON_MODES.has(parsed.options.mode)) {
        throw new Error(`Invalid daemon mode "${parsed.options.mode}". Use one of: auto, user, system.`);
    }
    ensureLinux();
    ensureSystemctl();
    const defaultPort = context.defaultPort || process.env.SERVER_PORT || process.env.PORT || '3001';
    const defaultFrontendPort = context.defaultFrontendPort || process.env.VITE_PORT || String(DEFAULT_FRONTEND_PORT);
    const configuredPort = parsed.options.serverPort || defaultPort;
    const configuredFrontendPort = parsed.options.frontendPort || defaultFrontendPort;
    const frontendEnabled = parsed.options.noFrontend !== true &&
        (Boolean(parsed.options.frontendPort) || process.env.PIXCODE_SEPARATE_FRONTEND === '1');
    const databasePath = parsed.options.databasePath || process.env.DATABASE_PATH || '';
    const portNum = Number(configuredPort);
    if (!Number.isInteger(portNum) || portNum < 1 || portNum > 65535) {
        throw new Error(`Invalid port "${configuredPort}". Expected an integer between 1 and 65535.`);
    }
    const frontendPortNum = Number(configuredFrontendPort);
    if (frontendEnabled && (!Number.isInteger(frontendPortNum) || frontendPortNum < 1 || frontendPortNum > 65535)) {
        throw new Error(`Invalid frontend port "${configuredFrontendPort}". Expected an integer between 1 and 65535.`);
    }
    const userBus = probeUserBus();
    const mode = resolveDaemonMode({
        requestedMode: parsed.options.mode,
        subcommand: parsed.subcommand,
        userBusAvailable: userBus.ok,
    });
    const servicePath = getDaemonServicePath(mode);
    const frontendServicePath = getFrontendServicePath(mode);
    const effectivePort = getPortFromServiceUnit(servicePath) || portNum;
    const effectiveFrontendPort = getPortFromServiceUnit(frontendServicePath) || frontendPortNum;
    if (mode === 'user' && !userBus.ok) {
        const installSystemCommand = buildDaemonCliCommand({ subcommand: 'install', mode: 'system' }, daemonCommandContext);
        throw new Error(`Could not connect to your systemd user session.\n${userBus.detail}\n` +
            `Try ${c.bright(installSystemCommand)} or enable user linger: ${c.bright(`sudo loginctl enable-linger ${os.userInfo().username}`)}`);
    }
    if (parsed.subcommand === 'doctor') {
        const linger = probeLinger();
        const userUnitInstalled = fs.existsSync(getDaemonServicePath('user'));
        const userFrontendUnitInstalled = fs.existsSync(getFrontendServicePath('user'));
        const systemUnitInstalled = fs.existsSync(getDaemonServicePath('system'));
        const systemFrontendUnitInstalled = fs.existsSync(getFrontendServicePath('system'));
        const selectedModePort = getPortFromServiceUnit(servicePath) || portNum;
        const selectedModeFrontendPort = frontendEnabled
            ? getPortFromServiceUnit(frontendServicePath) || frontendPortNum
            : undefined;
        const portReachable = await isPortReachable(selectedModePort);
        const frontendPortReachable = selectedModeFrontendPort
            ? await isPortReachable(selectedModeFrontendPort)
            : false;
        const userState = userBus.ok
            ? {
                backend: getServiceState('user', DAEMON_SERVICE_NAME),
                frontend: getServiceState('user', FRONTEND_DAEMON_SERVICE_NAME),
            }
            : {
                backend: { active: 'unavailable', enabled: 'unavailable' },
                frontend: { active: 'unavailable', enabled: 'unavailable' },
            };
        const systemState = {
            backend: getServiceState('system', DAEMON_SERVICE_NAME),
            frontend: getServiceState('system', FRONTEND_DAEMON_SERVICE_NAME),
        };
        const logsResult = readLogs(mode, 50, false, [DAEMON_SERVICE_NAME, FRONTEND_DAEMON_SERVICE_NAME]);
        const logsText = (logsResult.stdout || logsResult.stderr || '').trim();
        const lastErrorLine = findLatestErrorLine(logsText);
        console.log(`\n${c.bright('Pixcode Daemon Doctor')}\n`);
        console.log(`${c.info('[INFO]')} Requested mode: ${c.bright(parsed.options.mode)}`);
        console.log(`${c.info('[INFO]')} Resolved mode:  ${c.bright(mode)}`);
        console.log(`${c.info('[INFO]')} user-bus:       ${userBus.ok ? c.ok('ok') : c.warn('unavailable')}`);
        if (!userBus.ok) {
            console.log(`       ${c.dim(userBus.detail)}`);
        }
        console.log(`${c.info('[INFO]')} linger:         ${c.bright(linger.value)}${linger.detail ? ` ${c.dim(`(${linger.detail})`)}` : ''}`);
        console.log(`${c.info('[INFO]')} user backend:   ${userUnitInstalled ? c.ok('installed') : c.warn('missing')} (${c.dim(getDaemonServicePath('user'))})`);
        console.log(`${c.info('[INFO]')} user frontend:  ${userFrontendUnitInstalled ? c.ok('installed') : c.warn('missing')} (${c.dim(getFrontendServicePath('user'))})`);
        console.log(`${c.info('[INFO]')} system backend: ${systemUnitInstalled ? c.ok('installed') : c.warn('missing')} (${c.dim(getDaemonServicePath('system'))})`);
        console.log(`${c.info('[INFO]')} system frontend:${systemFrontendUnitInstalled ? c.ok('installed') : c.warn('missing')} (${c.dim(getFrontendServicePath('system'))})`);
        console.log(`${c.info('[INFO]')} user state:     backend active=${c.bright(userState.backend.active)} enabled=${c.bright(userState.backend.enabled)} | frontend active=${c.bright(userState.frontend.active)} enabled=${c.bright(userState.frontend.enabled)}`);
        console.log(`${c.info('[INFO]')} system state:   backend active=${c.bright(systemState.backend.active)} enabled=${c.bright(systemState.backend.enabled)} | frontend active=${c.bright(systemState.frontend.active)} enabled=${c.bright(systemState.frontend.enabled)}`);
        console.log(`${c.info('[INFO]')} backend port:   ${c.bright(String(selectedModePort))} (${portReachable ? c.ok('reachable') : c.warn('not reachable')})`);
        console.log(`${c.info('[INFO]')} frontend mode:  ${frontendEnabled ? c.bright('separate Vite service') : c.bright('single backend port')}`);
        if (frontendEnabled) {
            console.log(`${c.info('[INFO]')} frontend port:  ${c.bright(String(selectedModeFrontendPort))} (${frontendPortReachable ? c.ok('reachable') : c.warn('not reachable')})`);
        }
        if (lastErrorLine) {
            console.log(`${c.warn('[WARN]')} Latest error:   ${lastErrorLine}`);
        }
        console.log(`\n${c.bright('Machine Readable')}`);
        console.log(`MODE_REQUESTED=${parsed.options.mode}`);
        console.log(`MODE_RESOLVED=${mode}`);
        console.log(`USER_BUS_OK=${userBus.ok}`);
        console.log(`LINGER=${linger.value}`);
        console.log(`USER_BACKEND_UNIT_INSTALLED=${userUnitInstalled}`);
        console.log(`USER_FRONTEND_UNIT_INSTALLED=${userFrontendUnitInstalled}`);
        console.log(`SYSTEM_BACKEND_UNIT_INSTALLED=${systemUnitInstalled}`);
        console.log(`SYSTEM_FRONTEND_UNIT_INSTALLED=${systemFrontendUnitInstalled}`);
        console.log(`USER_BACKEND_ACTIVE=${userState.backend.active}`);
        console.log(`USER_BACKEND_ENABLED=${userState.backend.enabled}`);
        console.log(`USER_FRONTEND_ACTIVE=${userState.frontend.active}`);
        console.log(`USER_FRONTEND_ENABLED=${userState.frontend.enabled}`);
        console.log(`SYSTEM_BACKEND_ACTIVE=${systemState.backend.active}`);
        console.log(`SYSTEM_BACKEND_ENABLED=${systemState.backend.enabled}`);
        console.log(`SYSTEM_FRONTEND_ACTIVE=${systemState.frontend.active}`);
        console.log(`SYSTEM_FRONTEND_ENABLED=${systemState.frontend.enabled}`);
        console.log(`BACKEND_PORT=${selectedModePort}`);
        console.log(`BACKEND_PORT_REACHABLE=${portReachable}`);
        console.log(`FRONTEND_ENABLED=${frontendEnabled}`);
        console.log(`FRONTEND_PORT=${selectedModeFrontendPort ?? ''}`);
        console.log(`FRONTEND_PORT_REACHABLE=${frontendPortReachable}`);
        console.log(`LAST_ERROR_LINE=${JSON.stringify(lastErrorLine || '')}\n`);
        return;
    }
    const serviceDefs = [{ servicePath }];
    if (frontendEnabled) {
        serviceDefs.push({ servicePath: frontendServicePath });
    }
    switch (parsed.subcommand) {
        case 'install': {
            if (parsed.options.mode === 'auto' && mode === 'system' && !userBus.ok) {
                console.log(`${c.warn('[WARN]')} User mode is unavailable; auto mode is falling back to system mode.`);
            }
            try {
                fs.mkdirSync(path.dirname(servicePath), { recursive: true });
                if (frontendEnabled) {
                    fs.mkdirSync(path.dirname(frontendServicePath), { recursive: true });
                }
                const backendUnitContent = buildDaemonServiceUnit({
                    appRoot,
                    serverPort: portNum,
                    databasePath,
                    nodeExecPath: context.nodeExecPath,
                    cliEntry: context.cliEntry,
                });
                fs.writeFileSync(servicePath, backendUnitContent, 'utf8');
                if (frontendEnabled) {
                    const frontendUnitContent = buildFrontendDaemonServiceUnit({
                        appRoot,
                        frontendPort: frontendPortNum,
                        nodeExecPath: context.nodeExecPath,
                        cliEntry: context.cliEntry,
                    });
                    fs.writeFileSync(frontendServicePath, frontendUnitContent, 'utf8');
                }
            }
            catch (fileError) {
                if (mode === 'system' && (fileError.code === 'EACCES' || fileError.code === 'EPERM')) {
                    const installHint = buildDaemonCliCommand({
                        subcommand: 'install',
                        mode: 'system',
                        extraArgs: frontendEnabled
                            ? ['--port', String(portNum), '--frontend-port', String(frontendPortNum)]
                            : ['--port', String(portNum), '--single-port'],
                    }, daemonCommandContext);
                    throw new Error(`Permission denied writing daemon unit files (${servicePath}, ${frontendServicePath}). ` +
                        `Try: ${installHint}`);
                }
                throw fileError;
            }
            runSystemctl(mode, ['daemon-reload']);
            runSystemctl(mode, ['enable', '--now', DAEMON_SERVICE_NAME]);
            if (frontendEnabled) {
                runSystemctl(mode, ['enable', '--now', FRONTEND_DAEMON_SERVICE_NAME]);
            }
            else {
                runSystemctl(mode, ['stop', FRONTEND_DAEMON_SERVICE_NAME], { allowFailure: true });
                runSystemctl(mode, ['disable', FRONTEND_DAEMON_SERVICE_NAME], { allowFailure: true });
            }
            if (mode === 'user') {
                const lingerResult = runCommand('loginctl', ['enable-linger', os.userInfo().username]);
                if (lingerResult.status !== 0) {
                    console.log(`${c.warn('[WARN]')} Could not enable linger automatically.`);
                    console.log(`       ${c.dim(extractCommandError(lingerResult, 'Unknown linger error'))}`);
                    console.log(`       ${c.tip('[TIP]')} Run with sufficient privileges: ${c.bright(`sudo loginctl enable-linger ${os.userInfo().username}`)}`);
                }
            }
            const installedPort = getPortFromServiceUnit(servicePath) || portNum;
            await healthCheckOrThrow(mode, DAEMON_SERVICE_NAME, installedPort, c);
            const installedFrontendPort = frontendEnabled
                ? getPortFromServiceUnit(frontendServicePath) || frontendPortNum
                : undefined;
            if (frontendEnabled && installedFrontendPort) {
                await healthCheckOrThrow(mode, FRONTEND_DAEMON_SERVICE_NAME, installedFrontendPort, c);
            }
            const backendState = getServiceState(mode, DAEMON_SERVICE_NAME);
            const frontendState = frontendEnabled
                ? getServiceState(mode, FRONTEND_DAEMON_SERVICE_NAME)
                : { active: 'disabled', enabled: 'disabled' };
            console.log(`\n${c.ok('✔')} Daemon installed and started.`);
            console.log(`   Mode:    ${c.bright(mode)}`);
            console.log(`   Backend Unit:   ${c.dim(servicePath)}`);
            console.log(`   Frontend Mode:  ${c.bright(frontendEnabled ? 'separate service' : 'single backend port')}`);
            console.log(`   Backend Active: ${c.bright(backendState.active)}`);
            console.log(`   Backend Enabled:${c.bright(backendState.enabled)}`);
            console.log(`   Backend URL:    ${c.bright(`http://localhost:${installedPort}`)}`);
            if (frontendEnabled) {
                console.log(`   Frontend Unit:  ${c.dim(frontendServicePath)}`);
                console.log(`   Frontend Active:${c.bright(frontendState.active)}`);
                console.log(`   Frontend Enabled:${c.bright(frontendState.enabled)}`);
                console.log(`   Frontend URL:   ${c.bright(`http://localhost:${installedFrontendPort}`)}`);
            }
            console.log('');
            if (mode === 'system') {
                const statusCommand = buildDaemonCliCommand({ subcommand: 'status', mode: 'system' }, daemonCommandContext);
                const stopCommand = buildDaemonCliCommand({ subcommand: 'stop', mode: 'system' }, daemonCommandContext);
                const logsCommand = buildDaemonCliCommand({ subcommand: 'logs', mode: 'system' }, daemonCommandContext);
                console.log(`${c.ok('[OK]')} System daemon is active.`);
                console.log(`${c.info('[INFO]')} Backend health: ${c.bright(`http://localhost:${installedPort}/health`)}`);
                console.log(`${c.info('[INFO]')} UI: ${c.bright(`http://localhost:${installedPort}/`)}`);
                console.log(`${c.info('[INFO]')} Status: ${c.bright(statusCommand)}`);
                console.log(`${c.info('[INFO]')} Stop: ${c.bright(stopCommand)}`);
                console.log(`${c.info('[INFO]')} Logs: ${c.bright(logsCommand)}\n`);
            }
            else {
                const linger = probeLinger();
                const statusCommand = buildDaemonCliCommand({ subcommand: 'status', mode: 'user' }, daemonCommandContext);
                const stopCommand = buildDaemonCliCommand({ subcommand: 'stop', mode: 'user' }, daemonCommandContext);
                const logsCommand = buildDaemonCliCommand({ subcommand: 'logs', mode: 'user' }, daemonCommandContext);
                console.log(`${c.ok('[OK]')} User daemon is active.`);
                console.log(`${c.info('[INFO]')} Backend health: ${c.bright(`http://localhost:${installedPort}/health`)}`);
                console.log(`${c.info('[INFO]')} UI: ${c.bright(`http://localhost:${installedPort}/`)}`);
                console.log(`${c.info('[INFO]')} Status: ${c.bright(statusCommand)}`);
                console.log(`${c.info('[INFO]')} Stop: ${c.bright(stopCommand)}`);
                console.log(`${c.info('[INFO]')} Logs: ${c.bright(logsCommand)}`);
                if (linger.value !== 'yes') {
                    console.log(`${c.tip('[TIP]')} Enable linger for reboot/login persistence: ${c.bright(`sudo loginctl enable-linger ${os.userInfo().username}`)}\n`);
                }
                else {
                    console.log('');
                }
            }
            break;
        }
        case 'start':
            runSystemctl(mode, ['start', DAEMON_SERVICE_NAME]);
            if (frontendEnabled)
                runSystemctl(mode, ['start', FRONTEND_DAEMON_SERVICE_NAME]);
            await healthCheckOrThrow(mode, DAEMON_SERVICE_NAME, effectivePort, c);
            if (frontendEnabled)
                await healthCheckOrThrow(mode, FRONTEND_DAEMON_SERVICE_NAME, effectiveFrontendPort, c);
            console.log(`${c.ok('[OK]')} Pixcode service started.`);
            break;
        case 'stop':
            runSystemctl(mode, ['stop', FRONTEND_DAEMON_SERVICE_NAME], { allowFailure: true });
            runSystemctl(mode, ['stop', DAEMON_SERVICE_NAME]);
            console.log(`${c.ok('[OK]')} Pixcode service stopped (auto-start remains enabled).`);
            break;
        case 'restart':
            runSystemctl(mode, ['restart', DAEMON_SERVICE_NAME]);
            if (frontendEnabled)
                runSystemctl(mode, ['restart', FRONTEND_DAEMON_SERVICE_NAME]);
            await healthCheckOrThrow(mode, DAEMON_SERVICE_NAME, effectivePort, c);
            if (frontendEnabled)
                await healthCheckOrThrow(mode, FRONTEND_DAEMON_SERVICE_NAME, effectiveFrontendPort, c);
            console.log(`${c.ok('[OK]')} Pixcode service restarted.`);
            break;
        case 'enable':
            runSystemctl(mode, ['enable', DAEMON_SERVICE_NAME]);
            if (frontendEnabled)
                runSystemctl(mode, ['enable', FRONTEND_DAEMON_SERVICE_NAME]);
            console.log(`${c.ok('[OK]')} Pixcode service enabled for auto-start.`);
            break;
        case 'disable':
            runSystemctl(mode, ['disable', DAEMON_SERVICE_NAME]);
            runSystemctl(mode, ['disable', FRONTEND_DAEMON_SERVICE_NAME]);
            console.log(`${c.ok('[OK]')} Pixcode service disabled for auto-start.`);
            break;
        case 'logs': {
            const logsResult = readLogs(mode, 100, true, [DAEMON_SERVICE_NAME, FRONTEND_DAEMON_SERVICE_NAME]);
            if (logsResult.status !== 0) {
                throw new Error(extractCommandError(logsResult, 'Unable to read daemon logs'));
            }
            break;
        }
        case 'uninstall': {
            runSystemctl(mode, ['stop', FRONTEND_DAEMON_SERVICE_NAME], { allowFailure: true });
            runSystemctl(mode, ['disable', FRONTEND_DAEMON_SERVICE_NAME], { allowFailure: true });
            runSystemctl(mode, ['stop', DAEMON_SERVICE_NAME], { allowFailure: true });
            runSystemctl(mode, ['disable', DAEMON_SERVICE_NAME], { allowFailure: true });
            for (const def of serviceDefs) {
                if (!fs.existsSync(def.servicePath))
                    continue;
                try {
                    fs.unlinkSync(def.servicePath);
                }
                catch (unlinkError) {
                    if (mode === 'system' && (unlinkError.code === 'EACCES' || unlinkError.code === 'EPERM')) {
                        const uninstallHint = buildDaemonCliCommand({ subcommand: 'uninstall', mode: 'system' }, daemonCommandContext);
                        throw new Error(`Permission denied removing ${def.servicePath}. Try: ${uninstallHint}`);
                    }
                    throw unlinkError;
                }
            }
            runSystemctl(mode, ['daemon-reload'], { allowFailure: true });
            console.log(`${c.ok('[OK]')} Backend and frontend daemons uninstalled.`);
            break;
        }
        case 'status':
        default: {
            const backendState = getServiceState(mode, DAEMON_SERVICE_NAME);
            const frontendState = getServiceState(mode, FRONTEND_DAEMON_SERVICE_NAME);
            const backendUnitExists = fs.existsSync(servicePath);
            const frontendUnitExists = fs.existsSync(frontendServicePath);
            const selectedPort = getPortFromServiceUnit(servicePath) || portNum;
            const selectedFrontendPort = frontendEnabled
                ? getPortFromServiceUnit(frontendServicePath) || frontendPortNum
                : undefined;
            console.log(`\n${c.bright('Pixcode Daemon Status')}\n`);
            console.log(`${c.info('[INFO]')} Mode:      ${c.bright(mode)} ${parsed.options.mode === 'auto' ? c.dim('(resolved from auto)') : ''}`);
            console.log(`${c.info('[INFO]')} Backend Unit:   ${c.dim(servicePath)} ${backendUnitExists ? c.ok('[OK]') : c.warn('[MISSING]')}`);
            console.log(`${c.info('[INFO]')} Backend Active: ${c.bright(backendState.active)}`);
            console.log(`${c.info('[INFO]')} Backend Enabled:${c.bright(backendState.enabled)}`);
            console.log(`${c.info('[INFO]')} Backend Port:   ${c.bright(String(selectedPort))}`);
            console.log(`${c.info('[INFO]')} UI URL:         ${c.bright(`http://localhost:${selectedPort}/`)}`);
            console.log(`${c.info('[INFO]')} Frontend Mode:  ${frontendEnabled ? c.bright('separate Vite service') : c.bright('single backend port')}`);
            if (frontendEnabled) {
                console.log(`${c.info('[INFO]')} Frontend Unit:  ${c.dim(frontendServicePath)} ${frontendUnitExists ? c.ok('[OK]') : c.warn('[MISSING]')}`);
                console.log(`${c.info('[INFO]')} Frontend Active:${c.bright(frontendState.active)}`);
                console.log(`${c.info('[INFO]')} Frontend Enabled:${c.bright(frontendState.enabled)}`);
                console.log(`${c.info('[INFO]')} Frontend Port:  ${c.bright(String(selectedFrontendPort))}`);
            }
            else if (frontendUnitExists) {
                console.log(`${c.info('[INFO]')} Legacy Frontend:${c.dim(frontendServicePath)} active=${c.bright(frontendState.active)} enabled=${c.bright(frontendState.enabled)}`);
            }
            console.log('');
        }
    }
}
//# sourceMappingURL=daemon-manager.js.map