<?php
declare(strict_types=1);

/**
ET-Chat Copyright by SEDesign | ET-Chat v3.x.x Lizenz: CCPL | Autor: Evgeni Tcherkasski (info@s-e-d.de)
ET-Chat_T-FISH-MOD Weiterentwicklungen, Optimierungen und Ergänzungen am Code sind das geistige Eigentum von Tommy (Thomas Kuhn) und Harlekin (Bernd Witte).

Die darauf folgende Optimierungen und Ergänzungen am Code sind das Geistige Eigentum von Powermen (Christian K.)
und wird unter der Namenserweiterung M.C.v.x.x.x. geführt. 
PHP 8/9 Ready, XML Parser, PDO Prepared Statements Get Set sicherheit usw.
 */

class AdminSpracheSpeichern extends DbConectionMaker
{
    public function __construct()
    {
        parent::__construct();

        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }

        // 🔐 Rollenprüfung
        $allowedRoles = ["admin"];
        $userRole = $_SESSION['etchat_'.$this->_prefix.'user_priv'] ?? '';

        if (!in_array($userRole, $allowedRoles, true)) {
            header("Location: ./");
            exit;
        }

        // 🔐 CSRF prüfen
        $csrfSession = $_SESSION["etchat_" . $this->_prefix . "csrf_token"] ?? '';
        $csrfPost    = $_POST['csrf'] ?? '';

        if (!$csrfSession || !$csrfPost || !hash_equals($csrfSession, $csrfPost)) {
            $this->fail("Ungültige Anfrage (CSRF).");
        }

        // 🔐 Eingaben validieren
        $bereich = trim((string)($_POST['bereich'] ?? ''));
        $eintraege = $_POST['eintraege'] ?? [];

        if (
            $bereich === '' ||
            !preg_match('/^[a-zA-Z0-9_\/-]+$/', $bereich) ||
            !is_array($eintraege)
        ) {
            $this->fail("Ungültige Eingaben.");
        }

        // Config laden
        $desei = $this->dbObj->sqlGet(
            "SELECT etchat_config_style, etchat_config_lang
             FROM {$this->_prefix}etchat_config
             WHERE etchat_config_id = :id",
            [':id' => 1]
        );

        $this->speichereAenderungen($desei, $bereich, $eintraege);
    }

    private function speichereAenderungen($desei, string $bereich, array $eintraege): void
    {
        $langFile = 'lang_de.xml';
        $langBase = realpath(__DIR__ . '/../../lang/');

        if (is_array($desei)) {
            foreach ($desei as $data) {
                $langValue = $data['etchat_config_lang'] ?? '';
                if (!empty($langValue)) {
                    $safeFile = basename($langValue);
                    $fullPath = realpath(__DIR__ . '/../../lang/' . $safeFile);

                    if ($fullPath && $langBase && str_starts_with($fullPath, $langBase)) {
                        $langFile = $safeFile;
                    }
                }
            }
        }

        $xml_file = realpath(__DIR__ . '/../../lang/' . $langFile);

        if (!$xml_file || !file_exists($xml_file)) {
            $this->fail("XML-Datei nicht gefunden.");
        }

        // 🔐 Backup
        $backupDir = __DIR__ . '/../../lang/old/';

        if (!is_dir($backupDir) && !mkdir($backupDir, 0755, true) && !is_dir($backupDir)) {
            $this->fail("Backup-Ordner konnte nicht erstellt werden.");
        }

        $backupFile = basename($xml_file) . '.bak.' . date('Ymd_His');
        $backup = $backupDir . $backupFile;

        if (!copy($xml_file, $backup)) {
            $this->fail("Backup konnte nicht erstellt werden!");
        }

        // 🔐 XML laden
        libxml_use_internal_errors(true);

        $dom = new DOMDocument('1.0', 'UTF-8');
        $dom->preserveWhiteSpace = false;
        $dom->formatOutput = true;

        if (!$dom->load($xml_file)) {
            copy($backup, $xml_file);
            $this->fail("Fehler beim Laden der XML.");
        }

        $xpath = new DOMXPath($dom);

        $teileBereich = array_values(array_filter(explode('/', $bereich)));

        if (empty($teileBereich)) {
            $this->fail("Ungültiger Bereich.");
        }

        $rootName = $dom->documentElement->nodeName;
        $query = '/' . $rootName . '/' . implode('/', $teileBereich);

        $nodes = $xpath->query($query);

        if ($nodes->length === 0) {
            copy($backup, $xml_file);
            $this->fail("Bereich nicht gefunden.");
        }

        $targetNode = $nodes->item(0);

        $bereichName = end($teileBereich);

        foreach ($eintraege as $pfadRelativ => $wert) {

            $wert = (string)$wert;
            $pfadRelativ = trim((string)$pfadRelativ, "/");

            if ($pfadRelativ === '') continue;

            if (strpos($pfadRelativ, $bereichName . '/') === 0) {
                $pfadRelativ = substr($pfadRelativ, strlen($bereichName) + 1);
            }

            $parts = array_values(array_filter(explode('/', $pfadRelativ)));
            $current = $targetNode;

            foreach ($parts as $segment) {

                if (preg_match('/^(.*)_(\d+)$/', $segment, $m)) {
                    $tag = $m[1];
                    $index = (int)$m[2];
                } else {
                    $tag = $segment;
                    $index = 0;
                }

                $existing = [];

                foreach ($current->childNodes as $child) {
                    if ($child->nodeType === XML_ELEMENT_NODE && $child->nodeName === $tag) {
                        $existing[] = $child;
                    }
                }

                while (count($existing) <= $index) {
                    $new = $dom->createElement($tag);
                    $current->appendChild($new);
                    $existing[] = $new;
                }

                $current = $existing[$index];
            }

            while ($current->firstChild) {
                $current->removeChild($current->firstChild);
            }

            $current->appendChild($dom->createTextNode($wert));
        }

        // 🔐 speichern
        $tmpFile = $xml_file . '.tmp';

        if (!$dom->save($tmpFile)) {
            copy($backup, $xml_file);
            $this->fail("Fehler beim Schreiben.");
        }

        if (!rename($tmpFile, $xml_file)) {
            if (!copy($tmpFile, $xml_file)) {
                copy($backup, $xml_file);
                if (is_file($tmpFile)) unlink($tmpFile);
                $this->fail("Speichern fehlgeschlagen.");
            }
            unlink($tmpFile);
        }

        $this->dbObj->close();

        // 👉 Übergabe ans Template
        $this->renderTemplate($bereich, $desei);
    }

    private function renderTemplate(string $bereich, $desei): void
    {
        $style = '';

        if (is_array($desei)) {
            foreach ($desei as $data) {
                $style = $data['etchat_config_style'] ?? '';
            }
        }

        $bereichEsc = htmlspecialchars($bereich, ENT_QUOTES, 'UTF-8');

        include __DIR__ . '/../../styles/admin_tpl/insertSpracheSpeichern.tpl.html';
    }

    private function fail(string $msg): void
    {
        echo htmlspecialchars($msg, ENT_QUOTES, 'UTF-8');
        exit;
    }
}