const http = require('http');
const fs = require('fs');
const path = require('path');

const PORT = 8090;
const printJobs = new Map();

const MIME_TYPES = {
    '.html': 'text/html; charset=utf-8',
    '.css': 'text/css; charset=utf-8',
    '.js': 'text/javascript; charset=utf-8',
    '.png': 'image/png',
    '.jpg': 'image/jpeg',
    '.gif': 'image/gif',
    '.svg': 'image/svg+xml',
    '.ico': 'image/x-icon',
    '.json': 'application/json; charset=utf-8',
    '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    '.webp': 'image/webp',
};

const server = http.createServer((req, res) => {
    // Log request
    console.log(`[${new Date().toLocaleTimeString()}] ${req.method} ${req.url}`);

    // Strip query parameters
    const urlPath = req.url.split('?')[0];

    // API endpoints for automatic backups to disk
    if (req.method === 'POST' && urlPath === '/api/save-backup') {
        let body = '';
        req.on('data', chunk => {
            body += chunk;
        });
        req.on('end', () => {
            try {
                fs.writeFileSync(path.join(__dirname, 'manuscript_backup.json'), body, 'utf8');
                res.statusCode = 200;
                res.setHeader('Content-Type', 'application/json; charset=utf-8');
                res.end(JSON.stringify({ status: 'ok' }));
            } catch (err) {
                console.error("Erro ao salvar backup em disco:", err);
                res.statusCode = 500;
                res.setHeader('Content-Type', 'application/json; charset=utf-8');
                res.end(JSON.stringify({ error: err.message }));
            }
        });
        return;
    }
    if (req.method === 'POST' && urlPath === '/api/save-cover-backup') {
        let body = '';
        req.on('data', chunk => {
            body += chunk;
        });
        req.on('end', () => {
            try {
                fs.writeFileSync(path.join(__dirname, 'cover_backup.json'), body, 'utf8');
                res.statusCode = 200;
                res.setHeader('Content-Type', 'application/json; charset=utf-8');
                res.end(JSON.stringify({ status: 'ok' }));
            } catch (err) {
                console.error("Erro ao salvar backup da capa em disco:", err);
                res.statusCode = 500;
                res.setHeader('Content-Type', 'application/json; charset=utf-8');
                res.end(JSON.stringify({ error: err.message }));
            }
        });
        return;
    }
    if (req.method === 'POST' && urlPath === '/api/save-print-job') {
        let body = '';
        req.on('data', chunk => {
            body += chunk;
        });
        req.on('end', () => {
            try {
                const data = JSON.parse(body);
                const jobId = Date.now();
                printJobs.set(jobId, data);
                res.statusCode = 200;
                res.setHeader('Content-Type', 'application/json; charset=utf-8');
                res.end(JSON.stringify({ status: 'ok', id: jobId }));
            } catch (err) {
                console.error("Erro ao salvar print job:", err);
                res.statusCode = 500;
                res.setHeader('Content-Type', 'application/json; charset=utf-8');
                res.end(JSON.stringify({ error: err.message }));
            }
        });
        return;
    }

    if (req.method === 'GET' && urlPath === '/api/get-print-job') {
        const queryParams = new URLSearchParams(req.url.split('?')[1] || '');
        const id = queryParams.get('id');
        const job = printJobs.get(Number(id));
        if (job) {
            res.statusCode = 200;
            res.setHeader('Content-Type', 'application/json; charset=utf-8');
            res.end(JSON.stringify(job));
            // Deixa disponível por 2 minutos e depois remove para liberar memória
            setTimeout(() => {
                printJobs.delete(Number(id));
            }, 120000);
        } else {
            res.statusCode = 404;
            res.end('Job de impressao expirado ou nao encontrado.');
        }
        return;
    }
    if (req.method === 'GET' && urlPath === '/api/load-backup') {
        const backupPath = path.join(__dirname, 'manuscript_backup.json');
        if (fs.existsSync(backupPath)) {
            res.statusCode = 200;
            res.setHeader('Content-Type', 'application/json; charset=utf-8');
            const data = fs.readFileSync(backupPath, 'utf8');
            res.end(data);
        } else {
            res.statusCode = 404;
            res.setHeader('Content-Type', 'application/json; charset=utf-8');
            res.end(JSON.stringify({ error: 'Nenhum backup encontrado' }));
        }
        return;
    }
    if (req.method === 'GET' && urlPath === '/api/load-cover-backup') {
        const backupPath = path.join(__dirname, 'cover_backup.json');
        if (fs.existsSync(backupPath)) {
            res.statusCode = 200;
            res.setHeader('Content-Type', 'application/json; charset=utf-8');
            const data = fs.readFileSync(backupPath, 'utf8');
            res.end(data);
        } else {
            res.statusCode = 404;
            res.setHeader('Content-Type', 'application/json; charset=utf-8');
            res.end(JSON.stringify({ error: 'Nenhum backup de capa encontrado' }));
        }
        return;
    }

    // Decode URI to support special characters in file names
    let filePath = path.join(__dirname, decodeURIComponent(urlPath));
    if (urlPath === '/' || urlPath === '') {
        filePath = path.join(__dirname, 'index.html');
    }

    // Security check: ensure filePath is within __dirname
    const relative = path.relative(__dirname, filePath);
    const isSafe = (relative && !relative.startsWith('..') && !path.isAbsolute(relative)) || filePath === path.join(__dirname, 'index.html');
    
    if (!isSafe) {
        res.statusCode = 403;
        res.setHeader('Content-Type', 'text/plain; charset=utf-8');
        res.end('Acesso Negado / Forbidden');
        return;
    }

    fs.stat(filePath, (err, stats) => {
        if (err || !stats.isFile()) {
            res.statusCode = 404;
            res.setHeader('Content-Type', 'text/plain; charset=utf-8');
            res.end('Arquivo não encontrado / File not found');
            return;
        }

        const ext = path.extname(filePath).toLowerCase();
        const contentType = MIME_TYPES[ext] || 'application/octet-stream';

        res.statusCode = 200;
        res.setHeader('Content-Type', contentType);
        
        const stream = fs.createReadStream(filePath);
        stream.on('error', (streamErr) => {
            console.error(streamErr);
            if (!res.headersSent) {
                res.statusCode = 500;
                res.setHeader('Content-Type', 'text/plain; charset=utf-8');
                res.end('Erro interno do servidor / Server error');
            }
        });
        stream.pipe(res);
    });
});

server.on('error', (e) => {
    if (e.code === 'EADDRINUSE') {
        console.log(`[AVISO] A porta ${PORT} já está em uso. Assumindo que o servidor já está rodando.`);
    } else {
        console.error("Erro no servidor HTTP:", e);
    }
});

server.listen(PORT, () => {
    console.log(`Servidor do BookForge Pro Turbo rodando em http://localhost:${PORT}/`);
    console.log(`Pressione Ctrl+C para encerrar o servidor.`);
});
