const http = require('http');

function dockerRequest(method, path, body = null) {
    return new Promise((resolve, reject) => {
        const opts = {
            socketPath: '/var/run/docker.sock',
            method,
            path,
            headers: { 'Content-Type': 'application/json' }
        };
        const req = http.request(opts, res => {
            let data = '';
            res.on('data', c => data += c);
            res.on('end', () => {
                try { resolve({ status: res.statusCode, data: data ? JSON.parse(data) : null }); }
                catch { resolve({ status: res.statusCode, data }); }
            });
        });
        req.on('error', reject);
        if (body) req.write(JSON.stringify(body));
        req.end();
    });
}

const getContainers = async (req, res) => {
    try {
        const { data } = await dockerRequest('GET', '/containers/json?all=1');
        const containers = (data || []).map(c => ({
            id: c.Id.substring(0, 12),
            name: (c.Names[0] || '').replace(/^\//, ''),
            image: c.Image,
            status: c.Status,
            state: c.State,
            created: c.Created,
            ports: c.Ports || [],
        }));
        res.json(containers);
    } catch (e) {
        res.status(503).json({ error: 'Docker nicht erreichbar', detail: e.message });
    }
};

const getStats = async (req, res) => {
    try {
        const { data: list } = await dockerRequest('GET', '/containers/json?all=0');
        const running = (list || []).filter(c => c.State === 'running');
        const stats = await Promise.all(running.map(async c => {
            try {
                const { data } = await dockerRequest('GET', `/containers/${c.Id}/stats?stream=0`);
                const cpuDelta = (data.cpu_stats?.cpu_usage?.total_usage || 0) - (data.precpu_stats?.cpu_usage?.total_usage || 0);
                const sysDelta = (data.cpu_stats?.system_cpu_usage || 0) - (data.precpu_stats?.system_cpu_usage || 0);
                const cpus = data.cpu_stats?.online_cpus || 1;
                const cpuPct = sysDelta > 0 ? (cpuDelta / sysDelta) * cpus * 100 : 0;
                const memUsed = data.memory_stats?.usage || 0;
                const memLimit = data.memory_stats?.limit || 1;
                return {
                    id: c.Id.substring(0, 12),
                    name: (c.Names[0] || '').replace(/^\//, ''),
                    cpuPct: Math.round(cpuPct * 10) / 10,
                    memUsed,
                    memLimit,
                    memPct: Math.round((memUsed / memLimit) * 1000) / 10,
                };
            } catch { return null; }
        }));
        res.json(stats.filter(Boolean));
    } catch (e) {
        res.status(503).json({ error: 'Docker nicht erreichbar', detail: e.message });
    }
};

const getLogs = async (req, res) => {
    try {
        const lines = parseInt(req.query.lines) || 100;
        const opts = {
            socketPath: '/var/run/docker.sock',
            method: 'GET',
            path: `/containers/${req.params.id}/logs?stdout=1&stderr=1&tail=${lines}&timestamps=1`,
        };
        const raw = await new Promise((resolve, reject) => {
            const req2 = http.request(opts, r => {
                const chunks = [];
                r.on('data', c => chunks.push(c));
                r.on('end', () => resolve(Buffer.concat(chunks)));
            });
            req2.on('error', reject);
            req2.end();
        });
        // Strip Docker log stream headers (8-byte prefix per line)
        let out = '';
        let i = 0;
        while (i < raw.length) {
            if (i + 8 > raw.length) break;
            const size = raw.readUInt32BE(i + 4);
            if (i + 8 + size > raw.length) break;
            out += raw.slice(i + 8, i + 8 + size).toString('utf8');
            i += 8 + size;
        }
        res.json({ logs: out || raw.toString('utf8') });
    } catch (e) {
        res.status(500).json({ error: e.message });
    }
};

const containerAction = async (req, res) => {
    const { id } = req.params;
    const { action } = req.params;
    const map = { start: 'POST', stop: 'POST', restart: 'POST' };
    if (!map[action]) return res.status(400).json({ error: 'Unbekannte Aktion' });
    try {
        const { status } = await dockerRequest('POST', `/containers/${id}/${action}`);
        if (status === 204 || status === 200 || status === 304) {
            res.json({ ok: true });
        } else {
            res.status(status).json({ error: `Docker returned ${status}` });
        }
    } catch (e) {
        res.status(500).json({ error: e.message });
    }
};

module.exports = { getContainers, getStats, getLogs, containerAction };
