const express = require('express');
const { spawn } = require('child_process');
const bodyParser = require('body-parser');
const cors = require('cors');
const fs = require('fs');
const path = require('path');

const app = express();
const PORT = 3001; 

// --- DEBUG LOGGING ---
// WICHTIG: Im Docker-Container market-backend ist nur /app/Log gemountet!
const LOG_DIR = '/app/Log';
const LOG_FILE = path.join(LOG_DIR, 'backend_debug.log');
const DUMP_FILE = path.join(LOG_DIR, 'server_dump.txt');

const logToFile = (message) => {
    try {
        if (!fs.existsSync(LOG_DIR)) return; 
        const timestamp = new Date().toISOString();
        const logLine = `[${timestamp}] ${message}\n`;
        fs.appendFileSync(LOG_FILE, logLine);
    } catch (e) {
        console.error("Failed to write to debug log:", e);
    }
};

const dumpToFile = (content) => {
    try {
        if (!fs.existsSync(LOG_DIR)) return;
        const separator = `\n\n--- DUMP ${new Date().toISOString()} ---\n`;
        fs.appendFileSync(DUMP_FILE, separator + content + "\n--- END DUMP ---\n");
    } catch (e) {
        console.error("Failed to dump:", e);
    }
};

// Middleware
app.use(cors()); 
app.use(bodyParser.json({ limit: '50mb' })); 

app.use((req, res, next) => {
    logToFile(`INCOMING REQUEST: ${req.method} ${req.url}`);
    next();
});

// Helper für Python-Aufrufe, um Code-Duplizierung zu vermeiden
const runPython = (args, res, tempFilesToDelete = []) => {
    // Im Docker (python:3.11-slim Image) nutzen wir das globale python3
    const pythonExecutable = 'python3';
    
    logToFile(`Spawning python: ${args.join(' ')}`);
    console.log(`Spawning command: ${pythonExecutable} ${args.join(' ')}`);

    const pythonProcess = spawn(pythonExecutable, args);

    let pythonOutput = '';
    let pythonError = '';

    pythonProcess.stdout.on('data', (data) => {
        pythonOutput += data.toString();
    });

    pythonProcess.stderr.on('data', (data) => {
        pythonError += data.toString();
    });

    pythonProcess.on('close', (code) => {
        logToFile(`Python exited with code ${code}`);
        
        // GLOBAL DUMP
        dumpToFile(`STDOUT:\n${pythonOutput}\n\nSTDERR:\n${pythonError}`);

        if (code !== 0) {
            console.error(`Python script exited with error.`);
            return res.status(500).json({ error: 'Python script failed', details: pythonError });
        }

        try {
            // Versuche JSON zu parsen
            // Suche nach dem ersten '{' und dem letzten '}', falls Müll davor/dahinter ist
            let jsonString = pythonOutput;
            const match = pythonOutput.match(/\{[\s\S]*\}/);
            if (match) {
                jsonString = match[0];
            }

            const result = JSON.parse(jsonString);
            res.json(result);
        } catch (parseError) {
            logToFile(`JSON Parse Error. Full Output dumped to server_dump.txt`);
            console.error('Failed to parse Python output as JSON:', parseError);
            res.status(500).json({ 
                error: 'Invalid JSON from Python script', 
                rawOutputSnippet: pythonOutput.substring(0, 200), 
                details: pythonError 
            });
        }
        
        // Aufräumen
        tempFilesToDelete.forEach(file => {
            if (fs.existsSync(file)) try { fs.unlinkSync(file); } catch(e){}
        });
    });

    pythonProcess.on('error', (err) => {
        logToFile(`FATAL: Failed to start python process: ${err.message}`);
        res.status(500).json({ error: 'Failed to start Python process', details: err.message });
    });
};


// API-Endpunkt für generateSearchStrategy
app.post('/api/generate-search-strategy', async (req, res) => {
    logToFile(`[${new Date().toISOString()}] HIT: /api/generate-search-strategy`);
    const { referenceUrl, contextContent, language } = req.body;

    if (!referenceUrl || !contextContent) {
        return res.status(400).json({ error: 'Missing referenceUrl or contextContent' });
    }

    const tmpDir = path.join(__dirname, 'tmp');
    if (!fs.existsSync(tmpDir)) fs.mkdirSync(tmpDir);
    const tempContextFilePath = path.join(tmpDir, `context_${Date.now()}.md`);

    try {
        fs.writeFileSync(tempContextFilePath, contextContent);
        
        const pythonScript = path.join(__dirname, 'market_intel_orchestrator.py');
        const scriptArgs = [
            pythonScript, 
            '--mode', 'generate_strategy', 
            '--reference_url', referenceUrl, 
            '--context_file', tempContextFilePath,
            '--language', language || 'de'
        ];
        
        runPython(scriptArgs, res, [tempContextFilePath]);

    } catch (writeError) {
        console.error('Failed to write temporary context file:', writeError);
        res.status(500).json({ error: 'Failed to write temporary file', details: writeError.message });
    }
});

// API-Endpunkt für identifyCompetitors
app.post('/api/identify-competitors', async (req, res) => {
    logToFile(`[${new Date().toISOString()}] HIT: /api/identify-competitors`);
    const { referenceUrl, targetMarket, contextContent, referenceCity, referenceCountry, summaryOfOffer, language } = req.body;

    if (!referenceUrl || !targetMarket) {
        return res.status(400).json({ error: 'Missing referenceUrl or targetMarket' });
    }

    const tmpDir = path.join(__dirname, 'tmp');
    if (!fs.existsSync(tmpDir)) fs.mkdirSync(tmpDir);
    const tempContextFilePath = path.join(tmpDir, `context_comp_${Date.now()}.md`);

    try {
        const cleanupFiles = [];
        if (contextContent) {
            fs.writeFileSync(tempContextFilePath, contextContent);
            cleanupFiles.push(tempContextFilePath);
        }

        const pythonScript = path.join(__dirname, 'market_intel_orchestrator.py');
        const scriptArgs = [
            pythonScript,
            '--mode', 'identify_competitors',
            '--reference_url', referenceUrl,
            '--target_market', targetMarket,
            '--language', language || 'de'
        ];

        if (contextContent) scriptArgs.push('--context_file', tempContextFilePath);
        if (referenceCity) scriptArgs.push('--reference_city', referenceCity);
        if (referenceCountry) scriptArgs.push('--reference_country', referenceCountry);
        if (summaryOfOffer) scriptArgs.push('--summary_of_offer', summaryOfOffer);
        
        runPython(scriptArgs, res, cleanupFiles);

    } catch (writeError) {
        res.status(500).json({ error: 'Failed to write temporary file', details: writeError.message });
    }
});

// API-Endpunkt für analyze-company (Deep Tech Audit)
app.post('/api/analyze-company', async (req, res) => {
    logToFile(`[${new Date().toISOString()}] HIT: /api/analyze-company`);
    const { companyName, strategy, targetMarket, language } = req.body;

    if (!companyName || !strategy) {
        return res.status(400).json({ error: 'Missing companyName or strategy' });
    }

    const pythonScript = path.join(__dirname, 'market_intel_orchestrator.py');
    const scriptArgs = [
        pythonScript,
        '--mode', 'analyze_company',
        '--company_name', companyName,
        '--strategy_json', JSON.stringify(strategy),
        '--target_market', targetMarket || 'Germany',
        '--language', language || 'de'
    ];

    runPython(scriptArgs, res);
});

// API-Endpunkt für generate-outreach
app.post('/api/generate-outreach', async (req, res) => {
    logToFile(`[${new Date().toISOString()}] HIT: /api/generate-outreach`);
    
    // Set a long timeout for this specific route (5 minutes)
    req.setTimeout(300000);

    const { companyData, knowledgeBase, referenceUrl, specific_role, language } = req.body;

    if (!companyData || !knowledgeBase) {
        return res.status(400).json({ error: 'Missing companyData or knowledgeBase' });
    }

    const tmpDir = path.join(__dirname, 'tmp');
    if (!fs.existsSync(tmpDir)) fs.mkdirSync(tmpDir);
    const tempDataFilePath = path.join(tmpDir, `outreach_data_${Date.now()}.json`);
    const tempContextFilePath = path.join(tmpDir, `outreach_context_${Date.now()}.md`);

    try {
        fs.writeFileSync(tempDataFilePath, JSON.stringify(companyData));
        fs.writeFileSync(tempContextFilePath, knowledgeBase);

        const pythonScript = path.join(__dirname, 'market_intel_orchestrator.py');
        const scriptArgs = [
            pythonScript,
            '--mode', 'generate_outreach',
            '--company_data_file', tempDataFilePath,
            '--context_file', tempContextFilePath,
            '--reference_url', referenceUrl || '',
            '--language', language || 'de'
        ];

        if (specific_role) {
            scriptArgs.push('--specific_role', specific_role);
        }

        runPython(scriptArgs, res, [tempDataFilePath, tempContextFilePath]);

    } catch (err) {
        res.status(500).json({ error: err.message });
    }
});

// --- DATABASE ROUTES ---

// Initialize DB on startup
const dbScript = path.join(__dirname, 'market_db_manager.py');
spawn('python3', [dbScript, 'init']);

app.get('/api/projects', (req, res) => {
    runPython([dbScript, 'list'], res);
});

app.get('/api/projects/:id', (req, res) => {
    runPython([dbScript, 'load', req.params.id], res);
});

app.delete('/api/projects/:id', (req, res) => {
    runPython([dbScript, 'delete', req.params.id], res);
});

app.post('/api/save-project', (req, res) => {
    const projectData = req.body;
    const tmpDir = path.join(__dirname, 'tmp');
    if (!fs.existsSync(tmpDir)) fs.mkdirSync(tmpDir);
    const tempFilePath = path.join(tmpDir, `save_${Date.now()}.json`);

    try {
        fs.writeFileSync(tempFilePath, JSON.stringify(projectData));
        runPython([dbScript, 'save', tempFilePath], res, [tempFilePath]);
    } catch (e) {
        res.status(500).json({ error: 'Failed to write project data to disk' });
    }
});

const server = app.listen(PORT, () => {
    console.log(`Node.js API Bridge running on http://localhost:${PORT} (Version: 1.1.0-Fix)`);
});

// Set timeout to 10 minutes (600s) to handle long AI generation steps
server.setTimeout(600000);
server.keepAliveTimeout = 610000;
server.headersTimeout = 620000;