require('dotenv').config({ override: true });
const express = require('express');
const { Pool } = require('pg');
const bodyParser = require('body-parser');
const cors = require('cors');
const path = require('node:path');

const app = express();
app.disable('x-powered-by');
const port = process.env.PORT || 3000;

app.use(cors({
  origin: ['http://localhost:3000', 'http://localhost:5173', 'http://127.0.0.1:3000', 'http://127.0.0.1:5173'],
  credentials: true
}));
app.use(bodyParser.json());

// Serve static files from the root directory
app.use(express.static(path.join(__dirname, './')));

const pool = new Pool({
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  database: process.env.DB_NAME,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD
});

// In-memory logs for remote debugging
const serverLogs = [];
function log(msg) {
    const entry = `[${new Date().toISOString()}] ${msg}`;
    console.log(entry);
    serverLogs.push(entry);
    if (serverLogs.length > 50) serverLogs.shift();
}

// Status-Endpunkt für Diagnose
app.get('/api/status', async (req, res) => {
    try {
        const result = await pool.query('SELECT NOW()');
        res.json({ 
            status: 'online', 
            database: 'connected', 
            time: result.rows[0].now,
            schema: process.env.DB_SCHEMA || 'geodaten'
        });
    } catch (err) {
        res.status(500).json({ status: 'error', database: 'disconnected', error: err.message });
    }
});

app.get('/api/logs', (req, res) => {
    res.type('text/plain').send(serverLogs.join('\n'));
});

// API to save turbines
app.post('/api/wea', async (req, res) => {
    const { projekt_id, turbines } = req.body;
    const targetProject = projekt_id || 'BWSamern-Ohne';
    const schema = process.env.DB_SCHEMA || 'geodaten';
    
    log(`Empfange Save-Request für Projekt: ${targetProject} (${turbines?.length || 0} WEAs)`);

    const client = await pool.connect();
    try {
        await client.query('BEGIN');
        
        // 1. Bestehende WEAs für dieses Projekt löschen
        const delRes = await client.query(
            `DELETE FROM ${schema}.wea_standorte WHERE projekt_id = $1`,
            [targetProject]
        );
        log(`Gelöscht: ${delRes.rowCount} bestehende Anlagen.`);

        // 2. Neue WEAs einfügen
        if (turbines && turbines.length > 0) {
            for (const t of turbines) {
                log(`Füge WEA ein: Nr=${t.nr}, Typ=${t.type}, Pos=${t.latlng?.lat},${t.latlng?.lng}`);
                await client.query(
                    `INSERT INTO ${schema}.wea_standorte 
                    (projekt_id, wea_nummer, hersteller, anlagentyp, nabenhoehe, rotordurchmesser, ksf_drehung, variante, geom) 
                    VALUES ($1, $2, $3, $4, $5, $6, $7, $8, ST_Transform(ST_SetSRID(ST_MakePoint($9, $10), 4326), 25832))`,
                    [targetProject, t.nr, t.hersteller, t.type, t.hh, t.rd, t.ksfAngle, t.variant, t.latlng.lng, t.latlng.lat]
                );
            }
        }

        await client.query('COMMIT');
        log(`Erfolgreich gespeichert: ${turbines?.length || 0} WEAs.`);
        res.json({ message: `${turbines?.length || 0} WEAs erfolgreich in Datenbank gespeichert.` });
    } catch (err) {
        await client.query('ROLLBACK');
        log(`FEHLER beim Speichern: ${err.message}`);
        res.status(500).json({ error: 'Datenbankfehler beim Speichern', details: err.message });
    } finally {
        client.release();
    }
});

// API to load turbines
app.get('/api/wea/:projekt_id', async (req, res) => {
    const { projekt_id } = req.params;
    log(`Lade WEAs für Projekt: ${projekt_id}`);
    try {
        const result = await pool.query(
            `SELECT wea_nummer as nr, hersteller as hersteller, anlagentyp as type, nabenhoehe as hh, rotordurchmesser as rd, ksf_drehung as ksfAngle, variante as variant,
                    ST_X(ST_Transform(geom, 4326)) as lng, ST_Y(ST_Transform(geom, 4326)) as lat
             FROM geodaten.wea_standorte WHERE projekt_id = $1`,
            [projekt_id]
        );
        log(`Geladen: ${result.rowCount} Anlagen.`);
        res.status(200).json(result.rows);
    } catch (e) {
        log(`FEHLER beim Laden: ${e.message}`);
        res.status(500).json({ error: e.message });
    }
});

// Hilfsfunktion zur Auflösung von Projekt-ID oder Name
async function resolveProjectId(client, input) {
    if (!input) return null;
    
    // Prüfen, ob input eine valide UUID ist
    const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
    if (uuidRegex.test(input)) return input;

    // Normalisierte Suche (Kleinschreibung, alle Bindestriche und Unterstriche entfernen)
    const normalized = input.toLowerCase().replace(/[-_]/g, '');
    
    const res = await client.query(
        'SELECT id FROM geodaten.projekte WHERE LOWER(REPLACE(REPLACE(name, \'-\', \'\'), \'_\', \'\')) = $1', 
        [normalized]
    );
    return res.rows.length > 0 ? res.rows[0].id : null;
}

// API zur Flächensicherung von Eigentümern
app.post('/api/sicherung', async (req, res) => {
    const { nachname, vorname, status, notiz } = req.body;
    const targetStatus = status || 'Gesichert';
    const schema = process.env.DB_SCHEMA || 'geodaten';
    
    log(`Sicherungs-Request: ${vorname} ${nachname} Status='${targetStatus}' Notiz='${notiz}'`);

    const client = await pool.connect();
    try {
        await client.query('BEGIN');
        
        // Suche nach dem Eigentümer in flaecheneigentuemer_alkis und aktualisiere status und notiz
        const searchNachname = (nachname || '').trim();
        const searchVorname = (vorname || '').trim();

        // Normalisierte Suche (TRIM und COALESCE für ALKIS-Daten)
        const updateRes = await client.query(
            `UPDATE ${schema}.flaecheneigentuemer_alkis 
             SET status = $1, notiz = $2
             WHERE 
                (TRIM(COALESCE("GNA", '')) = TRIM(COALESCE($3, '')) AND TRIM(COALESCE("VNA", '')) = TRIM(COALESCE($4, ''))) OR
                (TRIM(COALESCE("VNA", '')) = TRIM(COALESCE($5, '')) AND TRIM(COALESCE("GNA", '')) = '') OR
                (TRIM(COALESCE("GNA", '')) = TRIM(COALESCE($5, '')) AND TRIM(COALESCE("VNA", '')) = '') OR
                (LOWER(TRIM(COALESCE("GNA", ''))) = LOWER(TRIM(COALESCE($3, ''))) AND LOWER(TRIM(COALESCE("VNA", ''))) = LOWER(TRIM(COALESCE($4, ''))))`,
            [targetStatus, notiz, searchNachname, searchVorname, `${searchVorname} ${searchNachname}`.trim()]
        );

        if (updateRes.rowCount === 0) {
            log(`Kein Eigentümer für ${vorname} ${nachname} gefunden.`);
            await client.query('ROLLBACK');
            return res.status(404).json({ error: `Eigentümer '${vorname} ${nachname}' nicht in der ALKIS-Tabelle gefunden.` });
        }

        await client.query('COMMIT');
        log(`Erfolgreich: ${updateRes.rowCount || 1} Einträge in ALKIS aktualisiert.`);
        res.json({ 
            message: `Eigentümer ${vorname} ${nachname} erfolgreich aktualisiert.`,
            count: updateRes.rowCount
        });
    } catch (err) {
        await client.query('ROLLBACK');
        log(`FEHLER bei Sicherung: ${err.message}`);
        res.status(500).json({ error: 'Fehler bei der Flächensicherung', details: err.message });
    } finally {
        client.release();
    }
});

// API zum Laden der Sicherungsstände
app.get('/api/sicherung/:projekt_id', async (req, res) => {
    const { projekt_id } = req.params;
    log(`Lade Sicherungsstände für Projekt: ${projekt_id}`);
    
    const client = await pool.connect();
    try {
        // Wir laden nun direkt aus der ALKIS Tabelle, wie vom User gewünscht
        const result = await client.query(
            `SELECT "VNA" as vorname, "GNA" as nachname, status, notiz 
             FROM geodaten.flaecheneigentuemer_alkis 
             WHERE status IS NOT NULL OR notiz IS NOT NULL`
        );
        
        log(`Geladen: ${result.rowCount} Status-Einträge aus ALKIS.`);
        res.json(result.rows);
    } catch (e) {
        log(`FEHLER beim Laden der Stände: ${e.message}`);
        res.status(500).json({ error: e.message });
    } finally {
        client.release();
    }
});

// NEU: API zum Laden des ALKIS-Layers als GeoJSON
app.get('/api/layers/alkis', async (req, res) => {
    log("Lade ALKIS-Layer aus Datenbank...");
    try {
        const result = await pool.query(
            `SELECT jsonb_build_object(
                'type',     'FeatureCollection',
                'features', jsonb_agg(features.feature)
            )
            FROM (
              SELECT jsonb_build_object(
                'type',       'Feature',
                'id',         id,
                'geometry',   ST_AsGeoJSON(ST_Transform(geom, 4326))::jsonb,
                'properties', jsonb_build_object(
                    'id', id,
                    'vorname', "VNA",
                    'nachname', "GNA",
                    'FSK', "FSK",
                    'PLZ', "PLZ",
                    'ORP', "ORP",
                    'STR', "STR",
                    'HSN', "HSN",
                    'FLN', "FLN",
                    'ZAE', "FSN__ZAE",
                    'NEN', "FSN__NEN",
                    'status', status,
                    'notiz', notiz
                )
              ) AS feature
              FROM geodaten.flaecheneigentuemer_alkis
            ) features`
        );
        res.json(result.rows[0].jsonb_build_object);
    } catch (err) {
        log(`FEHLER beim Laden des ALKIS-Layers: ${err.message}`);
        res.status(500).json({ error: err.message });
    }
});

// NEU: API zum Laden des Artennachweis-Layers als GeoJSON
app.get('/api/layers/artennachweis', async (req, res) => {
    log("Lade Artennachweis-Layer aus Datenbank...");
    try {
        const result = await pool.query(
            `SELECT jsonb_build_object(
                'type',     'FeatureCollection',
                'features', COALESCE(jsonb_agg(features.feature), '[]'::jsonb)
            )
            FROM (
              SELECT jsonb_build_object(
                'type',       'Feature',
                'geometry',   ST_AsGeoJSON(ST_Transform(geom, 4326))::jsonb,
                'properties', jsonb_build_object(
                    'art', art
                )
              ) AS feature
              FROM geodaten.artennachweise
            ) features`
        );
        res.json(result.rows[0].jsonb_build_object);
    } catch (err) {
        log(`FEHLER beim Laden des Artennachweis-Layers: ${err.message}`);
        res.status(500).json({ error: err.message });
    }
});

// NEU: API zum Laden der Artennachweis Restriktionsabstände
app.get('/api/layers/artennachweise_restriktionen', async (req, res) => {
    log("Lade Artennachweise-Restriktionen aus Datenbank...");
    try {
        const result = await pool.query(
            `SELECT jsonb_build_object(
                'type',     'FeatureCollection',
                'features', COALESCE(jsonb_agg(features.feature), '[]'::jsonb)
            )
            FROM (
              SELECT jsonb_build_object(
                'type',       'Feature',
                'geometry',   ST_AsGeoJSON(ST_Transform(geom, 4326))::jsonb,
                'properties', jsonb_build_object()
              ) AS feature
              FROM geodaten.artennachweise_restriktion_abstand
            ) features`
        );
        res.json(result.rows[0].jsonb_build_object);
    } catch (err) {
        log(`FEHLER beim Laden der Restriktionen: ${err.message}`);
        res.status(500).json({ error: err.message });
    }
});

// NEU: API zum Laden der Leitungsverläufe (Freileitung, Wasserstoff etc.)
app.get('/api/layers/leitungsverlaeufe', async (req, res) => {
    log("Lade Leitungsverläufe aus Datenbank...");
    try {
        const result = await pool.query(
            `SELECT jsonb_build_object(
                'type',     'FeatureCollection',
                'features', COALESCE(jsonb_agg(features.feature), '[]'::jsonb)
            )
            FROM (
              SELECT jsonb_build_object(
                'type',       'Feature',
                'geometry',   ST_AsGeoJSON(ST_Transform(geom, 4326))::jsonb,
                'properties', jsonb_build_object(
                    'art', art,
                    'spannung', spannung,
                    'ltg_name', ltg_name,
                    'bezeichnun', bezeichnun,
                    'bemerkung', bemerkung,
                    'status', status,
                    'quelle', quelle,
                    'info', info,
                    'vorschlag', vorschlag
                )
              ) AS feature
              FROM geodaten.leitungsverleaufe
              WHERE art ILIKE '%wasserstoff%' OR art ILIKE '%freileitung%'
            ) features`
        );
        res.json(result.rows[0].jsonb_build_object);
    } catch (err) {
        log(`FEHLER beim Laden der Leitungsverläufe: ${err.message}`);
        res.status(500).json({ error: err.message });
    }
});

// NEU: API zum Laden der Gebäude
app.get('/api/layers/gebaeude', async (req, res) => {
    log("Lade Gebäude aus Datenbank...");
    try {
        const result = await pool.query(
            `SELECT jsonb_build_object(
                'type',     'FeatureCollection',
                'features', COALESCE(jsonb_agg(features.feature), '[]'::jsonb)
            )
            FROM (
              SELECT jsonb_build_object(
                'type',       'Feature',
                'geometry',   ST_AsGeoJSON(ST_Transform(geom, 4326))::jsonb,
                'properties', jsonb_build_object()
              ) AS feature
              FROM geodaten.gebaeude
            ) features`
        );
        res.json(result.rows[0].jsonb_build_object);
    } catch (err) {
        log(`FEHLER beim Laden der Gebäude: ${err.message}`);
        res.status(500).json({ error: err.message });
    }
});

// NEU: API zum Laden der Wohngebäude
app.get('/api/layers/wohngebeaude', async (req, res) => {
    log("Lade Wohngebäude aus Datenbank...");
    try {
        const result = await pool.query(
            `SELECT jsonb_build_object(
                'type',     'FeatureCollection',
                'features', COALESCE(jsonb_agg(features.feature), '[]'::jsonb)
            )
            FROM (
              SELECT jsonb_build_object(
                'type',       'Feature',
                'geometry',   ST_AsGeoJSON(ST_Transform(geom, 4326))::jsonb,
                'properties', jsonb_build_object()
              ) AS feature
              FROM geodaten.wohngebeaude
            ) features`
        );
        res.json(result.rows[0].jsonb_build_object);
    } catch (err) {
        log(`FEHLER beim Laden der Wohngebäude: ${err.message}`);
        res.status(500).json({ error: err.message });
    }
});

// API für Projekt-Statistiken (Fortschrittsanzeige)
app.get('/api/stats/:projekt_id', async (req, res) => {
    const { projekt_id } = req.params;
    log(`Lade Statistiken für Projekt: ${projekt_id}`);
    
    const client = await pool.connect();
    try {
        const resolvedPid = await resolveProjectId(client, projekt_id);
        if (!resolvedPid) {
            throw new Error(`Projekt '${projekt_id}' konnte nicht gefunden werden.`);
        }

        // Verwende die vom User vorgeschlagene Logik, aber mit resolvedPid
        // Wir gruppieren nach aktueller_status (da dies in der View v_projekt_sicherung so heißt)
        const result = await client.query(
            `SELECT 
                aktueller_status as status, 
                count(*) as anzahl,
                ROUND(SUM(ST_Area(geom)) / 10000, 2) as hektar
             FROM geodaten.v_projekt_sicherung 
             WHERE projekt_id = $1
             GROUP BY aktueller_status`,
            [resolvedPid]
        );
        
        log(`Statistiken berechnet: ${result.rows.length} Status-Gruppen.`);
        res.json(result.rows);
    } catch (e) {
        log(`FEHLER beim Laden der Statistiken: ${e.message}`);
        res.status(500).json({ error: e.message });
    } finally {
        client.release();
    }
});

// Catch-all route to serve index.html for any other request (optional, good for SPAs)
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'index.html'));
});

app.listen(port, '0.0.0.0', () => {
    console.log(`Server running at http://0.0.0.0:${port}`);
});
