<?php

class Data {
    
    public $id;
    private $pdo;
    private $icloudCalendarUrl;
    private $icloudUser;
    private $icloudPass;

    
    public function __construct($pdo, ?array $icloudConfig = null) {
            $this->pdo = $pdo;

            if ($icloudConfig === null) {
                $configPath = __DIR__ . '/config/icloud.php';
                $icloudConfig = file_exists($configPath) ? require $configPath : [];
            }

            $this->icloudCalendarUrl = $icloudConfig['calendar_url'] ?? '';
            $this->icloudUser        = $icloudConfig['username'] ?? '';
            $this->icloudPass        = $icloudConfig['password'] ?? '';
    }

    public function renderTemplate(string $template, array $vars): string {
        foreach ($vars as $key => $value) {
            $template = preg_replace(
                '/{{\s*' . preg_quote($key, '/') . '\s*}}/',
                (string)$value,
                $template
            );
        }
        return $template;
    }

    
    public function getDataByID($id, $column){
        $stmt = $this->pdo->prepare("SELECT * FROM users WHERE id = :id");
        $stmt->execute([':id' => $id]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        return $row[$column] ?? null;
    }

    public function getTerminDataById($id, $column){
        $stmt = $this->pdo->prepare("SELECT * FROM termine WHERE id = :id");
        $stmt->execute([':id' => $id]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        return $row[$column] ?? null;
    }

    public function getSettingsData($column){
        $stmt = $this->pdo->prepare("SELECT * FROM settings_calendar WHERE id = 1");
        $stmt->execute();
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        return $row[$column] ?? null;
    }

    public function timestampToDate($timestamp){
        return date('d.m.Y H:i', $timestamp);
    }

    /* ======================================
    KALENDER HASH BERECHNEN (zentral)
    ====================================== */
    private function buildCalendarHashFromTermin(array $t): string {
        $data = [
            'start' => (int)$t['startzeit'],
            'end'   => (int)$t['endzeit'],
            'title' => trim((string)$t['location']),
            'desc'  => trim((string)$t['beschreibung']),
        ];

        return hash('sha256', json_encode($data));
    }

    /* ======================================
    KALENDER SYNC STATUS SPEICHERN
    ====================================== */
    private function storeCalendarSyncState(int $terminId, array $terminRow): void
    {
        $hash = $this->buildCalendarHashFromTermin($terminRow);
        $eventId = "termin-$terminId@anjuma";

        $stmt = $this->pdo->prepare("
            UPDATE termine SET
                calendar_event_id = :eid,
                calendar_hash = :hash,
                calendar_synced_at = :ts
            WHERE id = :id
        ");

        $stmt->execute([
            ':eid'  => $eventId,
            ':hash' => $hash,
            ':ts'   => time(),
            ':id'   => $terminId
        ]);
    }



    public function getTerminLabel($id) {
        $sql = "SELECT status FROM termine WHERE id = :id";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([':id' => $id]);
        $status = $stmt->fetchColumn();

        return match ((int)$status) {
            0 => "status-open",     // Blau
            1 => "status-ready",    // Gelb
            2 => "status-done",     // Grün
            3 => "status-cancel",   // Rot
            default => "",
        };
    }

    
    public function getOnlineStatusLabel($id): string {
        $stmt = $this->pdo->prepare("SELECT online FROM users WHERE id = :id");
        $stmt->execute([':id' => $id]);
        $online = $stmt->fetchColumn();

        if ($online === false) {
            return "badge-secondary";
        }

        return ((int)$online === 0) ? "badge-danger" : "badge-success";
    }
    
    public function getTodoStatusLabel($id): string {
        $stmt = $this->pdo->prepare("SELECT status FROM todo WHERE id = :id");
        $stmt->execute([':id' => $id]);
        $status = $stmt->fetchColumn();

        return match ((int)$status) {
            0 => "danger",
            1 => "warning",
            2 => "success",
            default => "secondary",
        };
    }

    private function getLastEditorInfo($terminId)
    {
        $sql = $this->pdo->prepare("
            SELECT user_id, timestamp 
            FROM changes 
            WHERE termin_id = :id
            ORDER BY timestamp DESC 
            LIMIT 1
        ");
        $sql->execute([':id' => $terminId]);
        $row = $sql->fetch(PDO::FETCH_ASSOC);

        if (!$row) {
            return [
                'name' => '—',
                'date' => '—'
            ];
        }

        return [
            'name' => $this->getDataByID($row['user_id'], "name"),
            'date' => date("d.m.Y H:i", $row['timestamp'])
        ];
    }


    private function caldavPut($url, $ics, $isUpdate = false)
    {
        $ch = curl_init($url);

        curl_setopt($ch, CURLOPT_USERPWD, $this->icloudUser . ":" . $this->icloudPass);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
        curl_setopt($ch, CURLOPT_HTTPHEADER, $isUpdate ? [
            "Content-Type: text/calendar"
            // KEIN If-None-Match bei Updates!
        ] : [
            "Content-Type: text/calendar",
            "If-None-Match: *"      // nur bei neuen Events
        ]);

        curl_setopt($ch, CURLOPT_POSTFIELDS, $ics);

        $response = curl_exec($ch);
        $status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $err      = curl_error($ch);

        curl_close($ch);

        // 🔍 DEBUG VOR dem return
        $this->debugLog("PUT to $url | status=$status | error=$err | isUpdate=" . ($isUpdate ? "1" : "0"));

        if ($status !== 201 && $status !== 204) {
            $this->debugLog("Response body: " . substr((string)$response, 0, 500));
        }

        return $status === 201 || $status === 204;
    }


    public function createCalendarEvent($id, $startTs, $endTs, $location, $beschreibung)
    {
        $uid = "termin-$id@anjuma";

        $tz = 'Europe/Berlin';
        $dtstamp = gmdate('Ymd\THis\Z');

        // Sicherheits-Fallback, falls endTs 0 ist
        if (empty($endTs) || $endTs <= 0) {
            $endTs = $startTs + 2 * 3600; // +2 Stunden
        }

        // Start/Ende in lokaler Zeit
        $dtstartStr = (new DateTime("@$startTs"))
                        ->setTimezone(new DateTimeZone($tz))
                        ->format('Ymd\THis');

        $dtendStr   = (new DateTime("@$endTs"))
                        ->setTimezone(new DateTimeZone($tz))
                        ->format('Ymd\THis');

        $location     = $this->icsEscape($location);
        $beschreibung = $this->icsEscape($beschreibung);

        // Status-Name bestimmen
        $statusRaw = $this->getTerminDataById($id, "status");
        $statusName = [
            0 => "Offen",
            1 => "Bereit",
            2 => "Erledigt",
            3 => "Storniert"
        ][$statusRaw] ?? "Unbekannt";

        // Ersteller-Name holen
        $creatorId = $this->getTerminDataById($id, "user_id");
        $creatorName = $this->getDataByID($creatorId, "name");

        // Letzten Bearbeiter holen
        $editInfo = $this->getLastEditorInfo($id);

        // Gage holen
        $gage = $this->getTerminDataById($id, "gage");

        $vars = [
            'id'                    => $id,
            'status'                => $statusName,
            'locationtype'          => $this->getTerminDataById($id, "locationtype"),
            'location'              => $this->getTerminDataById($id, "location"),
            'startzeit'             => date('d.m.Y H:i', $this->getTerminDataById($id, "startzeit")),
            'endzeit'               => date('H:i', $this->getTerminDataById($id, "endzeit")),
            'gage'                  => $this->getTerminDataById($id, "gage"),
            'desc'                  => $this->getTerminDataById($id, "beschreibung"),
            'creator'               => $creatorName,
            'last_editor'           => $editInfo['name'],
            'last_edited'           => $editInfo['date']
        ];

        $summary = $this->renderTemplate($this->getSettingsData("title_template"), $vars);
        $beschreibungFull = $this->renderTemplate($this->getSettingsData("description_template"), $vars);
            
        $beschreibungFull = $this->icsEscape($beschreibungFull);



        $ics =
            "BEGIN:VCALENDAR\r\n" .
            "VERSION:2.0\r\n" .
            "PRODID:-//ANJUMA//DE\r\n" .
            "CALSCALE:GREGORIAN\r\n" .
            "BEGIN:VEVENT\r\n" .
            "UID:$uid\r\n" .
            "DTSTAMP:$dtstamp\r\n" .
            "DTSTART;TZID=$tz:$dtstartStr\r\n" .
            "DTEND;TZID=$tz:$dtendStr\r\n" .
            "SUMMARY:$summary\r\n" .
            "LOCATION:$location\r\n" .
            "DESCRIPTION:$beschreibungFull\r\n" .
            "URL:https://dashboard.anjuma-crew.de/termin_show.php?id=$id\r\n" .

            // Erinnerung 1 Tag vorher
            "BEGIN:VALARM\r\n" .
            "TRIGGER:-P1D\r\n" .
            "ACTION:DISPLAY\r\n" .
            "DESCRIPTION:Erinnerung\r\n" .
            "END:VALARM\r\n" .

            "END:VEVENT\r\n" .
            "END:VCALENDAR\r\n";

        $url = $this->icloudCalendarUrl . "termin-$id.ics";

        // Create = isUpdate=false
        $success = $this->caldavPut($url, $ics, false);

        if ($success) {
            // Termin neu laden (für Hash)
            $stmt = $this->pdo->prepare("SELECT * FROM termine WHERE id = :id");
            $stmt->execute([':id' => $id]);
            $termin = $stmt->fetch(PDO::FETCH_ASSOC);

            if ($termin) {
                $this->storeCalendarSyncState($id, $termin);
            }
        }

        return $success;

    }



    public function updateCalendarEvent($id)
    {
        $stmt = $this->pdo->prepare("SELECT * FROM termine WHERE id = :id");
        $stmt->execute([':id' => $id]);
        $t = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$t) {
            $this->debugLog("updateCalendarEvent: Termin $id nicht gefunden");
            return false;
        }

        $startTs      = (int)$t["startzeit"];
        $endTs        = (int)$t["endzeit"];
        $location     = $t["location"] ?? "";
        $beschreibung = $t["beschreibung"] ?? "";

        $uid = "termin-$id@anjuma";
        $tz  = 'Europe/Berlin';
        $dtstamp = gmdate('Ymd\THis\Z');

        if (empty($endTs) || $endTs <= 0) {
            $endTs = $startTs + 2 * 3600;
        }

        $dtstartStr = (new DateTime("@$startTs"))
                        ->setTimezone(new DateTimeZone($tz))
                        ->format('Ymd\THis');

        $dtendStr   = (new DateTime("@$endTs"))
                        ->setTimezone(new DateTimeZone($tz))
                        ->format('Ymd\THis');

        $locationEsc     = $this->icsEscape($location);
        $beschreibungEsc = $this->icsEscape($beschreibung);
        $summary         = "ANJUMA DJ $locationEsc ($id)";

        // Status-Name bestimmen
        $statusRaw = $this->getTerminDataById($id, "status");
        $statusName = [
            0 => "Offen",
            1 => "Bereit",
            2 => "Erledigt",
            3 => "Storniert"
        ][$statusRaw] ?? "Unbekannt";

        // Letzten Bearbeiter holen
        $editInfo = $this->getLastEditorInfo($id);

        // Gage holen
        $gage = $this->getTerminDataById($id, "gage");

        $creatorId = $this->getTerminDataById($id, "user_id");
        $creatorName = $this->getDataByID($creatorId, "name");

        $vars = [
            'id'                    => $id,
            'status'                => $statusName,
            'locationtype'          => $this->getTerminDataById($id, "locationtype"),
            'location'              => $this->getTerminDataById($id, "location"),
            'startzeit'             => date('d.m.Y H:i', $this->getTerminDataById($id, "startzeit")),
            'endzeit'               => date('H:i', $this->getTerminDataById($id, "endzeit")),
            'gage'                  => $this->getTerminDataById($id, "gage"),
            'desc'                  => $this->getTerminDataById($id, "beschreibung"),
            'creator'               => $creatorName,
            'last_editor'           => $editInfo['name'],
            'last_edited'           => $editInfo['date']
        ];

        $summary = $this->renderTemplate($this->getSettingsData("title_template"), $vars);
        $beschreibungFull = $this->renderTemplate($this->getSettingsData("description_template"), $vars);
            
        $beschreibungFull = $this->icsEscape($beschreibungFull);



        $ics =
            "BEGIN:VCALENDAR\r\n" .
            "VERSION:2.0\r\n" .
            "PRODID:-//ANJUMA//DE\r\n" .
            "CALSCALE:GREGORIAN\r\n" .
            "BEGIN:VEVENT\r\n" .
            "UID:$uid\r\n" .
            "DTSTAMP:$dtstamp\r\n" .
            "DTSTART;TZID=$tz:$dtstartStr\r\n" .
            "DTEND;TZID=$tz:$dtendStr\r\n" .
            "SUMMARY:$summary\r\n" .
            "LOCATION:$locationEsc\r\n" .
            "DESCRIPTION:$beschreibungFull\r\n" .
            "URL:https://dashboard.anjuma-crew.de/termin_show.php?id=$id\r\n" .

            "BEGIN:VALARM\r\n" .
            "TRIGGER:-P1D\r\n" .
            "ACTION:DISPLAY\r\n" .
            "DESCRIPTION:Erinnerung\r\n" .
            "END:VALARM\r\n" .

            "BEGIN:VALARM\r\n" .
            "TRIGGER:-PT2H\r\n" .
            "ACTION:DISPLAY\r\n" .
            "DESCRIPTION:Erinnerung\r\n" .
            "END:VALARM\r\n" .

            "END:VEVENT\r\n" .
            "END:VCALENDAR\r\n";

        $url = $this->icloudCalendarUrl . "termin-$id.ics";

        // Update = isUpdate=true
        $success = $this->caldavPut($url, $ics, true);

        if ($success) {
            $this->storeCalendarSyncState($id, $t);
        }

        return $success;

    }


    public function deleteCalendarEvent($id)
    {
        $url = $this->icloudCalendarUrl . "termin-$id.ics";

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
        curl_setopt($ch, CURLOPT_USERPWD, $this->icloudUser . ":" . $this->icloudPass);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);

        $response = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        curl_close($ch);

        return $status === 200 || $status === 204;
    }



    public function changeTermin($id, $was, $value): void {
        $allowed = [
            'startzeit', 'endzeit', 'location', 'locationtype',
            'gage', 'anwesend', 'beschreibung', 'status',
            'ansprechpartner', 'preisprostunde', 'realendzeit',
        ];

        if (!in_array($was, $allowed, true)) {
            throw new InvalidArgumentException("Ungültige Spalte: " . $was);
        }

        $sql = "UPDATE termine SET `" . $was . "` = :value WHERE id = :id";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([':value' => $value, ':id' => $id]);
    }
    private function icsEscape($text)
    {
        // Normalize line endings (Windows/Mac/Linux)
        $text = str_replace(["\r\n", "\r"], "\n", $text);

        // ICS requires escaping BACKSLASH first!
        $text = str_replace("\\", "\\\\", $text);

        // Then escape comma and semicolon
        $text = str_replace(",", "\\,", $text);
        $text = str_replace(";", "\\;", $text);

        // Only now convert \n to ICS linebreaks
        $text = str_replace("\n", "\\n", $text);

        return $text;
    }

    public function createTermin($startzeit, $endzeit, $location, $user_id, $gage, $locationtype)
    {
        if ($gage === "" || $gage === null) $gage = 0;

        $sql = "INSERT INTO termine 
            (startzeit, endzeit, locationtype, location, user_id, gage, status, anwesend, beschreibung)
            VALUES (:startzeit, :endzeit, :locationtype, :location, :user_id, :gage, 0, '[]', '')";

        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([
            ':startzeit'       => $startzeit,
            ':endzeit'         => $endzeit,
            ':locationtype'    => $locationtype,
            ':location'        => $location,
            ':user_id'         => $user_id,
            ':gage'            => $gage
        ]);

        $id = $this->pdo->lastInsertId();

        $this->createCalendarEvent($id, $startzeit, $endzeit, $location, "");

        return $id;
    }


    public function createChanges($id, $user_id, $was, $alt, $neu)
    {
        // =============================================
        // 1) CHANGE SPEICHERN
        // =============================================
        $stmt = $this->pdo->prepare("
            INSERT INTO changes (termin_id, user_id, was, alt, neu, timestamp)
            VALUES (:id, :user, :was, :alt, :neu, :ts)
        ");

        $stmt->execute([
            ':id'  => $id,
            ':user' => $user_id,
            ':was' => $was,
            ':alt' => $alt,
            ':neu' => $neu,
            ':ts'  => time()
        ]);
        // -------------------------------------------
        //  NTFY BENACHRICHTIGUNG (schön formatiert)
        // -------------------------------------------

        // === NTFY CHANNEL ===
        /*$ntfy_url = "https://ntfy.anjuma-crew.de/anjuma-dashboard"; // <<< anpassen

        // === Basic Auth ===
        $auth = "Basic anVzdGluOm5ZZ0dwNnNNRWdMRWwx";

        // === Nachricht bauen ===
        $username = $this->getDataByID($user_id, "name");

        if ($was === "anwesend") {
            $altDecoded = json_decode($alt, true) ?: [];
            $neuDecoded = json_decode($neu, true) ?: [];

            // IDs zu Namen umwandeln
            $altNames = array_map(fn($u) => $this->getDataByID($u, "name"), $altDecoded);
            $neuNames = array_map(fn($u) => $this->getDataByID($u, "name"), $neuDecoded);

            $alt = implode(", ", $altNames);
            $neu = implode(", ", $neuNames);
        }

        // Mapping für schönere Bezeichnungen syfe-xapm-vcjx-dnbi
        $labelMap = [
            "status"        => "Status",
            "anwesend"      => "Anwesende Personen",
            "location"      => "Location",
            "ansprechpartner" => "Ansprechpartner",
            "gage"          => "Gage",
            "preisprostunde" => "Preis pro Stunde",
            "startzeit"     => "Startzeit",
            "endzeit"       => "Endzeit",
            "realendzeit"   => "Tatsächliche Endzeit",
            "create"   => "Termin Erstellt"
        ];

        $label = $labelMap[$was] ?? ucfirst($was);

        // Titel
        $title = "Änderung in Termin #$id – $label";

        // Nachricht
        $body  = 
        "$username hat $label geändert.\n\n" .
        "🔻 Alt: $alt\n" .
        "🔺 Neu: $neu";


        // === CURL Request ===
        $ch = curl_init($ntfy_url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            "Authorization: $auth",
            "X-Title: $title",
            "X-Priority: 3",
            "Content-Type: text/plain"
        ]);
        curl_setopt($ch, CURLOPT_TIMEOUT, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        curl_exec($ch);
        curl_close($ch);*/
        return;
    }



    
    public function setTerminStatus($id, $status): void {
        $this->changeTermin($id, 'status', $status);
    }
    
    public function setTodoTitle($id, $title): void {
        $stmt = $this->pdo->prepare("UPDATE todo SET title = :title WHERE id = :id");
        $stmt->execute([':title' => $title, ':id' => $id]);
    }
    
    public function setTodoDescription($id, $description): void {
        $stmt = $this->pdo->prepare("UPDATE todo SET description = :desc WHERE id = :id");
        $stmt->execute([':desc' => $description, ':id' => $id]);
    }
    
    public function deleteTodoById($id): void {
        $stmt = $this->pdo->prepare("DELETE FROM todo WHERE id = :id");
        $stmt->execute([':id' => $id]);
    }
    
    public function createTodo($id, $title, $description): void {
        $stmt = $this->pdo->prepare("INSERT INTO todo (creator, title, description) VALUES (:creator, :title, :desc)");
        $stmt->execute([':creator' => $id, ':title' => $title, ':desc' => $description]);
    }
    
    public function getTodoDataById($id, $column){
        $stmt = $this->pdo->prepare("SELECT * FROM todo WHERE id = :id");
        $stmt->execute([':id' => $id]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        return $row[$column] ?? null;
    }
    
    public function getAllReadyGigs(): int {
        $stmt = $this->pdo->prepare("SELECT COUNT(*) FROM termine WHERE status = :status");
        $stmt->execute([':status' => 1]);
        return (int)$stmt->fetchColumn();
    }

    public function getAllProcessingGigs(): int {
        $stmt = $this->pdo->prepare("SELECT COUNT(*) FROM termine WHERE status = :status");
        $stmt->execute([':status' => 0]);
        return (int)$stmt->fetchColumn();
    }

    public function getAllCompletedGigs(): int {
        $stmt = $this->pdo->prepare("SELECT COUNT(*) FROM termine WHERE status = :status");
        $stmt->execute([':status' => 2]);
        return (int)$stmt->fetchColumn();
    }

    private function debugLog($msg) {
        $file = __DIR__ . "/debug/caldav_debug.log";
        file_put_contents($file, date("[Y-m-d H:i:s] ") . $msg . "\n", FILE_APPEND);
    }


}

?>