// poi-backend-service.js
// Dies ist ein Dienst, der für die Kommunikation mit dem Backend zuständig ist.
// Er sollte keine UI-Logik oder Domänenlogik enthalten, sondern nur Daten senden und empfangen.

import { getCurrentUser, getCurrentTimestamp, wait, is_development } from './sc-utilities.js';
export class BackendService {

    constructor() {
        this.baseUrl = this.#getApiBaseUrl();
        if (!this.baseUrl) {
            throw new Error("BackendService benötigt eine baseUrl im Konstruktor.");
        }
    }
    #getApiBaseUrl() {
        // Die Logik, um die Basis-URL zu definieren, bleibt unverändert.
        if (is_development()) {
            return window.location.href.substring(0, window.location.href.lastIndexOf('/') + 1);
        } else {
            // return window.location.origin + '/'; -> das war falsch, weil es nicht die umleitung aus index.php berücksichtigt
            return window.location.href.substring(0, window.location.href.lastIndexOf('/') + 1);
        }
    }



    /**
     * Führt einen generischen POST-Request an das Backend aus.
     * Dies ist eine interne Hilfsfunktion, die von anderen Methoden dieses Dienstes verwendet wird.
     * @param {string} endpoint - Der spezifische API-Endpunkt (z.B. "insert_poi.php").
     * @param {object} data - Das zu sendende Datenobjekt.
     * @returns {Promise<object>} Das JSON-Antwortobjekt vom Server.
     * @throws {Error} Bei Netzwerkfehlern oder nicht-OK HTTP-Antworten.
     */
    /*
    async _post(endpoint, data) {
        const url = `${this.baseUrl}/${endpoint}${window.location.search}`;
        console.log(`Sending POST to: ${url} with data:`, data);

        try {
            const response = await fetch(url, {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify(data),
            });

            if (!response.ok) {
                const errorText = await response.text();
                // Hier werfen wir einen Fehler für HTTP-Statuscodes, die nicht 2xx sind
                throw new Error(`Netzwerkfehler oder Serverantwort nicht OK: ${response.status} - ${response.statusText || errorText}`);
            }

            const result = await response.json();
            // Der BackendService gibt das Ergebnis roh zurück.
            // Die Prüfung von result.success obliegt dem aufrufenden Dienst (z.B. ScStone).
            return result;
        } catch (error) {
            console.error(`Fehler bei POST-Request zu ${url}:`, error);
            throw error; // Fehler weiterreichen zur Behandlung im aufrufenden Code
        }
    }
    */
    async _post(endpoint, data) {
        // Die URL wird korrekt mit window.location.search konstruiert.
        const url = `${this.baseUrl}/${endpoint}${window.location.search}`;

        console.log(`Sending POST to: ${url} with data:`, data);

        try {
            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(data) // Daten werden korrekt im Body gesendet.
            });

            // Fehlerbehandlung für ungültige HTTP-Antworten.
            if (!response.ok) {
                const errorData = await response.json();
                throw new Error(errorData.error || 'Serverantwort nicht OK.');
            }

            const result = await response.json();
            return result;
        } catch (error) {
            // Fehler, die bei der fetch-Anfrage auftreten.
            console.error('Fehler bei der POST-Anfrage:', error);
            throw error;
        }
    }


 
   /**
     * Ruft einen spezifischen Chunk von POI-Daten vom Server ab.
     * @param {number} startId - Die Start-ID des abzurufenden Datenbereichs.
     * @param {number} endId - Die End-ID (exklusive) des abzurufenden Datenbereichs.
     * @returns {Promise<Array<Object>>} Eine Promise, die ein Array von GeoJSON-Features zurückgibt.
     */
    async fetchPOIs(startId, endId) {
        console.log(`BackendService.fetchPOIs aufgerufen: ID-Bereich [${startId}, ${endId - 1}]`);
        
        const endpoint = `fetch_pois.php`;
        const url = `${this.baseUrl}/${endpoint}`;
        
        // --- KORRIGIERTE LOGIK: URL-PARAMETER SICHER ZUSAMMENFÜGEN ---
        const urlParams = new URLSearchParams(window.location.search);
        
        // Fügen die Chunk-Parameter hinzu (überschreiben vorhandene, falls sie aus Versehen in der Haupt-URL stehen)
        urlParams.set('start_id', startId);
        urlParams.set('end_id', endId);
        
        // Füge die Parameter zur finalen URL hinzu, beginnend mit einem Fragezeichen
        const finalUrl = `${url}?${urlParams.toString()}`;

        console.log("Aufrufende URL:", finalUrl);
        // --- ENDE KORRIGIERTE LOGIK ---

        try {
            const response = await fetch(finalUrl, {
                method: "GET",
                headers: { "Content-Type": "application/json" },
            });

            if (!response.ok) {
                const errorText = await response.text();
                console.error("HTTP-Fehler-Antwort-Text:", errorText);
                throw new Error(`Netzwerkfehler oder Serverantwort nicht OK: ${response.status} - ${response.statusText || errorText}`);
            }

            const responseText = await response.text();
            
            let result;
            try {
                result = JSON.parse(responseText);
            } catch (jsonError) {
                console.error("Fehler beim Parsen der JSON-Antwort:", jsonError);
                throw new Error("Antwort vom Server ist kein gültiges JSON. Roher Text: " + responseText);
            }

            // NEUE LOGIK: Prüfen auf GeoJSON FeatureCollection-Format
            if (result && result.type === "FeatureCollection" && Array.isArray(result.features)) {
                return result.features;
            } else {
                if (result && result.type === "FeatureCollection" && result.features.length === 0) {
                     return [];
                }
                
                throw new Error("Unerwartetes Datenformat vom Server für POIs. Erwartet GeoJSON FeatureCollection. Rohes JSON-Objekt: " + JSON.stringify(result));
            }
        } catch (error) {
            console.error(`Fehler beim Abrufen der POI-Daten von ${finalUrl}:`, error);
            throw error;
        }
    }

    /**
     * Ruft einen einzelnen POI anhand seiner GID vom Backend ab.
     * @param {number} gid Die eindeutige ID des POI.
     * @returns {Promise<Object>} Ein Promise, das die POI-Daten als einfaches Objekt auflöst.
     */

    async fetchPoiByGID(gid) {
        console.log(`BackendService.fetchUniquePOI für GID ${gid} aufgerufen.`);

        // URL ohne GID-Parameter, da dieser nun im Body gesendet wird
        const endpoint = `fetch_poi_by_gid.php`;
        const url = `${this.baseUrl}/${endpoint}${window.location.search}`;

        try {
            const response = await fetch(url, {
                method: "POST", // METHODE AUF POST GEÄNDERT
                headers: {
                    "Content-Type": "application/json"
                },
                // GID als JSON-Objekt im Body senden
                body: JSON.stringify({ gid: gid }),
            });

            if (!response.ok) {
                const errorText = await response.text();
                console.error("HTTP-Fehler-Antwort-Text:", errorText);
                throw new Error(`Netzwerkfehler oder Serverantwort nicht OK: ${response.status} - ${response.statusText || errorText}`);
            }

            const responseText = await response.text();

            let result;
            try {
                result = JSON.parse(responseText);
            } catch (jsonError) {
                console.error("Fehler beim Parsen der JSON-Antwort:", jsonError);
                throw new Error("Antwort vom Server ist kein gültiges JSON. Roher Text: " + responseText);
            }

            // NEUE LOGIK: Der Backend-Endpunkt fetch_poi_by_gid.php gibt ein einzelnes Objekt zurück.
            if (result && typeof result === "object") {
                return result;
            } else {
                throw new Error("Unerwartetes Datenformat vom Server. Erwartet ein einzelnes JSON-Objekt. Rohes JSON-Objekt: " + JSON.stringify(result));
            }

        } catch (error) {
            console.error(`Fehler beim Abrufen des POI mit GID ${gid} von ${url}:`, error);
            throw error;
        }
    }

    /**
     * Fügt einen neuen Stolperstein im Backend ein.
     * @param {ScStone} stone - Die ScStone-Instanz, die eingefügt werden soll.
     * @returns {Promise<object>}
     */
    async insertStone(stone) {
        // Hier bereiten wir die Daten für das Backend auf Basis der ScStone-Instanz vor
        if (!stone.updated_by) {
            stone.updated_by = getCurrentUser();
            stone.updated_at = getCurrentTimestamp();
        }
        const data = {
            first_name: stone.first_name,
            last_name: stone.last_name,
            year_of_birth: stone.year_of_birth,
            street: stone.street,
            house_no: stone.house_no,
            localdistrict: stone.localdistrict,
            city: stone.city,
            Lat: stone.Lat,
            Lon: stone.Lon,
            stone_position: stone.stone_position,
            status: stone.status,
            comment: stone.comment,
            caretaker: stone.caretaker,
            URL_Wikipedia: stone.URL_Wikipedia,
            Confirmed_by: stone.Confirmed_by,
            manual_address: stone.manual_address,
            URL_KoDb: stone.URL_KoDb,
            last_cleaned: stone.last_cleaned,
            instance_nr: stone.instance_nr,
            cleaned_by: stone.cleaned_by,
            updated_by: stone.updated_by,
            updated_at: stone.updated_at,
        };
        return this._post("insert-poi.php", data); // Nutzt jetzt die _post-Hilfsfunktion
    }

    /**
     * Aktualisiert den Reinigungsstatus eines Stolpersteins im Backend.
     * @param {object} data - Das Datenobjekt mit gid, username, deviceInfo.
     * @param {boolean} isDirty - True, wenn der Stein als schmutzig markiert werden soll, false für sauber.
     * @returns {Promise<object>} Das JSON-Antwortobjekt vom Server.
     * @throws {Error} Bei Fehlern während des Fetch-Aufrufs oder der Serverantwort.
     */
    async updateStoneCleaningStatus(data, isDirty) {
        console.log("BackendService.updateStoneCleaningStatus aufgerufen.");
        const endpoint = isDirty ? "update_poi_dirty.php" : "update_poi_clean.php";
        return this._post(endpoint, data); // Nutzt jetzt die _post-Hilfsfunktion
    }



    /**
     * Aktualisiert den Paten-Status eines Stolpersteins im Backend.
     * @param {object} data - Das Datenobjekt mit gid und caretaker-Informationen.
     * @returns {Promise<object>} Das JSON-Antwortobjekt vom Server.
     * @throws {Error} Bei Fehlern während des Fetch-Aufrufs oder der Serverantwort.
     */
    async updateStoneCaretakerStatus(data) {
        console.log("BackendService.updateStoneCaretakerStatus aufgerufen.");
        const endpoint = "update_poi_caretaker.php";
        return this._post(endpoint, data); // Nutzt jetzt die _post-Hilfsfunktion
    }

    /**
   * Aktualisiert die Detaildaten zu einem Stolpersteins im Backend.
   * @param {object} data - Das Datenobjekt mit den zu aktualisierenden Informationen.
   * @returns {Promise<object>} Das JSON-Antwortobjekt vom Server.
   * @throws {Error} Bei Fehlern während des Fetch-Aufrufs oder der Serverantwort.
   */
    async updateStoneDetails(data) {
        console.log("BackendService.updateStoneDetails aufgerufen.");
        const endpoint = "update_poi_details.php";
        return this._post(endpoint, data);
    }


    // NEUE METHODE HINZUFÜGEN
    async fetchPOIsByCoordinates(lat, lon, radiusMeters = 50) {
        try {
            const response = await fetch(`${this.baseUrl}get_pois_by_coordinates.php?lat=${lat}&lon=${lon}&radius=${radiusMeters}`);
            if (!response.ok) {
                const errorText = await response.text();
                throw new Error(`HTTP error! status: ${response.status}, response: ${errorText}`);
            }
            const data = await response.json();
            console.log(`POIs for coordinates (${lat}, ${lon}) with radius ${radiusMeters}m:`, data);
            return data; // Annahme: Das Backend gibt ein Array von POIs zurück
        } catch (error) {
            console.error("Error fetching POIs by coordinates:", error);
            throw error; // Fehler weiterwerfen zur weiteren Bearbeitung
        }
    }
    // In api-service.js (oder einem dedizierten poi-service.js)

    /**
     * Ruft Stolpersteine vom Backend ab, die einer bestimmten Adresse entsprechen.
     * Nutzt fetch_poi_by_address.php.
     *
     * @param {string} street - Der gesuchte Straßenname.
     * @param {string} houseNo - Die gesuchte Hausnummer.
     * @returns {Promise<Object[]>} Ein Promise, das mit einem Array von POI-Daten-Objekten aufgelöst wird.
     * Gibt ein leeres Array zurück, wenn keine POIs gefunden werden oder ein Fehler auftritt.
     */

    async fetchPoisByAddress(street, houseNr) {

        // 1. Erstelle die Query-Parameter und füge die Adressdaten hinzu
        const urlParams = new URLSearchParams();
        urlParams.append('street', street);
        urlParams.append('houseNr', houseNr);

        // 2. Prüfe auf den 'p'-Parameter in der aktuellen Browser-URL (für Test/Prod-Logik)
        const windowParams = new URLSearchParams(window.location.search);
        const pParameter = windowParams.get('p');

        // 3. Wenn 'p' in der Browser-URL vorhanden ist, füge es der Request-URL hinzu.
        // Dies handhabt ?p und ?p= korrekt.
        if (pParameter !== null) {
            // Fügt 'p=wert' oder 'p=' hinzu. Wenn die URL nur ?p enthielt, wird der Wert leer sein.
            urlParams.append('p', pParameter);
        }

        // 4. Konstruiere die vollständige URL
        let url = './fetch_poi_by_address.php';
        const queryString = urlParams.toString();
        if (queryString) {
            url += `?${queryString}`;
        }

        console.log("POI-Backend-Abfrage-URL (inkl. Parameter):", url);


        try {
            const response = await fetch(url, {
                method: 'POST'
            });

            if (!response.ok) {
                const errorText = await response.text();

                if (response.status === 400) {
                    console.warn("--- WICHTIGE WARNUNG ---");
                    console.warn(`400 Bad Request erhalten. Dies ist ein SERVER-Fehler. Der Fehler sollte nun behoben sein, wenn alle Parameter in der URL sind. Andernfalls überprüfen Sie bitte die JSON-Verarbeitung im PHP-Backend.`);
                    console.warn("-------------------------");
                    console.error(`POI-Suche (Adresse) abgelehnt/fehlerhaft (HTTP ${response.status}):`, errorText.substring(0, 100) + '...');
                    return [];
                }
                if (response.status === 500) {
                    console.error(`POI-Suche (Adresse) Server-interner Fehler (HTTP ${response.status}):`, errorText.substring(0, 100) + '...');
                    return [];
                }

                throw new Error(`POI-Suche HTTP-Fehler: ${response.status} - ${response.statusText}`);
            }

            const json = await response.json();

            if (json && json.success === true && Array.isArray(json.data)) {
                return json.data;
            } else {
                console.warn("POI-Suche (Adresse) Backend-Antwort in unerwartetem Format:", json);
                return [];
            }
        } catch (error) {
            console.error("Fehler beim Abrufen der POI-Daten (Adresse):", error);
            return [];
        }
    }

    // lese die "beste/nächste " Adresse zu einer Koordinate
    async getAddressFromLocation(lat, lng, maxRetries = 3, retryDelayMs = 1000) {
        let retries = 0;

        while (retries < maxRetries) {
            try {
                console.log(`Versuch ${retries + 1}/${maxRetries}: Abrufen der Adresse für ${lat}, ${lng}...`);
                const response = await fetch(`getAddressFromLocation.php?lat=${lat}&lon=${lng}`);

                if (!response.ok) {
                    const errorText = await response.text();
                    throw new Error(`Serverfehler (${response.status} ${response.statusText}): ${errorText}`);
                }

                const data = await response.json();
                console.log("Adresse erfolgreich empfangen (gesamte API-Antwort):", data);

                if (!data.items || data.items.length === 0) {
                    console.warn("Keine Adress-Items für Koordinaten gefunden.", { lat, lng });
                    return null;
                }

                // Die erste gefundene Adresse zurückgeben, wie es in Ihrem Backend erwartet wird
                return data.items[0];

            } catch (error) {
                console.error(`Fehler beim Abrufen der Adresse (Versuch ${retries + 1}/${maxRetries}):`, error.message);
                retries++;
                if (retries < maxRetries) {
                    console.log(`Warte ${retryDelayMs / 1000} Sekunde(n) vor dem nächsten Versuch...`);
                    await wait(retryDelayMs);
                } else {
                    throw new Error(`Adresse konnte nach ${maxRetries} Versuchen nicht abgerufen werden: ${error.message}`);
                }
            }
        }
        // Dieser Teil sollte niemals erreicht werden, wenn der Fehler im Catch-Block geworfen wird,
        // aber als Fallback für den Compiler.
        throw new Error("Unerwarteter Fehler im Retry-Mechanismus für getAddressFromLocation.");
    }
/**
     * Aktualisiert die geom_geolocation-Spalte eines Stolpersteins im Backend.
     * Dies wird temporär für die automatische Adressvalidierung verwendet.
     *
     * @param {number} gid - Die GID des zu aktualisierenden POI.
     * @param {number} lat - Die neue, präzise Breitengrad-Koordinate.
     * @param {number} lon - Die neue, präzise Längengrad-Koordinate.
     * @returns {Promise<object>} Das JSON-Antwortobjekt vom Server, inklusive success-Status.
     * @throws {Error} Bei Fehlern während des Fetch-Aufrufs oder der Serverantwort.
     */
    async updateStoneGeoLocation(gid, lat, lon) {
        console.log(`BackendService.updateStoneGeoLocation für GID ${gid} aufgerufen.`);
        
        // Das Datenobjekt für den POST-Request vorbereiten
        const data = {
            gid: gid,
            lat: lat,
            lon: lon
        };
        
        // Den Endpunkt (update_poi_geolocation.php) verwenden, den wir im PHP-Skript definiert haben
        return this._post("update_poi_geolocation.php", data); 
    }
    // Weitere Methoden für andere Backend-Interaktionen hier
        /**
     * Holt POI-Daten vom Backend basierend auf dem Namen und Geburtsjahr.
     * Stellt sicher, dass der 'p'-Parameter korrekt im Payload übergeben wird.
     * @param {string[]} nameParts Array von Namensbestandteilen (kann 1 oder mehr sein).
     * @param {number|null} yearOfBirth Das Geburtsjahr (kann null sein).
     * @returns {Promise<object[]>} Liste von POI-Ergebnissen im Standardformat.
     */
    async fetchPoisByName(nameParts, yearOfBirth) {
        let url = './fetch_poi_by_name.php';

        // --- ANPASSUNG FÜR 'p'-PARAMETER ---
        const urlParams = new URLSearchParams(window.location.search);
        const pParameter = urlParams.get('p');
        // -----------------------------------

        const payload = {
            name_parts: nameParts,
            year_of_birth: yearOfBirth
        };

        // Füge den 'p'-Parameter zur Payload hinzu, wenn er in der URL vorhanden ist
        if (pParameter !== null) {
            url += `?p=${encodeURIComponent(pParameter)}`;
        }

        try {
            const response = await fetch(url, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(payload)
            });

            if (!response.ok) {
                const errorText = await response.text();
                // Fangen Sie 400er/500er-Fehler ab, die aufgrund ungültiger Suchparameter entstehen.
                if (response.status === 400 || response.status === 500) {
                    console.error(`POI-Suche (Name) abgelehnt/fehlerhaft (HTTP ${response.status}):`, errorText.substring(0, 100) + '...');
                    return [];
                }
                throw new Error(`POI-Suche HTTP-Fehler: ${response.status} - ${response.statusText}`);
            }

            const json = await response.json();

            if (json && json.success === true && Array.isArray(json.data)) {
                return json.data;
            } else {
                console.warn("POI-Suche (Name) Backend-Antwort in unerwartetem Format:", json);
                return [];
            }
        } catch (error) {
            console.error("Fehler beim Abrufen der POI-Daten (Name):", error);
            return [];
        }
    }
}


