<?php
if (!defined('ABSPATH')) {
    exit;
}

class simpbook_DB_Reservierungen {

    public function __construct() {
        add_shortcode('simpbook_bookingform', array($this, 'simpbook_reservierungsformular_anzeigen'));
        add_action('admin_menu', array($this, 'simpbook_admin_menu_erstellen'));
        add_action('wp_ajax_simpbook_reservierung_speichern', array($this, 'simpbook_reservierung_speichern'));
        add_action('wp_ajax_nopriv_simpbook_reservierung_speichern', array($this, 'simpbook_reservierung_speichern'));
        add_action('wp_enqueue_scripts', array($this, 'simpbook_skripte_laden'));
        add_action('admin_enqueue_scripts', array($this, 'simpbook_admin_skripte_laden'));
        add_action('wp_ajax_simpbook_get_available_times', array($this, 'simpbook_get_available_times'));
        add_action('wp_ajax_nopriv_simpbook_get_available_times', array($this, 'simpbook_get_available_times'));
        add_action('wp_ajax_simpbook_get_mitarbeiter_fuer_dienstleistung', array($this, 'simpbook_ajax_get_mitarbeiter_fuer_dienstleistung'));
        add_action('wp_ajax_nopriv_simpbook_get_mitarbeiter_fuer_dienstleistung', array($this, 'simpbook_ajax_get_mitarbeiter_fuer_dienstleistung'));

        add_action('wp_ajax_simpbook_sende_nachricht_an_gast', [$this, 'simpbook_sende_nachricht_an_gast']);
        add_action('wp_ajax_simpbook_get_email_templates', array($this, 'simpbook_get_email_templates_ajax'));
        add_action('wp_ajax_simpbook_save_dienstleistung', array($this, 'simpbook_ajax_save_dienstleistung'));
        add_action('wp_ajax_simpbook_get_mitarbeiter_zuweisung_for_dienstleistung', array($this, 'simpbook_ajax_get_mitarbeiter_zuweisung_for_dienstleistung'));
        add_action('wp_ajax_simpbook_toggle_dienstleistung_status', array($this, 'simpbook_ajax_toggle_dienstleistung_status'));
        add_action('wp_ajax_simpbook_delete_dienstleistung', array($this, 'simpbook_ajax_delete_dienstleistung'));
        add_action('wp_ajax_simpbook_reorder_dienstleistungen', array($this, 'simpbook_ajax_reorder_dienstleistungen'));
        add_action('wp_ajax_simpbook_duplicate_dienstleistung', array($this, 'simpbook_ajax_duplicate_dienstleistung'));
        add_action('wp_ajax_simpbook_get_buchungsoptionen', array($this, 'simpbook_ajax_get_buchungsoptionen'));
        add_action('wp_ajax_simpbook_get_dienstleistung_buchungsoptionen', array($this, 'simpbook_ajax_get_dienstleistung_buchungsoptionen'));
        add_action('wp_ajax_simpbook_delete_buchungsoption', array($this, 'simpbook_ajax_delete_buchungsoption'));
        add_action('wp_ajax_simpbook_delete_mitarbeiter', array($this, 'simpbook_ajax_delete_mitarbeiter'));
        add_action('wp_ajax_simpbook_get_available_dates_for_service', array($this, 'simpbook_ajax_get_available_dates_for_service'));
        add_action('wp_ajax_nopriv_simpbook_get_available_dates_for_service', array($this, 'simpbook_ajax_get_available_dates_for_service'));
        add_action('wp_ajax_simpbook_get_available_employees_for_service_date', array($this, 'simpbook_ajax_get_available_employees_for_service_date'));
        add_filter('wp_mail_from', array($this, 'simpbook_aendere_mail_absender_email'));
        add_filter('wp_mail_from_name', array($this, 'simpbook_aendere_mail_absender_name'));
        add_action('admin_init', array($this, 'simpbook_handle_csv_export_action'));
        add_action('template_redirect', array($this, 'simpbook_handle_cancellation_request'));
        add_action('wp_ajax_simpbook_cancel_reservation', array($this, 'simpbook_ajax_cancel_reservation'));
        add_action('wp_ajax_nopriv_simpbook_cancel_reservation', array($this, 'simpbook_ajax_cancel_reservation'));
        add_action('wp_ajax_simpbook_get_calendar_events', array($this, 'simpbook_ajax_get_calendar_events'));
        add_action('wp_ajax_simpbook_get_reservierung_details', array($this, 'simpbook_ajax_get_reservierung_details'));
        add_action('wp_ajax_simpbook_update_reservierung_mitarbeiter', array($this, 'simpbook_ajax_update_reservierung_mitarbeiter'));
        add_action('wp_ajax_simpbook_generate_calendar_token', array($this, 'simpbook_ajax_generate_calendar_token'));
        add_action('wp_ajax_simpbook_delete_calendar_token', array($this, 'simpbook_ajax_delete_calendar_token'));
        add_action('wp_ajax_simpbook_get_form_preview', array($this, 'simpbook_get_form_preview_ajax'));
        add_action('wp_ajax_simpbook_get_form_config', array($this, 'simpbook_get_form_config_ajax'));
        add_action('wp_ajax_simpbook_save_form_config', array($this, 'simpbook_save_form_config_ajax'));
        add_action('wp_ajax_simpbook_update_language_override', array($this, 'simpbook_ajax_update_language_override'));
        add_action('init', array($this, 'simpbook_handle_ics_feed'));

        // Textdomain Loading
        add_action('plugins_loaded', array($this, 'simpbook_load_plugin_textdomain'), 1);
        add_action('init', array($this, 'simpbook_load_plugin_textdomain'), 1);
        add_filter('plugin_locale', array($this, 'simpbook_override_plugin_locale'), 10, 2);

        // Cron-Job für Erinnerungs-E-Mails sicherstellen (auch bei bereits aktiven Plugins)
        add_action('init', 'simpbook_maybe_schedule_reminder_emails');

        // Setup-Wizard Hooks
        add_action('admin_init', array($this, 'simpbook_handle_setup_wizard_submit'), 1);
        add_action('admin_init', array($this, 'simpbook_handle_setup_wizard_reset'), 1);
        add_action('admin_init', array($this, 'simpbook_handle_setup_wizard_complete_reset'), 1);

        // Mitarbeiter Formular-Verarbeitung
        add_action('admin_init', array($this, 'simpbook_handle_mitarbeiter_submit'), 1);

        // Admin-Aktionen früh verarbeiten (vor Header-Ausgabe für Redirects)
        add_action('admin_init', array($this, 'simpbook_handle_admin_actions_early'), 1);
    }

    /**
     * Override locale for this plugin
     */
    public function simpbook_override_plugin_locale($locale, $domain) {
        if ('simple-appointment-booking' === $domain) {
            $plugin_language = simpbook_get_current_language();
            return $plugin_language;
        }
        return $locale;
    }

    /**
     * Load plugin textdomain
     */
    public function simpbook_load_plugin_textdomain() {
        self::reload_plugin_textdomain();
    }

    /**
     * Reload plugin textdomain (static method for use outside class)
     */
    public static function reload_plugin_textdomain() {
        // WordPress Cache für Optionen leeren, um sicherzustellen, dass wir die neueste Sprache erhalten
        wp_cache_delete('simpbook_language', 'options');
        wp_cache_delete('simpbook_language_override', 'options');
        wp_cache_delete('alloptions', 'options');

        // Get current language using the override logic (Priority: Override → WordPress Language → en_US)
        $plugin_language = simpbook_get_current_language();

        // Sanitize language to ensure it's valid
        $plugin_language = simpbook_sanitize_language($plugin_language);

        // Unload existing translations first
        unload_textdomain('simple-appointment-booking');

        // Load plugin-specific translation file directly
        $mofile = plugin_dir_path(dirname(__FILE__)) . 'languages/simple-appointment-booking-' . $plugin_language . '.mo';
        if (file_exists($mofile)) {
            load_textdomain('simple-appointment-booking', $mofile);
        } else {
            // Fallback: Try to load default language if requested language file doesn't exist
            $default_mofile = plugin_dir_path(dirname(__FILE__)) . 'languages/simple-appointment-booking-en_US.mo';
            if (file_exists($default_mofile)) {
                load_textdomain('simple-appointment-booking', $default_mofile);
            }
        }
        // Note: WordPress automatically loads plugin translations since version 4.6
    }

    /**
     * Get current plugin language
     */
    public static function get_current_language() {
        return simpbook_get_current_language();
    }

    /**
     * Verarbeitet Reset-Requests vom Setup-Wizard.
     */
    public function simpbook_handle_setup_wizard_reset() {
        // Nur auf der Wizard-Seite ausführen
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
        $current_page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
        if (($current_page !== 'simpbook-reservierungen' && $current_page !== 'simpbook-dashboard') || !isset($_GET['simpbook_wizard'])) {
            return;
        }

        // Prüfe ob Reset-Request
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for action routing only
        if (!isset($_GET['simpbook_reset_step']) || !isset($_GET['simpbook_nonce'])) {
            return;
        }

        $step = intval($_GET['simpbook_reset_step']);
        $nonce = sanitize_text_field(wp_unslash($_GET['simpbook_nonce']));

        if (!wp_verify_nonce($nonce, 'simpbook_wizard_reset_step_' . $step)) {
            wp_die(esc_html__('Security check failed.', 'simple-appointment-booking'));
            return;
        }

        if ($step === 1) {
            // Schritt 1 zurücksetzen: Grunddaten
            update_option('simpbook_firmen_name', get_bloginfo('name'));
            update_option('simpbook_benachrichtigungs_email', '');
            update_option('simpbook_email_benachrichtigungen', '1');

            wp_safe_redirect(admin_url('admin.php?page=simpbook-dashboard&simpbook_wizard=1&simpbook_step=1&simpbook_reset=success'));
            exit;
        }
    }

    /**
     * Verarbeitet kompletten Reset des Setup-Wizards (von Einstellungsseite).
     */
    public function simpbook_handle_setup_wizard_complete_reset() {
        // Prüfe ob Reset-Request von Einstellungsseite
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for action routing only
        if (!isset($_GET['simpbook_wizard_reset']) || !isset($_GET['simpbook_nonce'])) {
            return;
        }

        // Prüfe ob auf Dashboard oder Einstellungsseite
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
        $current_page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
        if ($current_page !== 'simpbook-reservierungen' && $current_page !== 'simpbook-reservierungen-einstellungen') {
            return;
        }

        $nonce = sanitize_text_field(wp_unslash($_GET['simpbook_nonce']));

        if (!wp_verify_nonce($nonce, 'simpbook_wizard_reset')) {
            wp_die(esc_html__('Security check failed.', 'simple-appointment-booking'));
            return;
        }

        // Lösche den Wizard-Completed-Transient
        delete_transient('simpbook_setup_wizard_completed');

        // Weiterleitung zum Wizard
        wp_safe_redirect(admin_url('admin.php?page=simpbook-dashboard&simpbook_wizard=1&simpbook_step=1'));
        exit;
    }

    /**
     * Verarbeitet Setup-Wizard Formular-Submits (vor Output).
     */
    public function simpbook_handle_setup_wizard_submit() {
        // Nur auf der Wizard-Seite ausführen
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
        $current_page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
        if (($current_page !== 'simpbook-reservierungen' && $current_page !== 'simpbook-dashboard') || !isset($_GET['simpbook_wizard'])) {
            return;
        }

        // Prüfe ob Formular abgeschickt wurde
        if (!isset($_POST['simpbook_wizard_submit']) || !isset($_POST['simpbook_wizard_step'])) {
            return;
        }

        $step = intval($_POST['simpbook_wizard_step']);
        check_admin_referer('simpbook_wizard_step_' . $step);

        if ($step === 1) {
            // Schritt 1: Firmenname und E-Mail
            if (isset($_POST['simpbook_firmen_name'])) {
                update_option('simpbook_firmen_name', sanitize_text_field(wp_unslash($_POST['simpbook_firmen_name'])));
            }
            if (isset($_POST['simpbook_benachrichtigungs_email'])) {
                $email = sanitize_email(wp_unslash($_POST['simpbook_benachrichtigungs_email']));
                if (!empty($email)) {
                    update_option('simpbook_benachrichtigungs_email', $email);
                }
            }
            if (isset($_POST['simpbook_email_benachrichtigungen'])) {
                update_option('simpbook_email_benachrichtigungen', '1');
            } else {
                update_option('simpbook_email_benachrichtigungen', '0');
            }
            wp_safe_redirect(admin_url('admin.php?page=simpbook-dashboard&simpbook_wizard=1&simpbook_step=2'));
            exit;
        } elseif ($step === 2) {
            // Schritt 2: Öffnungszeiten (mindestens ein Tag)
            $wochentag_zeiten = get_option('simpbook_wochentag_zeiten', []);
            $wochentage_keys = ['montag', 'dienstag', 'mittwoch', 'donnerstag', 'freitag', 'samstag', 'sonntag'];

            $at_least_one_day = false;
            foreach ($wochentage_keys as $tag_key) {
                $aktiv = isset($_POST['simpbook_' . $tag_key . '_aktiv']) ? '1' : '0';
                $beginn = isset($_POST['simpbook_' . $tag_key . '_beginn']) ? sanitize_text_field(wp_unslash($_POST['simpbook_' . $tag_key . '_beginn'])) : '11:00';
                $ende = isset($_POST['simpbook_' . $tag_key . '_ende']) ? sanitize_text_field(wp_unslash($_POST['simpbook_' . $tag_key . '_ende'])) : '22:00';

                if ($aktiv === '1') {
                    $at_least_one_day = true;
                }

                $wochentag_zeiten[$tag_key] = [
                    'aktiv' => $aktiv,
                    'beginn' => $beginn,
                    'ende' => $ende
                ];
            }

            if ($at_least_one_day) {
                update_option('simpbook_wochentag_zeiten', $wochentag_zeiten);
                wp_safe_redirect(admin_url('admin.php?page=simpbook-dashboard&simpbook_wizard=1&simpbook_step=3'));
                exit;
            } else {
                wp_safe_redirect(admin_url('admin.php?page=simpbook-dashboard&simpbook_wizard=1&simpbook_step=2&simpbook_error=no_day'));
                exit;
            }
        } elseif ($step === 3) {
            // Schritt 3: Dienstleistung anlegen
            global $wpdb;
            $table_name = $wpdb->prefix . 'dienstleistungen';

            $name = isset($_POST['simpbook_dienstleistung_name']) ? sanitize_text_field(wp_unslash($_POST['simpbook_dienstleistung_name'])) : '';
            $dauer_minuten = isset($_POST['simpbook_dienstleistung_dauer']) ? intval($_POST['simpbook_dienstleistung_dauer']) : 30;
            $pufferzeit_minuten = isset($_POST['simpbook_dienstleistung_pufferzeit']) ? intval($_POST['simpbook_dienstleistung_pufferzeit']) : 0;
            $beschreibung = isset($_POST['simpbook_dienstleistung_beschreibung']) ? wp_kses_post(wp_unslash($_POST['simpbook_dienstleistung_beschreibung'])) : '';

            if (!empty($name)) {
                $data = [
                    'name' => $name,
                    'dauer_minuten' => $dauer_minuten,
                    'pufferzeit_minuten' => $pufferzeit_minuten,
                    'beschreibung' => $beschreibung,
                    'aktiv' => 1,
                    'sortierung' => 0,
                ];
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
                $wpdb->insert($table_name, $data, ['%s', '%d', '%d', '%s', '%d', '%d']);
            }

            wp_safe_redirect(admin_url('admin.php?page=simpbook-dashboard&simpbook_wizard=1&simpbook_step=4'));
            exit;
        } elseif ($step === 4) {
            // Schritt 4: Mitarbeiter anlegen
            global $wpdb;
            $mitarbeiter_table = $wpdb->prefix . 'mitarbeiter';

            $name = isset($_POST['simpbook_mitarbeiter_name']) ? sanitize_text_field(wp_unslash($_POST['simpbook_mitarbeiter_name'])) : '';
            $email = isset($_POST['simpbook_mitarbeiter_email']) ? sanitize_email(wp_unslash($_POST['simpbook_mitarbeiter_email'])) : '';
            $telefon = isset($_POST['simpbook_mitarbeiter_telefon']) ? sanitize_text_field(wp_unslash($_POST['simpbook_mitarbeiter_telefon'])) : '';

            if (!empty($name)) {
                // Keine individuellen Arbeitszeiten beim Erstellen - verwendet globale Öffnungszeiten
                $data = [
                    'name' => $name,
                    'email' => $email,
                    'telefon' => $telefon,
                    'profilfoto_url' => '',
                    'im_frontend_anzeigen' => 1,
                    'aktiv' => 1,
                    'sortierung' => 0,
                    'arbeitszeiten' => '',
                ];
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
                $wpdb->insert($mitarbeiter_table, $data, ['%s', '%s', '%s', '%s', '%d', '%d', '%d', '%s']);
            }

            wp_safe_redirect(admin_url('admin.php?page=simpbook-dashboard&simpbook_wizard=1&simpbook_step=5'));
            exit;
        } elseif ($step === 5) {
            // Schritt 5: Sprache
            if (isset($_POST['simpbook_language'])) {
                $language = sanitize_text_field(wp_unslash($_POST['simpbook_language']));
                $valid_languages = ['de_DE', 'en_US', 'en_US_AMPM', 'it_IT', 'es_ES', 'fr_FR', 'pl_PL'];
                if (in_array($language, $valid_languages, true)) {
                    // Speichere in simpbook_language_override (die korrekte Option)
                    simpbook_update_option('simpbook_language_override', $language);
                    wp_safe_redirect(admin_url('admin.php?page=simpbook-dashboard&simpbook_wizard=1&simpbook_step=6'));
                    exit;
                }
            }
        } elseif ($step === 6) {
            // Schritt 6: Abschluss
            set_transient('simpbook_setup_wizard_completed', true, YEAR_IN_SECONDS);
            wp_safe_redirect(admin_url('admin.php?page=simpbook-dashboard&simpbook_wizard_completed=1'));
            exit;
        }
    }

    /**
     * Verarbeitet das Mitarbeiter-Formular (vor Header-Senden)
     */
    public function simpbook_handle_mitarbeiter_submit() {
        // Debug: Logge dass die Funktion aufgerufen wird
        // Disabled for production
        // if (defined('WP_DEBUG') && WP_DEBUG) {
        //     error_log('PocketBooking: simpbook_handle_mitarbeiter_submit() called');
        //     error_log('PocketBooking: $_GET[page] = ' . (isset($_GET['page']) ? $_GET['page'] : 'not set'));
        //     error_log('PocketBooking: $_POST[simpbook_mitarbeiter_speichern] = ' . (isset($_POST['simpbook_mitarbeiter_speichern']) ? 'SET' : 'NOT SET'));
        //     error_log('PocketBooking: $_POST keys = ' . implode(', ', array_keys($_POST)));
        // }

        // Nur auf der Mitarbeiter-Seite ausführen
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
        $current_page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
        if ($current_page !== 'simpbook-mitarbeiter') {
            return;
        }

        // Prüfe ob Formular abgeschickt wurde
        if (!isset($_POST['simpbook_mitarbeiter_speichern'])) {
            return;
        }

        // Debug: Prüfe Nonce
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Form data validated by check_admin_referer
        $nonce_check = check_admin_referer('simpbook_mitarbeiter_speichern');
        // Disabled for production
        // if (defined('WP_DEBUG') && WP_DEBUG) {
        //     error_log('PocketBooking: Mitarbeiter submit - Nonce check: ' . ($nonce_check ? 'passed' : 'failed'));
        //     error_log('PocketBooking: simpbook_name = ' . (isset($_POST['simpbook_name']) ? $_POST['simpbook_name'] : 'NOT SET'));
        // }

        if (!$nonce_check) {
            return;
        }

        global $wpdb;
        $mitarbeiter_table = $wpdb->prefix . 'mitarbeiter';
        $relation_table = $wpdb->prefix . 'mitarbeiter_dienstleistungen';

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for ID check only
        $mitarbeiter_id = isset($_GET['simpbook_id']) ? intval($_GET['simpbook_id']) : 0;
        $mitarbeiter = null;
        if ($mitarbeiter_id > 0) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
            $mitarbeiter = $wpdb->get_row($wpdb->prepare("SELECT * FROM %i WHERE id = %d", $mitarbeiter_table, $mitarbeiter_id));
        }

        $name = isset($_POST['simpbook_name']) ? sanitize_text_field(wp_unslash($_POST['simpbook_name'])) : '';
        $email = isset($_POST['simpbook_email']) ? sanitize_email(wp_unslash($_POST['simpbook_email'])) : '';
        $telefon = isset($_POST['simpbook_telefon']) ? sanitize_text_field(wp_unslash($_POST['simpbook_telefon'])) : '';
        $profilfoto_url = isset($_POST['simpbook_profilfoto_url']) ? esc_url_raw(wp_unslash($_POST['simpbook_profilfoto_url'])) : '';
        $aktiv = isset($_POST['simpbook_aktiv']) ? 1 : 0;
        // im_frontend_anzeigen wird automatisch auf den gleichen Wert wie aktiv gesetzt
        $im_frontend_anzeigen = $aktiv;
        $sortierung = isset($_POST['simpbook_sortierung']) ? intval($_POST['simpbook_sortierung']) : 0;

        // Arbeitszeiten speichern - nur wenn individuelle Arbeitszeiten aktiviert sind
        $individuelle_arbeitszeiten_aktiv = isset($_POST['simpbook_individuelle_arbeitszeiten_aktiv']) ? 1 : 0;
        $arbeitszeiten_json = '';

        if ($individuelle_arbeitszeiten_aktiv) {
            $wochentage = ['montag', 'dienstag', 'mittwoch', 'donnerstag', 'freitag', 'samstag', 'sonntag'];
            $standard_beginn = '09:00';
            $standard_ende = '18:00';
            $arbeitszeiten_data = [];
            foreach ($wochentage as $tag_key) {
                $aktiv_tag = isset($_POST["simpbook_arbeitszeit_{$tag_key}_aktiv"]) ? '1' : '0';
                $beginn = isset($_POST["simpbook_arbeitszeit_{$tag_key}_beginn"]) ? sanitize_text_field(wp_unslash($_POST["simpbook_arbeitszeit_{$tag_key}_beginn"])) : $standard_beginn;
                $ende = isset($_POST["simpbook_arbeitszeit_{$tag_key}_ende"]) ? sanitize_text_field(wp_unslash($_POST["simpbook_arbeitszeit_{$tag_key}_ende"])) : $standard_ende;
                $arbeitszeiten_data[$tag_key] = [
                    'aktiv' => $aktiv_tag,
                    'beginn' => $beginn,
                    'ende' => $ende
                ];
            }
            $arbeitszeiten_json = json_encode($arbeitszeiten_data);
        }

        // Dienstleistungszuordnungen
        $selected_dienstleistungen = isset($_POST['simpbook_dienstleistungen']) && is_array($_POST['simpbook_dienstleistungen'])
            ? array_map('intval', $_POST['simpbook_dienstleistungen'])
            : [];

        if (empty($name)) {
            // Fehler: Name fehlt - Redirect zurück mit Fehlermeldung
            $redirect_url = admin_url('admin.php?page=simpbook-mitarbeiter&simpbook_aktion=bearbeiten');
            if ($mitarbeiter_id > 0) {
                $redirect_url .= '&simpbook_id=' . $mitarbeiter_id;
            }
            $redirect_url .= '&simpbook_nachricht=fehler_name';
            wp_safe_redirect($redirect_url);
            exit;
        }

        $data = [
            'name' => $name,
            'email' => $email,
            'telefon' => $telefon,
            'profilfoto_url' => $profilfoto_url,
            'im_frontend_anzeigen' => $im_frontend_anzeigen,
            'aktiv' => $aktiv,
            'sortierung' => $sortierung,
            'arbeitszeiten' => $arbeitszeiten_json,
        ];
        
        // App-Zugang verarbeiten (wenn Spalte existiert)
        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $app_zugang_column_exists = $wpdb->get_results("SHOW COLUMNS FROM $mitarbeiter_table LIKE 'app_zugang_aktiv'");
        $app_zugang_aktiv = isset($_POST['simpbook_app_zugang_aktiv']) ? 1 : 0;
        
        // Validierung: Wenn App-Zugang aktiviert ist, muss eine E-Mail vorhanden sein
        if (!empty($app_zugang_column_exists) && $app_zugang_aktiv && empty($email)) {
            $redirect_url = admin_url('admin.php?page=simpbook-mitarbeiter&simpbook_aktion=bearbeiten');
            if ($mitarbeiter_id > 0) {
                $redirect_url .= '&simpbook_id=' . $mitarbeiter_id;
            }
            $redirect_url .= '&simpbook_nachricht=fehler_email_app_zugang';
            wp_safe_redirect($redirect_url);
            exit;
        }
        
        if (!empty($app_zugang_column_exists)) {
            $data['app_zugang_aktiv'] = $app_zugang_aktiv;
        }

        if ($mitarbeiter_id > 0 && $mitarbeiter) {
            // Aktualisieren
            // Format-Strings dynamisch aufbauen basierend auf vorhandenen Spalten
            $format_strings = ['%s', '%s', '%s', '%s', '%d', '%d', '%d', '%s'];
            if (!empty($app_zugang_column_exists)) {
                $format_strings[] = '%d'; // app_zugang_aktiv
            }
            
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->update($mitarbeiter_table, $data, ['id' => $mitarbeiter_id], $format_strings, ['%d']);
            
            // App-Zugang: WordPress-User erstellen wenn aktiviert und noch nicht vorhanden
            if (!empty($app_zugang_column_exists) && $app_zugang_aktiv && !empty($email)) {
                $current_wp_user_id = isset($mitarbeiter->wp_user_id) ? (int) $mitarbeiter->wp_user_id : 0;
                
                if (!$current_wp_user_id && class_exists('Simpbook_PWA_Auth')) {
                    $auth = Simpbook_PWA_Auth::get_instance();
                    $password = wp_generate_password(12, true, true);
                    $new_user_id = $auth->create_user_for_mitarbeiter($mitarbeiter_id, $email, $password);
                    
                    if (!is_wp_error($new_user_id)) {
                        // E-Mail mit Zugangsdaten senden
                        $auth->send_app_access_email($mitarbeiter_id, $password);
                    }
                }
            }

            // Dienstleistungszuordnungen aktualisieren
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->delete($relation_table, ['mitarbeiter_id' => $mitarbeiter_id], ['%d']);
            foreach ($selected_dienstleistungen as $dienstleistung_id) {
                if ($dienstleistung_id > 0) {
                    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                    $wpdb->insert($relation_table, ['mitarbeiter_id' => $mitarbeiter_id, 'dienstleistung_id' => $dienstleistung_id], ['%d', '%d']);
                }
            }

            wp_safe_redirect(admin_url('admin.php?page=simpbook-mitarbeiter&simpbook_aktion=bearbeiten&simpbook_id=' . $mitarbeiter_id . '&simpbook_nachricht=aktualisiert'));
            exit;
        } else {
            // Neu erstellen
            $format_strings = ['%s', '%s', '%s', '%s', '%d', '%d', '%d', '%s'];
            if (!empty($app_zugang_column_exists)) {
                $format_strings[] = '%d'; // app_zugang_aktiv
            }
            
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->insert($mitarbeiter_table, $data, $format_strings);
            $new_mitarbeiter_id = $wpdb->insert_id;

            // App-Zugang: WordPress-User erstellen wenn aktiviert
            if (!empty($app_zugang_column_exists) && $app_zugang_aktiv && !empty($email)) {
                if (class_exists('Simpbook_PWA_Auth')) {
                    $auth = Simpbook_PWA_Auth::get_instance();
                    $password = wp_generate_password(12, true, true);
                    $new_user_id = $auth->create_user_for_mitarbeiter($new_mitarbeiter_id, $email, $password);
                    
                    if (!is_wp_error($new_user_id)) {
                        // E-Mail mit Zugangsdaten senden
                        $auth->send_app_access_email($new_mitarbeiter_id, $password);
                    }
                }
            }

            // Dienstleistungszuordnungen speichern
            foreach ($selected_dienstleistungen as $dienstleistung_id) {
                if ($dienstleistung_id > 0) {
                    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                    $wpdb->insert($relation_table, ['mitarbeiter_id' => $new_mitarbeiter_id, 'dienstleistung_id' => $dienstleistung_id], ['%d', '%d']);
                }
            }

            wp_safe_redirect(admin_url('admin.php?page=simpbook-mitarbeiter&simpbook_aktion=bearbeiten&simpbook_id=' . $new_mitarbeiter_id . '&simpbook_nachricht=gespeichert'));
            exit;
        }
    }

    /**
     * Verarbeitet Admin-Aktionen (Status ändern, Löschen, Stornieren) früh vor Header-Ausgabe.
     * Wird in admin_init ausgeführt, um Redirects zu ermöglichen.
     */
    public function simpbook_handle_admin_actions_early() {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
        $current_page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
        
        // Nur auf unseren Plugin-Seiten ausführen
        if (!in_array($current_page, array('simpbook-reservierungen', 'simpbook-kalender'), true)) {
            return;
        }

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for action routing only
        $aktion = isset($_GET['simpbook_aktion']) ? sanitize_text_field(wp_unslash($_GET['simpbook_aktion'])) : '';
        $id = isset($_GET['simpbook_id']) ? intval($_GET['simpbook_id']) : 0;

        if (empty($aktion) || $id <= 0) {
            return;
        }

        // Status ändern
        if ($aktion === 'simpbook_status_aendern' && isset($_GET['simpbook_status'])) {
            $provided_token = isset($_GET['simpbook_token']) ? sanitize_text_field(wp_unslash($_GET['simpbook_token'])) : '';
            $provided_nonce = isset($_GET['simpbook_nonce']) ? sanitize_text_field(wp_unslash($_GET['simpbook_nonce'])) : '';
            
            $is_authorized = false;
            $is_token_auth = false;
            
            // Methode 1: Token-basierte Authentifizierung (für E-Mail-Links)
            if (!empty($provided_token)) {
                $token_data = simpbook_verify_email_token($provided_token, $id);
                if ($token_data) {
                    $is_authorized = true;
                    $is_token_auth = true;
                }
            }
            
            // Methode 2: Nonce-basierte Authentifizierung (für Admin-Backend)
            if (!$is_authorized && !empty($provided_nonce) && is_user_logged_in() && current_user_can('read')) {
                if (wp_verify_nonce($provided_nonce, 'simpbook_status_change_nonce_' . $id)) {
                    $is_authorized = true;
                }
            }
            
            if ($is_authorized) {
                // URL-safe Status-Code zu echtem Status konvertieren (für Gmail-Kompatibilität)
                $status_code = sanitize_text_field(wp_unslash($_GET['simpbook_status']));
                $status_map = [
                    'BESTAETIGT' => 'BESTÄTIGT',
                    'BESTÄTIGT' => 'BESTÄTIGT',  // Fallback falls direkt aufgerufen
                    'ABGELEHNT' => 'ABGELEHNT'
                ];
                $neuer_status = isset($status_map[$status_code]) ? $status_map[$status_code] : $status_code;
                
                $this->simpbook_status_aendern($id, $neuer_status);
                
                // Token wird NICHT gelöscht und bleibt bis zum Ablaufdatum gültig (7 Tage)
                // Dadurch können Links mehrfach verwendet werden ohne Fehlermeldung

                // Status-Nachricht basierend auf dem neuen Status
                $nachricht = 'aktualisiert';
                if ($neuer_status === 'BESTÄTIGT') {
                    $nachricht = 'bestaetigt';
                } elseif ($neuer_status === 'ABGELEHNT') {
                    $nachricht = 'abgelehnt';
                }

                // Redirect-URL bestimmen
                if ($current_page === 'simpbook-kalender') {
                    $redirect_url = isset($_GET['simpbook_redirect_to']) 
                        ? esc_url_raw(wp_unslash($_GET['simpbook_redirect_to'])) 
                        : simpbook_maybe_add_pwa_param(admin_url('admin.php?page=simpbook-kalender'));
                    $redirect_url = add_query_arg('simpbook_nachricht', $nachricht, $redirect_url);
                } else {
                    $redirect_params = array('simpbook_nachricht' => $nachricht);
                    if (isset($_GET['simpbook_seite_nr'])) $redirect_params['simpbook_seite_nr'] = sanitize_text_field(wp_unslash($_GET['simpbook_seite_nr']));
                    if (isset($_GET['simpbook_order'])) $redirect_params['simpbook_order'] = sanitize_text_field(wp_unslash($_GET['simpbook_order']));
                    if (isset($_GET['simpbook_direction'])) $redirect_params['simpbook_direction'] = sanitize_text_field(wp_unslash($_GET['simpbook_direction']));
                    if (isset($_GET['simpbook_filter'])) $redirect_params['simpbook_filter'] = sanitize_text_field(wp_unslash($_GET['simpbook_filter']));
                    $redirect_url = add_query_arg($redirect_params, simpbook_maybe_add_pwa_param(admin_url('admin.php?page=simpbook-reservierungen')));
                }

                wp_safe_redirect($redirect_url);
                exit;
            } else {
                // Benutzerfreundliche Fehlermeldung
                $error_title = __('Link invalid or expired', 'simple-appointment-booking');
                $error_message = __('This link is no longer valid. Possible reasons:', 'simple-appointment-booking');
                $reason_1 = __('The link is older than 7 days', 'simple-appointment-booking');
                $reason_2 = __('Die Reservierung wurde bereits bearbeitet', 'simple-appointment-booking');
                $contact_message = __('Bei Fragen kontaktieren Sie uns bitte.', 'simple-appointment-booking');
                
                echo '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">';
                echo '<style>body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,sans-serif;background:#f5f5f5;margin:0;padding:20px}.error-container{max-width:600px;margin:40px auto;background:#fff;border-radius:8px;box-shadow:0 2px 8px rgba(0,0,0,0.1);padding:40px;text-align:center}.error-icon{font-size:64px;margin-bottom:20px}.error-title{color:#d32f2f;font-size:24px;margin:0 0 20px;font-weight:600}.error-message{color:#555;font-size:16px;line-height:1.6;margin-bottom:20px}.reason-list{text-align:left;margin:20px auto;max-width:400px;padding:20px;background:#f9f9f9;border-radius:6px}.reason-list li{margin:10px 0;color:#666}.contact{margin-top:30px;padding-top:20px;border-top:2px solid #f0f0f0;color:#888;font-size:14px}</style>';
                echo '</head><body>';
                echo '<div class="error-container">';
                echo '<div class="error-icon">⚠️</div>';
                echo '<h1 class="error-title">' . esc_html($error_title) . '</h1>';
                echo '<p class="error-message">' . esc_html($error_message) . '</p>';
                echo '<ul class="reason-list">';
                echo '<li>' . esc_html($reason_1) . '</li>';
                echo '<li>' . esc_html($reason_2) . '</li>';
                echo '</ul>';
                echo '<p class="contact">' . esc_html($contact_message) . '</p>';
                echo '</div>';
                
                // Debug-Informationen nur für eingeloggte Admins
                if (is_user_logged_in() && current_user_can('manage_options')) {
                    echo '<details style="max-width:600px;margin:20px auto;padding:20px;background:#fff;border-radius:8px;">';
                    echo '<summary style="cursor:pointer;font-weight:bold;color:#666;">🔧 Debug-Informationen (nur für Admins sichtbar)</summary>';
                    echo '<div style="margin-top:20px;font-family:monospace;font-size:12px;text-align:left;">';
                
                echo '<h3>📧 Request Data:</h3>';
                echo '<p><strong>Provided Token:</strong> <code style="background:#f0f0f0;padding:3px 8px;border-radius:4px;">' . esc_html($provided_token ?: '(none)') . '</code></p>';
                echo '<p><strong>Provided Nonce:</strong> <code style="background:#f0f0f0;padding:3px 8px;border-radius:4px;">' . esc_html($provided_nonce ?: '(none)') . '</code></p>';
                echo '<p><strong>Booking ID:</strong> <code style="background:#f0f0f0;padding:3px 8px;border-radius:4px;">' . esc_html($id) . '</code></p>';
                echo '<p><strong>Status Code:</strong> <code style="background:#f0f0f0;padding:3px 8px;border-radius:4px;">' . (isset($_GET['simpbook_status']) ? esc_html(sanitize_text_field(wp_unslash($_GET['simpbook_status']))) : 'NONE') . '</code></p>';
                
                echo '<hr><h3>👤 User Info:</h3>';
                echo '<p><strong>Current User ID:</strong> ' . absint(get_current_user_id()) . '</p>';
                echo '<p><strong>Is User Logged In:</strong> ' . (is_user_logged_in() ? '✅ YES' : '❌ NO') . '</p>';
                if (is_user_logged_in()) {
                    $current_user = wp_get_current_user();
                    echo '<p><strong>User Login:</strong> ' . esc_html($current_user->user_login) . '</p>';
                    echo '<p><strong>User Roles:</strong> ' . esc_html(implode(', ', $current_user->roles)) . '</p>';
                }
                
                echo '<hr><h3>🔑 Authentication Check:</h3>';
                
                // Token-Check
                if (!empty($provided_token)) {
                    global $wpdb;
                    $tokens_table = $wpdb->prefix . 'simpbook_email_tokens';
                    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                    $token_info = $wpdb->get_row($wpdb->prepare(
                        "SELECT * FROM %i WHERE token = %s AND booking_id = %d",
                        $tokens_table,
                        $provided_token,
                        $id
                    ));
                    
                    if ($token_info) {
                        echo '<p><strong>Token Found:</strong> ✅ YES</p>';
                        echo '<p><strong>Token Created:</strong> ' . esc_html($token_info->created_at) . '</p>';
                        echo '<p><strong>Token Expires:</strong> ' . esc_html($token_info->expires_at) . '</p>';
                        $now = current_time('mysql');
                        $is_expired = ($token_info->expires_at < $now);
                        echo '<p><strong>Token Status:</strong> ' . ($is_expired ? '❌ EXPIRED' : '⚠️ VALID but verification failed') . '</p>';
                    } else {
                        echo '<p><strong>Token Found:</strong> ❌ NO - Token existiert nicht oder falsche Booking-ID</p>';
                    }
                } else {
                    echo '<p><strong>Token:</strong> Nicht angegeben</p>';
                }
                
                // Nonce-Check
                if (!empty($provided_nonce)) {
                    $nonce_valid = wp_verify_nonce($provided_nonce, 'simpbook_status_' . $id);
                    echo '<p><strong>Nonce Valid:</strong> ' . ($nonce_valid ? '✅ YES' : '❌ NO - Nonce ungültig oder abgelaufen') . '</p>';
                } else {
                    echo '<p><strong>Nonce:</strong> Nicht angegeben</p>';
                }
                
                echo '<hr><h3>🌐 Request Info:</h3>';
                $request_method = isset($_SERVER['REQUEST_METHOD']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_METHOD'])) : '';
                echo '<p><strong>Request Method:</strong> ' . esc_html($request_method) . '</p>';
                
                $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';
                echo '<p style="word-break:break-all;"><strong>Full URL:</strong> <small>' . esc_html($request_uri) . '</small></p>';
                
                echo '</div></details>';
                }
                
                echo '</body></html>';
                exit;
            }
        }

        // Löschen
        if ($aktion === 'loeschen') {
            if (isset($_GET['simpbook_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['simpbook_nonce'])), 'simpbook_delete_nonce_' . $id)) {
                global $wpdb;
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
                $wpdb->delete($wpdb->prefix . 'buchungen', array('id' => $id), array('%d'));

                // Redirect-URL bestimmen
                if ($current_page === 'simpbook-kalender') {
                    $redirect_url = isset($_GET['simpbook_redirect_to']) 
                        ? esc_url_raw(wp_unslash($_GET['simpbook_redirect_to'])) 
                        : simpbook_maybe_add_pwa_param(admin_url('admin.php?page=simpbook-kalender'));
                    $redirect_url = add_query_arg('simpbook_nachricht', 'geloescht', $redirect_url);
                } else {
                    $redirect_params = array('simpbook_nachricht' => 'geloescht');
                    if (isset($_GET['simpbook_seite_nr'])) $redirect_params['simpbook_seite_nr'] = sanitize_text_field(wp_unslash($_GET['simpbook_seite_nr']));
                    if (isset($_GET['simpbook_order'])) $redirect_params['simpbook_order'] = sanitize_text_field(wp_unslash($_GET['simpbook_order']));
                    if (isset($_GET['simpbook_direction'])) $redirect_params['simpbook_direction'] = sanitize_text_field(wp_unslash($_GET['simpbook_direction']));
                    if (isset($_GET['simpbook_filter'])) $redirect_params['simpbook_filter'] = sanitize_text_field(wp_unslash($_GET['simpbook_filter']));
                    $redirect_url = add_query_arg($redirect_params, simpbook_maybe_add_pwa_param(admin_url('admin.php?page=simpbook-reservierungen')));
                }

                wp_safe_redirect($redirect_url);
                exit;
            } else {
                wp_die(esc_html__('Security check failed.', 'simple-appointment-booking'));
            }
        }

        // Stornieren
        if ($aktion === 'stornieren') {
            if (isset($_GET['simpbook_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['simpbook_nonce'])), 'simpbook_delete_nonce_' . $id)) {
                $this->simpbook_reservierung_stornieren_ohne_redirect($id);

                // Redirect-URL bestimmen
                if ($current_page === 'simpbook-kalender') {
                    $redirect_url = isset($_GET['simpbook_redirect_to']) 
                        ? esc_url_raw(wp_unslash($_GET['simpbook_redirect_to'])) 
                        : simpbook_maybe_add_pwa_param(admin_url('admin.php?page=simpbook-kalender'));
                    $redirect_url = add_query_arg('simpbook_nachricht', 'storniert', $redirect_url);
                } else {
                    $redirect_params = array('simpbook_nachricht' => 'storniert');
                    if (isset($_GET['simpbook_seite_nr'])) $redirect_params['simpbook_seite_nr'] = sanitize_text_field(wp_unslash($_GET['simpbook_seite_nr']));
                    if (isset($_GET['simpbook_order'])) $redirect_params['simpbook_order'] = sanitize_text_field(wp_unslash($_GET['simpbook_order']));
                    if (isset($_GET['simpbook_direction'])) $redirect_params['simpbook_direction'] = sanitize_text_field(wp_unslash($_GET['simpbook_direction']));
                    if (isset($_GET['simpbook_filter'])) $redirect_params['simpbook_filter'] = sanitize_text_field(wp_unslash($_GET['simpbook_filter']));
                    $redirect_url = add_query_arg($redirect_params, simpbook_maybe_add_pwa_param(admin_url('admin.php?page=simpbook-reservierungen')));
                }

                wp_safe_redirect($redirect_url);
                exit;
            } else {
                wp_die(esc_html__('Security check failed.', 'simple-appointment-booking'));
            }
        }
    }

    /**
     * Storniert eine Reservierung ohne Redirect (für frühe Verarbeitung).
     */
    private function simpbook_reservierung_stornieren_ohne_redirect($id) {
        global $wpdb;
        $tabellen_name = $wpdb->prefix . 'buchungen';

        // Reservierung laden
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
        $reservierung = $wpdb->get_row($wpdb->prepare("SELECT * FROM %i WHERE id = %d", $tabellen_name, $id));
        if (!$reservierung) {
            return false;
        }

        // Als storniert markieren
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->update(
            $tabellen_name,
            array(
                'storniert' => 1,
                'stornierungs_datum' => current_time('mysql'),
            ),
            array('id' => $id),
            array('%d', '%s'),
            array('%d')
        );

        // E-Mail an Gast senden (wenn E-Mail-Benachrichtigungen aktiviert sind)
        if (simpbook_get_option('simpbook_email_benachrichtigungen', '1') === '1') {
            $this->simpbook_sende_stornierungs_email($id);
        }

        return true;
    }

    /**
     * Gibt modernes CSS für Admin-Seiten zurück.
     */
    public function simpbook_get_modern_admin_css() {
        $css = '/* Modern Admin Menu Styling */';
        $css .= '
#adminmenu #toplevel_page_simpbook-dashboard {
    background: linear-gradient(135deg, #1a4a8a 0%, #0e7490 100%) !important;
    border-radius: 8px;
    margin: 10px 0;
    box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
    transition: all 0.3s ease;
}

#adminmenu #toplevel_page_simpbook-dashboard:hover {
    background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
    box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
    transform: translateX(2px);
}

#adminmenu #toplevel_page_simpbook-dashboard > a {
    color: white !important;
    font-weight: 600;
}

#adminmenu #toplevel_page_simpbook-dashboard .wp-menu-image {
    filter: brightness(1.2);
}

/* Submenu Items Styling */
#adminmenu #toplevel_page_simpbook-dashboard ul.wp-submenu {
    background: #f8f9fa;
    border-left: 4px solid #667eea;
    border-radius: 0 8px 8px 0;
    padding: 8px 0;
    margin-left: 0;
}

#adminmenu #toplevel_page_simpbook-dashboard ul.wp-submenu a {
    color: #333;
    font-size: 13px;
    transition: all 0.2s ease;
    border-left: 3px solid transparent;
}

#adminmenu #toplevel_page_simpbook-dashboard ul.wp-submenu a:hover {
    background: #e9ecef;
    color: #667eea;
    border-left-color: #667eea;
}

#adminmenu #toplevel_page_simpbook-dashboard ul.wp-submenu li.current a {
    background: #f0f3ff;
    color: #667eea;
    border-left-color: #667eea;
    font-weight: 600;
}

/* Admin Page Headers */
.wrap h1, .wrap h2 {
    color: #333;
    font-weight: 700;
    border-bottom: 3px solid #667eea;
    display: inline-block;
}

/* Table Styling */
.wp-list-table {
    border: 1px solid #e0e0e0;
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

.wp-list-table thead {
    background: linear-gradient(135deg, #1a4a8a 0%, #0e7490 100%) !important;
    color: white;
}

.wp-list-table thead th {
    color: white;
    font-weight: 600;
    padding: 15px;
    border-bottom: none;
}

.wp-list-table tbody tr {
    border-bottom: 1px solid #e0e0e0;
    transition: background-color 0.2s ease;
}

.wp-list-table tbody tr:hover {
    background: #f5f7ff;
}

.wp-list-table tbody td {
    padding: 15px;
    vertical-align: middle;
}

/* Cards/Boxes Styling */
.postbox, .notice, .error, .updated, .metabox-holder {
    border: 1px solid #e0e0e0;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

.postbox {
    padding: 20px;
}

.notice.notice-success {
    background-color: #d4edda;
    border-color: #28a745;
    color: #155724;
}

.notice.notice-error {
    background-color: #f8d7da;
    border-color: #f5c6cb;
    color: #721c24;
}

.notice.notice-warning {
    background-color: #fff3cd;
    border-color: #ffc107;
    color: #856404;
}

.notice.notice-info {
    background-color: #d1ecf1;
    border-color: #0c5460;
    color: #0c5460;
}

/* Form Inputs */
input[type="text"], input[type="email"], input[type="number"], input[type="date"],
input[type="time"], textarea, select {
    border: 1px solid #ddd;
    border-radius: 6px;
    padding: 10px 12px;
    font-size: 14px;
    transition: all 0.2s ease;
    font-family: inherit;
}

input[type="text"]:focus, input[type="email"]:focus, input[type="number"]:focus,
input[type="date"]:focus, input[type="time"]:focus, textarea:focus, select:focus {
    border-color: #667eea;
    box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
    outline: none;
}

/* Badge/Label Styling */
.badge, .label {
    background: linear-gradient(135deg, #1a4a8a 0%, #0e7490 100%) !important;
    color: white;
    padding: 4px 12px;
    border-radius: 20px;
    font-size: 12px;
    font-weight: 600;
    display: inline-block;
    margin: 2px 4px;
}

/* Status Indicators */
.status-active {
    color: #28a745;
}

.status-inactive {
    color: #dc3545;
}

.status-pending {
    color: #ffc107;
}

/* Admin Notices Dismiss Button */
.notice .notice-dismiss {
    color: #666;
    opacity: 0.5;
    transition: opacity 0.2s ease;
}

.notice .notice-dismiss:hover {
    opacity: 1;
    color: #333;
}
';
        return $css;
    }

    /**
     * Lädt Skripte und Stile für das Admin-Backend.
     */
    public function simpbook_admin_skripte_laden($hook) {
        // Register shared external libraries
        wp_register_style('jquery-ui-style', plugin_dir_url(dirname(__FILE__)) . 'vendor/jquery-ui/jquery-ui.min.css', array(), SIMPBOOK_VERSION);
        
        // FullCalendar
        wp_register_style('fullcalendar', plugin_dir_url(dirname(__FILE__)) . 'vendor/fullcalendar/main.min.css', array(), SIMPBOOK_VERSION);
        wp_register_script('fullcalendar', plugin_dir_url(dirname(__FILE__)) . 'vendor/fullcalendar/main.min.js', array('jquery'), SIMPBOOK_VERSION, true);
        
        // Chart.js
        wp_register_script('chartjs', plugin_dir_url(dirname(__FILE__)) . 'vendor/chartjs/chart.min.js', array(), SIMPBOOK_VERSION, true);

        // Lade Backend-CSS für alle Admin-Seiten des Plugins
        // Hook-Format: simple-booking_page_simpbook-{submenu-slug}
        // Enthält jetzt auch alle Styles für Mitarbeiter und Dienstleistungen
        // Prüfe sowohl Hook als auch GET-Parameter für Kompatibilität
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing/filtering only
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Input validated and sanitized on use
        if (strpos($hook, 'simpbook') !== false ||
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- GET parameter for page routing/filtering only
            (isset($_GET['page']) && strpos($_GET['page'], 'simpbook-') === 0)) {
            $backend_css_path = plugin_dir_path(dirname(__FILE__)) . 'css/backend-style.css';
            $backend_version = file_exists($backend_css_path) ? filemtime($backend_css_path) : '1.0.0';
            wp_enqueue_style(
                'simpbook-backend-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/backend-style.css',
                array(),
                $backend_version
            );

            // Modern Admin CSS
            wp_add_inline_style('simpbook-backend-style', $this->simpbook_get_modern_admin_css());

            // Custom Confirm/Alert Dialog CSS und JS für alle Admin-Seiten
            wp_enqueue_style(
                'simpbook-admin-confirm-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/admin-confirm.css',
                array('simpbook-backend-style'),
                SIMPBOOK_VERSION
            );
            wp_enqueue_script(
                'simpbook-admin-confirm-script',
                plugin_dir_url(dirname(__FILE__)) . 'js/admin-confirm.js',
                array('jquery'),
                SIMPBOOK_VERSION,
                true
            );
            
            // Lokalisierung für Dialog-Buttons
            wp_localize_script(
                'simpbook-admin-confirm-script',
                'simpbookDialogConfig',
                array(
                    'buttonCancel' => __('Cancel', 'simple-appointment-booking'),
                    'buttonConfirm' => __('Confirm', 'simple-appointment-booking'),
                    'buttonOk' => __('OK', 'simple-appointment-booking'),
                )
            );
        }

        // Dashboard CSS laden
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
        if (isset($_GET['page']) && $_GET['page'] === 'simpbook-dashboard') {
            wp_enqueue_style(
                'simpbook-dashboard-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/dashboard.css',
                array('simpbook-backend-style'),
                SIMPBOOK_VERSION
            );
            wp_enqueue_script(
                'dashboard-js',
                plugin_dir_url(dirname(__FILE__)) . 'js/dashboard.js',
                array('jquery'),
                SIMPBOOK_VERSION,
                true
            );
            wp_localize_script('dashboard-js', 'simpbookDashboard', array(
                'translations' => array(
                    'copied' => __('Copied!', 'simple-appointment-booking'),
                ),
            ));
        }

        // Einstellungs-Seite JS und CSS laden
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
        $einstellungen_seiten = ['simpbook-reservierungen-einstellungen', 'simpbook-dienstleistungen-einstellungen'];
        if (isset($_GET['page']) && in_array($_GET['page'], $einstellungen_seiten, true)) {
            // Lade Einstellungs-CSS (inline version only)
            wp_enqueue_style(
                'simpbook-einstellungen-inline-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/einstellungen-inline.css',
                array('simpbook-backend-style'),
                SIMPBOOK_VERSION
            );

            // Dynamische CSS-Variablen für Einstellungen
            $dynamic_css = "
                :root {
                    --simpbook-container-bg: " . esc_html(get_option('simpbook_container_background', '#8bbce4')) . ";
                    --simpbook-text-color: " . esc_html(get_option('simpbook_text_color', '#000000')) . ";
                    --simpbook-button-color: " . esc_html(get_option('simpbook_button_color', '#2271b1')) . ";
                    --simpbook-button-hover: " . esc_html(get_option('simpbook_button_hover', '#135e96')) . ";
                    --simpbook-input-text-color: #000000;
                    --simpbook-active-color: " . esc_html(get_option('simpbook_button_color', '#2271b1')) . ";
                    --simpbook-tile-bg: " . esc_html(get_option('simpbook_tile_background', '#ffffff')) . ";
                    --simpbook-tile-text-color: " . esc_html(get_option('simpbook_tile_text_color', '#333333')) . ";
                }
            ";
            wp_add_inline_style('simpbook-einstellungen-inline-style', $dynamic_css);

            // Lade jQuery UI Datepicker
            wp_enqueue_script('jquery-ui-datepicker');
            wp_enqueue_style('jquery-ui-style');
            wp_enqueue_media();

            // Lade Einstellungs-JavaScript
            wp_enqueue_script('jquery');
            wp_enqueue_script('wp-color-picker');
            wp_enqueue_style('wp-color-picker');

            // Hole notwendige Daten für das JavaScript
            $default_map = simpbook_get_default_settings_map();
            $wochentag_zeiten = get_option('simpbook_wochentag_zeiten', $default_map['simpbook_wochentag_zeiten']);
            $current_language = simpbook_get_current_language();

            // Datepicker Übersetzungen (sprachabhängig)
            $einstellungen_month_names = simpbook_get_datepicker_month_names($current_language);
            $einstellungen_day_names   = simpbook_get_datepicker_day_names($current_language);
            $datepicker_translations = [
                'monthNames'      => $einstellungen_month_names['full'],
                'monthNamesShort' => $einstellungen_month_names['short'],
                'dayNames'        => $einstellungen_day_names['full'],
                'dayNamesShort'   => $einstellungen_day_names['short'],
                'dayNamesMin'     => $einstellungen_day_names['min'],
                'currentLanguage' => $current_language
            ];

            // Übersetzungsstrings für JavaScript
            $translations = [
                'ganzen_tag_schliessen' => __('Close Entire Day', 'simple-appointment-booking'),
                'spezielle_oeffnungszeiten' => __('Special Opening Hours', 'simple-appointment-booking'),
                'of' => __('From:', 'simple-appointment-booking'),
                'bis' => __('To:', 'simple-appointment-booking'),
                'entfernen' => __('Remove', 'simple-appointment-booking'),
                'datum_auswaehlen' => __('Please select a date first', 'simple-appointment-booking'),
                'urlaub_beide_daten_auswaehlen' => __('Please select start and end date', 'simple-appointment-booking'),
                'urlaub_enddatum_nach_startdatum' => __('Das Enddatum muss nach dem Startdatum liegen', 'simple-appointment-booking'),
                'invalid_hex_color' => __('Invalid hexadecimal color', 'simple-appointment-booking'),
            ];

            wp_enqueue_script(
                'simpbook-einstellungen-script',
                plugin_dir_url(dirname(__FILE__)) . 'js/einstellungen.js',
                array('jquery', 'jquery-ui-datepicker', 'wp-color-picker'),
                SIMPBOOK_VERSION,
                true
            );

            wp_localize_script(
                'simpbook-einstellungen-script',
                'SimpleBookingEinstellungen',
                [
                    'simpbookTranslations' => $translations,
                    'simpbookDatepickerTranslations' => $datepicker_translations,
                    'urlaubDates' => simpbook_expand_urlaub_dates(),
                    'wochentagZeitenSettings' => $wochentag_zeiten,
                    // WICHTIG: Reihenfolge muss mit date.getDay() übereinstimmen: 0=Sonntag, 1=Montag, etc.
                    'wochentagKeysSettings' => ['sonntag', 'montag', 'dienstag', 'mittwoch', 'donnerstag', 'freitag', 'samstag'],
                    'currentLanguage' => $current_language,
                    'ajaxUrl' => admin_url('admin-ajax.php'),
                    'nonces' => [
                        'simpbook_email_templates_nonce' => wp_create_nonce('simpbook_email_templates_nonce'),
                    ]
                ]
            );
        }

        // Mitarbeiter bearbeiten Seite CSS und JS laden
        $is_mitarbeiter_page = (isset($_GET['page']) && $_GET['page'] === 'simpbook-mitarbeiter'); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
        $aktion = isset($_GET['simpbook_aktion']) ? sanitize_text_field(wp_unslash($_GET['simpbook_aktion'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
        $id = isset($_GET['simpbook_id']) ? intval($_GET['simpbook_id']) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only

        // Debug: Prüfe Bedingungen für Mitarbeiter-JS
        $debug_load_js = $is_mitarbeiter_page && ($aktion === 'bearbeiten' || $aktion === '' || $id > 0);
        // Disabled for production
        // if (defined('WP_DEBUG') && WP_DEBUG) {
        //     error_log('PocketBooking Debug - Mitarbeiter JS Load:');
        //     error_log('is_mitarbeiter_page: ' . ($is_mitarbeiter_page ? 'true' : 'false'));
        //     error_log('aktion: "' . $aktion . '"');
        //     error_log('id: ' . $id);
        //     error_log('aktion === bearbeiten: ' . ($aktion === 'bearbeiten' ? 'true' : 'false'));
        //     error_log('aktion === empty: ' . ($aktion === '' ? 'true' : 'false'));
        //     error_log('id > 0: ' . ($id > 0 ? 'true' : 'false'));
        //     error_log('Will load JS: ' . ($debug_load_js ? 'true' : 'false'));
        // }

        if ($debug_load_js) {
            $mitarbeiter_bearbeiten_css_path = plugin_dir_path(dirname(__FILE__)) . 'css/mitarbeiter-bearbeiten.css';
            $mitarbeiter_bearbeiten_css_version = file_exists($mitarbeiter_bearbeiten_css_path) ? filemtime($mitarbeiter_bearbeiten_css_path) : '1.0.0';
            
            wp_enqueue_style(
                'simpbook-mitarbeiter-bearbeiten-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/mitarbeiter-bearbeiten.css',
                array('simpbook-backend-style'),
                $mitarbeiter_bearbeiten_css_version
            );
            wp_enqueue_media();
            wp_enqueue_script('jquery');

            // Lokalisierung für Übersetzungen
            $current_language = simpbook_get_current_language();
            $mitarbeiter_month_names = simpbook_get_datepicker_month_names($current_language);
            $mitarbeiter_day_names   = simpbook_get_datepicker_day_names($current_language);
            $datepicker_translations = [
                'monthNames'      => $mitarbeiter_month_names['full'],
                'monthNamesShort' => $mitarbeiter_month_names['short'],
                'dayNames'        => $mitarbeiter_day_names['full'],
                'dayNamesShort'   => $mitarbeiter_day_names['short'],
                'dayNamesMin'     => $mitarbeiter_day_names['min'],
                'currentLanguage' => $current_language
            ];

            $mitarbeiter_bearbeiten_js_path = plugin_dir_path(dirname(__FILE__)) . 'js/mitarbeiter-bearbeiten.js';
            $mitarbeiter_bearbeiten_js_version = file_exists($mitarbeiter_bearbeiten_js_path) ? filemtime($mitarbeiter_bearbeiten_js_path) : '1.0.0';

            wp_enqueue_script(
                'simpbook-mitarbeiter-bearbeiten-script',
                plugin_dir_url(dirname(__FILE__)) . 'js/mitarbeiter-bearbeiten.js',
                array('jquery'),
                $mitarbeiter_bearbeiten_js_version,
                true
            );

            wp_localize_script(
                'simpbook-mitarbeiter-bearbeiten-script',
                'simpbookMitarbeiterBearbeiten',
                [
                    'simpbookDatepickerTranslations' => $datepicker_translations,
                    'uploadFotoTitle' => __('Select profile photo', 'simple-appointment-booking'),
                    'uploadFotoButton' => __('Verwenden', 'simple-appointment-booking'),
                    'invalidIdMessage' => __('Invalid staff member ID', 'simple-appointment-booking'),
                    'errorTitle' => __('Error', 'simple-appointment-booking'),
                    'confirmDeleteMessage' => __('Do you really want to delete this employee?', 'simple-appointment-booking'),
                    'confirmTitle' => __('Confirmation', 'simple-appointment-booking'),
                    'deleteErrorMessage' => __('Error deleting the staff member.', 'simple-appointment-booking'),
                    'unknownErrorMessage' => __('Ein unbekannter Fehler ist aufgetreten.', 'simple-appointment-booking'),
                    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing/filtering only
                    'mitarbeiterId' => isset($_GET['simpbook_id']) ? intval($_GET['simpbook_id']) : 0,
                    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing/filtering only
                    'deleteNonce' => isset($_GET['simpbook_id']) ? wp_create_nonce('simpbook_delete_mitarbeiter_' . intval($_GET['simpbook_id'])) : '',
                    'redirectUrl' => admin_url('admin.php?page=simpbook-mitarbeiter&simpbook_nachricht=geloescht'),
                    // PWA App-Zugang Nonce
                    'appEmailNonce' => wp_create_nonce('simpbook_app_email_nonce'),
                ]
            );
        }

        // Neue Reservierung Seite CSS und JS laden
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
        if (isset($_GET['page']) && $_GET['page'] === 'simpbook-reservierungen-neu') {
            $simpbook_neue_reservierung_css_path = plugin_dir_path(dirname(__FILE__)) . 'css/neue-reservierung.css';
            $simpbook_neue_reservierung_css_version = file_exists($simpbook_neue_reservierung_css_path) ? filemtime($simpbook_neue_reservierung_css_path) : '1.0.0';
            
            wp_enqueue_style(
                'simpbook-neue-reservierung-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/neue-reservierung.css',
                array('simpbook-backend-style'),
                $simpbook_neue_reservierung_css_version
            );

            // Dynamische CSS-Variablen
            $dynamic_css = "
                :root {
                    --simpbook-container-bg: " . esc_html(get_option('simpbook_container_background', '#8bbce4')) . ";
                    --simpbook-text-color: " . esc_html(get_option('simpbook_text_color', '#000000')) . ";
                    --simpbook-button-color: " . esc_html(get_option('simpbook_button_color', '#2271b1')) . ";
                    --simpbook-button-hover: " . esc_html(get_option('simpbook_button_hover', '#135e96')) . ";
                    --simpbook-input-text-color: #000000;
                    --simpbook-active-color: " . esc_html(get_option('simpbook_button_color', '#2271b1')) . ";
                }
            ";
            wp_add_inline_style('simpbook-neue-reservierung-style', $dynamic_css);

            wp_enqueue_script('jquery-ui-datepicker');
            wp_enqueue_style('jquery-ui-style');

            // Datepicker-Farbregeln nach jQuery UI injizieren
            $datepicker_color_css = "
                .ui-datepicker td.urlaub-gesperrt-tag span.ui-state-default,
                .ui-datepicker td.urlaub-gesperrt-tag a.ui-state-default {
                    background: #fff3e0 !important;
                    border-color: #ffb74d !important;
                    color: #e65100 !important;
                    cursor: not-allowed !important;
                    opacity: 1 !important;
                }
                .ui-datepicker td.speziell-geschlossen-tag span.ui-state-default,
                .ui-datepicker td.speziell-geschlossen-tag a.ui-state-default {
                    background: #fce4e4 !important;
                    border-color: #e57373 !important;
                    color: #c62828 !important;
                    cursor: not-allowed !important;
                    opacity: 1 !important;
                }
                .ui-datepicker td.deaktivierter-wochentag span.ui-state-default,
                .ui-datepicker td.deaktivierter-wochentag a.ui-state-default {
                    background: #f5f5f5 !important;
                    border-color: #ddd !important;
                    color: #bbb !important;
                    cursor: not-allowed !important;
                    opacity: 1 !important;
                }
            ";
            wp_add_inline_style('jquery-ui-style', $datepicker_color_css);

            $simpbook_neue_reservierung_js_path = plugin_dir_path(dirname(__FILE__)) . 'js/neue-reservierung.js';
            $simpbook_neue_reservierung_js_version = file_exists($simpbook_neue_reservierung_js_path) ? filemtime($simpbook_neue_reservierung_js_path) : '1.0.0';

            wp_enqueue_script(
                'simpbook-neue-reservierung-script',
                plugin_dir_url(dirname(__FILE__)) . 'js/neue-reservierung.js',
                array('jquery', 'jquery-ui-datepicker'),
                $simpbook_neue_reservierung_js_version,
                true
            );

            // Daten vorbereiten
            $current_language = simpbook_get_current_language();
            $month_names = simpbook_get_datepicker_month_names($current_language);
            $day_names = simpbook_get_datepicker_day_names($current_language);
            
            // Wochentage und Zeiten aus der Datenbank laden
            // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
            $default_map = simpbook_get_default_settings_map();
            $wochentag_zeiten = get_option('simpbook_wochentag_zeiten', $default_map['simpbook_wochentag_zeiten']);
            
            $intervall = intval(get_option('simpbook_intervall', 30));
            $ausgeschlossene_tage = get_option('simpbook_ausgeschlossene_tage', '');
            $ausgeschlossene_tage_array = [];
            if (!empty($ausgeschlossene_tage)) {
                $ausgeschlossene_tage_array = array_map('trim', explode(',', $ausgeschlossene_tage));
            }
            $simpbook_urlaub_dates_nr = simpbook_expand_urlaub_dates();
            if (!empty($simpbook_urlaub_dates_nr)) {
                $ausgeschlossene_tage_array = array_values(array_unique(array_merge($ausgeschlossene_tage_array, $simpbook_urlaub_dates_nr)));
            }
            
            // Datepicker Format bestimmen
            $datepicker_date_format = 'dd.mm.yy'; // Standard (Deutsch/Europäisch)
            if ($current_language === 'en_US_AMPM' || $current_language === 'en_US') {
                $datepicker_date_format = 'mm/dd/yy'; // US Format
            }

            // Spezielle Tage-Konfiguration laden
            $default_map = simpbook_get_default_settings_map();
            $spezielle_tage_konfiguration = simpbook_get_option('simpbook_spezielle_tage_konfiguration', $default_map['simpbook_spezielle_tage_konfiguration']);
            // phpcs:enable

            wp_localize_script('simpbook-neue-reservierung-script', 'simpbookNeueReservierungData', array(
                'ajax_url' => admin_url('admin-ajax.php'),
                'times_nonce' => wp_create_nonce('simpbook_get_available_times_nonce'),
                'mitarbeiter_nonce' => wp_create_nonce('simpbook_mitarbeiter_nonce'),
                'buchungsoptionenAktiv' => get_option('simpbook_buchungsoptionen_aktiv', '0') === '1',
                'wochentag_zeiten' => $wochentag_zeiten,
                'intervall' => $intervall,
                'ausgeschlossene_tage' => $ausgeschlossene_tage_array,
                'urlaub_tage' => simpbook_expand_urlaub_dates(),
                'spezielle_tage_konfiguration' => $spezielle_tage_konfiguration,
                'dateFormat' => $datepicker_date_format,
                'datepicker_translations' => array(
                    'monthNames' => $month_names['full'],
                    'monthNamesShort' => $month_names['short'],
                    'dayNames' => $day_names['full'],
                    'dayNamesShort' => $day_names['short'],
                    'dayNamesMin' => $day_names['min'],
                    'currentLanguage' => $current_language
                ),
                'translations' => array(
                    'uhrzeit_waehlen' => __('Select time', 'simple-appointment-booking'),
                    'keine_reservierungen_an_diesem_tag' => __('Keine Reservierungen an diesem Tag', 'simple-appointment-booking'),
                    'mitarbeiter_waehlen' => __('Select staff member', 'simple-appointment-booking'),
                    'diese_dienstleistung_wird_nur_an_folgenden_tagen_angeboten' => __('This service is only offered on the following days:', 'simple-appointment-booking'),
                    'bitte_zuerst_datum_und_dienstleistung_auswaehlen' => __('-- Please select date and service --', 'simple-appointment-booking'),
                    'lade_verfuegbare_zeiten' => __('Loading available times...', 'simple-appointment-booking'),
                    'fehler_beim_laden' => __('Error loading', 'simple-appointment-booking'),
                    'fehler_beim_laden_der_zeiten' => __('Fehler beim Laden der Zeiten', 'simple-appointment-booking'),
                    'kein_bestimmter_mitarbeiter' => __('No Specific Staff Member', 'simple-appointment-booking'),
                    'keine_mitarbeiter_verfuegbar' => __('No staff available', 'simple-appointment-booking'),
                    'fehler_beim_laden_der_mitarbeiter' => __('Fehler beim Laden der Mitarbeiter', 'simple-appointment-booking'),
                    'bitte_zuerst_dienstleistung_auswaehlen' => __('Please select a service first', 'simple-appointment-booking'),
                    'buchungsoption_waehlen' => __('Choose Booking Option', 'simple-appointment-booking')
                )
            ));
        }

        // Setup Wizard CSS laden
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
        if (isset($_GET['page']) && ($_GET['page'] === 'simpbook-reservierungen' || $_GET['page'] === 'simpbook-dashboard') && isset($_GET['simpbook_wizard'])) {
            $setup_wizard_css_path = plugin_dir_path(dirname(__FILE__)) . 'css/setup-wizard.css';
            $setup_wizard_css_version = file_exists($setup_wizard_css_path) ? filemtime($setup_wizard_css_path) : '1.0.0';
            
            wp_enqueue_style(
                'simpbook-setup-wizard-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/setup-wizard.css',
                array('simpbook-backend-style'),
                $setup_wizard_css_version
            );

            $setup_wizard_js_path = plugin_dir_path(dirname(__FILE__)) . 'js/setup-wizard.js';
            $setup_wizard_js_version = file_exists($setup_wizard_js_path) ? filemtime($setup_wizard_js_path) : '1.0.0';

            wp_enqueue_script(
                'simpbook-setup-wizard-js',
                plugin_dir_url(dirname(__FILE__)) . 'js/setup-wizard.js',
                array('jquery'),
                $setup_wizard_js_version,
                true
            );

            // Lokalisierung für Setup Wizard
            $current_language = simpbook_get_current_language();
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
            $current_page_for_js = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : 'simpbook-dashboard';

            wp_localize_script('simpbook-setup-wizard-js', 'simpbookSetupWizardData', array(
                'currentLanguage' => $current_language,
                // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for display control only
                'showResetSuccess' => (isset($_GET['simpbook_reset']) && $_GET['simpbook_reset'] === 'success'),
                'resetUrl' => admin_url('admin.php?page=' . $current_page_for_js . '&simpbook_wizard=1&simpbook_step=1&simpbook_reset_step=1&simpbook_nonce=' . wp_create_nonce('simpbook_wizard_reset_step_1')),
                'translations' => array(
                    'resetSuccess' => __('Settings have been reset.', 'simple-appointment-booking'),
                    'confirmResetMessage' => __('Do you really want to reset all fields in this step?', 'simple-appointment-booking'),
                    'confirmResetTitle' => __('Confirmation', 'simple-appointment-booking'),
                )
            ));
        }

        // CSS und JS für Kalender-Seite
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters for page routing only
        if (strpos($hook, 'simpbook-kalender') !== false || (isset($_GET['page']) && $_GET['page'] === 'simpbook-kalender')) {
            // Wochentage und Zeiten aus der Datenbank laden für Kalender
            $default_map = simpbook_get_default_settings_map();
            $wochentag_zeiten = get_option('simpbook_wochentag_zeiten', $default_map['simpbook_wochentag_zeiten']);
            
            // FullCalendar CSS laden
            wp_enqueue_style('fullcalendar');

            wp_enqueue_style(
                'simpbook-kalender-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/kalender.css',
                array('simpbook-backend-style', 'fullcalendar'),
                SIMPBOOK_VERSION
            );

            wp_enqueue_style(
                'simpbook-kalender-modal-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/kalender-modal.css',
                array('simpbook-kalender-style'),
                SIMPBOOK_VERSION
            );

            // FullCalendar JS laden
            $plugin_language = simpbook_get_current_language();
            $fc_locale = explode('_', $plugin_language)[0];

            wp_enqueue_script('fullcalendar');

            // Kalender-Script laden
            wp_enqueue_script(
                'simpbook-kalender-js',
                plugin_dir_url(dirname(__FILE__)) . 'js/kalender.js',
                array('jquery', 'fullcalendar'),
                SIMPBOOK_VERSION,
                true
            );

            // PWA-Modus prüfen für URLs
            $is_pwa = simpbook_is_pwa_mode();
            $base_url = $is_pwa 
                ? admin_url('admin.php?page=simpbook-kalender&pwa=1')
                : admin_url('admin.php?page=simpbook-kalender');
            $edit_url = $is_pwa
                ? admin_url('admin.php?page=simpbook-reservierungen&pwa=1&simpbook_aktion=bearbeiten')
                : admin_url('admin.php?page=simpbook-reservierungen&simpbook_aktion=bearbeiten');

            // Lokalisierung für JavaScript
            wp_localize_script('simpbook-kalender-js', 'simpbookKalender', array(
                'ajaxUrl' => admin_url('admin-ajax.php'),
                'baseUrl' => $base_url,
                'editUrl' => $edit_url,
                'isPwa' => $is_pwa,
                'fcLocale' => $fc_locale,
                'currentLanguage' => $plugin_language,
                'wochentag_zeiten' => $wochentag_zeiten,
                'detailsNonce' => wp_create_nonce('simpbook_reservierung_details_nonce'),
                'eventsNonce' => wp_create_nonce('simpbook_calendar_events_nonce'),
                'tokenNonce' => wp_create_nonce('simpbook_calendar_token'),
                'updateMitarbeiterNonce' => wp_create_nonce('simpbook_update_mitarbeiter_nonce'),
                'alleMitarbeiter' => simpbook_get_all_mitarbeiter(false, false),
                'translations' => array(
                    'confirmation' => __('Confirmation', 'simple-appointment-booking'),
                    'error' => __('Error', 'simple-appointment-booking'),
                    'errorStatusChange' => __('Error changing status', 'simple-appointment-booking'),
                    'generalError' => __('An error occurred', 'simple-appointment-booking'),
                    'errorDeleteReservation' => __('Error deleting the reservation', 'simple-appointment-booking'),
                    'errorLoadingDetails' => __('Fehler beim Laden der Details', 'simple-appointment-booking'),
                    'ausstehend' => __('Pending', 'simple-appointment-booking'),
                    'bestaetigt' => __('Confirmed', 'simple-appointment-booking'),
                    'abgelehnt' => __('Rejected', 'simple-appointment-booking'),
                    'storniert' => __('Cancelled', 'simple-appointment-booking'),
                    'contactInfo' => __('Contact', 'simple-appointment-booking'),
                    'name' => __('Name:', 'simple-appointment-booking'),
                    'email' => __('Email:', 'simple-appointment-booking'),
                    'phone' => __('Phone:', 'simple-appointment-booking'),
                    'appointment' => __('Appointment', 'simple-appointment-booking'),
                    'date' => __('Date:', 'simple-appointment-booking'),
                    'time' => __('Time:', 'simple-appointment-booking'),
                    'service' => __('Service', 'simple-appointment-booking'),
                    'serviceType' => __('Service:', 'simple-appointment-booking'),
                    'employee' => __('Staff:', 'simple-appointment-booking'),
                    'noSpecificEmployee' => __('No Specific Staff Member', 'simple-appointment-booking'),
                    'saved' => __('Saved', 'simple-appointment-booking'),
                    'message' => __('Message', 'simple-appointment-booking'),
                    'none' => __('None', 'simple-appointment-booking'),
                    'statusAndActions' => __('Status & Actions', 'simple-appointment-booking'),
                    'currentStatus' => __('Current Status:', 'simple-appointment-booking'),
                    'at' => __('at:', 'simple-appointment-booking'),
                    'atTime' => __('at', 'simple-appointment-booking'),
                    'confirm' => __('Confirm', 'simple-appointment-booking'),
                    'reject' => __('Reject', 'simple-appointment-booking'),
                    'cancel' => __('Cancel', 'simple-appointment-booking'),
                    'edit' => __('Edit', 'simple-appointment-booking'),
                    'sendMessage' => __('Send Message', 'simple-appointment-booking'),
                    'delete' => __('Delete', 'simple-appointment-booking'),
                    'confirmBooking' => __('Would you like to confirm this booking?', 'simple-appointment-booking'),
                    'rejectBooking' => __('Would you like to reject this booking?', 'simple-appointment-booking'),
                    'cancelBooking' => __('Would you like to cancel this booking?', 'simple-appointment-booking'),
                    'confirmDelete' => __('Would you like to delete this booking?', 'simple-appointment-booking'),
                    'messageSent' => __('Message sent successfully!', 'simple-appointment-booking'),
                    'success' => __('Erfolg', 'simple-appointment-booking'),
                    'sending' => __('Sende...', 'simple-appointment-booking'),
                    'errorColon' => __('Fehler: ', 'simple-appointment-booking'),
                    'generalErrorRetry' => __('An error occurred. Please try again.', 'simple-appointment-booking'),
                    'errorGenerateUrl' => __('Error generating URL', 'simple-appointment-booking'),
                    'confirmDeleteToken' => __('Do you really want to delete the token? All calendar links created with this token will become invalid.', 'simple-appointment-booking'),
                    'tokenDeleted' => __('Token successfully deleted', 'simple-appointment-booking'),
                    'errorDeleteToken' => __('Error deleting token', 'simple-appointment-booking'),
                    /* translators: %s: Number of additional items */
                    'moreLinkText' => __('+%s more', 'simple-appointment-booking'),
                ),
                'buttonText' => array(
                    'today' => __('Today', 'simple-appointment-booking'),
                    'month' => __('Month', 'simple-appointment-booking'),
                    'week' => __('Week', 'simple-appointment-booking'),
                    'day' => __('Day', 'simple-appointment-booking'),
                ),
                'instructions' => array(
                    'google' => __('Google Calendar: Click the "+" next to "Other calendars", select "Add by URL" and paste the URL.', 'simple-appointment-booking'),
                    'outlook' => __('Outlook: Go to Calendar > Add Calendar > Subscribe from Internet and paste the URL.', 'simple-appointment-booking'),
                    'thunderbird' => __('Thunderbird: Go to Calendar > New Calendar > On the Network and paste the URL.', 'simple-appointment-booking'),
                    'apple' => __('Apple Calendar: Go to Calendar > Add Subscription and paste the URL.', 'simple-appointment-booking'),
                ),
            ));
        }

        // CSS für Statistiken-Seite (Hook oder GET-Parameter prüfen)
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters for page routing only
        if (strpos($hook, 'simpbook-statistiken') !== false || (isset($_GET['page']) && $_GET['page'] === 'simpbook-statistiken')) {
            wp_enqueue_style(
                'simpbook-statistiken-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/statistiken.css',
                array('simpbook-backend-style'),
                SIMPBOOK_VERSION
            );

            // Chart.js laden
            wp_enqueue_script('chartjs');

            // Statistiken JS laden
            $statistiken_js_path = plugin_dir_path(dirname(__FILE__)) . 'js/statistiken.js';
            $statistiken_js_version = file_exists($statistiken_js_path) ? filemtime($statistiken_js_path) : '1.0.0';

            wp_enqueue_script(
                'simpbook-statistiken-js',
                plugin_dir_url(dirname(__FILE__)) . 'js/statistiken.js',
                array('jquery', 'chartjs'),
                $statistiken_js_version,
                true
            );

            // Daten für Statistiken vorbereiten
            global $wpdb;
            $tabellen_name = $wpdb->prefix . 'buchungen';
            // Zeitraum-Filter (Standard: Von heute bis +30 Tage)
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for filter only
            $filter_start = isset($_GET['simpbook_filter_start']) ? sanitize_text_field(wp_unslash($_GET['simpbook_filter_start'])) : wp_date('Y-m-d');
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for filter only
            $filter_end = isset($_GET['simpbook_filter_end']) ? sanitize_text_field(wp_unslash($_GET['simpbook_filter_end'])) : wp_date('Y-m-d', strtotime('now +30 days'));

            // Buchungen pro Dienstleistung
            $buchungen_pro_dienstleistung = $wpdb->get_results($wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
                "SELECT dienstleistung_id, COUNT(*) as anzahl
                FROM %i 
                WHERE datum >= %s AND datum <= %s AND storniert = 0
                GROUP BY dienstleistung_id
                ORDER BY anzahl DESC
                LIMIT 10",
                $tabellen_name, $filter_start, $filter_end
            ));

            // Buchungen pro Mitarbeiter
            $buchungen_pro_mitarbeiter = $wpdb->get_results($wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
                 "SELECT mitarbeiter_id, COUNT(*) as anzahl
                FROM %i
                WHERE datum >= %s AND datum <= %s AND storniert = 0 AND mitarbeiter_id IS NOT NULL
                GROUP BY mitarbeiter_id
                ORDER BY anzahl DESC",
                $tabellen_name, $filter_start, $filter_end
            ));

            // Buchungen pro Tag (für Chart)
            $buchungen_pro_tag = $wpdb->get_results($wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
             "SELECT DATE(datum) as tag, COUNT(*) as anzahl
                FROM %i
                WHERE datum >= %s AND datum <= %s AND storniert = 0
                GROUP BY DATE(datum)
                ORDER BY tag ASC",
                $tabellen_name, $filter_start, $filter_end
            ));

            // Daten für JS formatieren
            $service_labels = [];
            $service_values = [];
            foreach ($buchungen_pro_dienstleistung as $item) {
                $dienstleistung = simpbook_get_dienstleistung($item->dienstleistung_id);
                if ($dienstleistung) {
                    $service_labels[] = simpbook_format_dienstleistung_name_with_kategorie($dienstleistung);
                    $service_values[] = $item->anzahl;
                }
            }

            $employee_labels = [];
            $employee_values = [];
            foreach ($buchungen_pro_mitarbeiter as $item) {
                $mitarbeiter = simpbook_get_mitarbeiter($item->mitarbeiter_id);
                if ($mitarbeiter) {
                    $employee_labels[] = $mitarbeiter->name;
                    $employee_values[] = $item->anzahl;
                }
            }

            $day_labels = [];
            $day_values = [];
            foreach ($buchungen_pro_tag as $item) {
                $date_obj = new DateTime($item->tag);
                $day_labels[] = $date_obj->format('d.m.Y');
                $day_values[] = $item->anzahl;
            }

            $js_data = array(
                'bookingsPerDay' => array(
                    'labels' => $day_labels,
                    'values' => $day_values,
                    'label' => __('Bookings', 'simple-appointment-booking')
                ),
                'bookingsPerService' => array(
                    'labels' => $service_labels,
                    'values' => $service_values,
                    'label' => __('Bookings', 'simple-appointment-booking')
                ),
                'bookingsPerEmployee' => !empty($buchungen_pro_mitarbeiter) ? array(
                    'labels' => $employee_labels,
                    'values' => $employee_values,
                    'label' => __('Bookings', 'simple-appointment-booking')
                ) : null
            );

            wp_localize_script('simpbook-statistiken-js', 'simpbookStatistikenData', $js_data);
        }

        // CSS für Dienstleistungen-Seite (Hook oder GET-Parameter prüfen)
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters for page routing only
        if (strpos($hook, 'simpbook-dienstleistungen') !== false || (isset($_GET['page']) && $_GET['page'] === 'simpbook-dienstleistungen')) {
            wp_enqueue_style(
                'simpbook-dienstleistungen-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/dienstleistungen.css',
                array('simpbook-backend-style'),
                SIMPBOOK_VERSION
            );
            // Dynamische CSS-Variablen (gleich wie neue-reservierung, damit Datepicker die Plugin-Farben übernimmt)
            $simpbook_dl_dynamic_css = "
                :root {
                    --simpbook-container-bg: " . esc_html(get_option('simpbook_container_background', '#8bbce4')) . ";
                    --simpbook-text-color: " . esc_html(get_option('simpbook_text_color', '#000000')) . ";
                    --simpbook-button-color: " . esc_html(get_option('simpbook_button_color', '#2271b1')) . ";
                }
            ";
            wp_add_inline_style('simpbook-dienstleistungen-style', $simpbook_dl_dynamic_css);
            // Lade Media-Library für Bild-Upload
            wp_enqueue_media();
            // JavaScript für Dienstleistungen-Seite einbinden
            wp_enqueue_script(
                'simpbook-dienstleistungen-js',
                plugin_dir_url(dirname(__FILE__)) . 'js/dienstleistungen.js',
                array('jquery', 'jquery-ui-sortable', 'jquery-ui-datepicker'),
                SIMPBOOK_VERSION,
                true
            );

            $simpbook_dl_current_lang  = simpbook_get_current_language();
            $simpbook_dl_month_names  = simpbook_get_datepicker_month_names($simpbook_dl_current_lang);
            $simpbook_dl_day_names    = simpbook_get_datepicker_day_names($simpbook_dl_current_lang);
            // Build excluded dates array for the availability datepicker
            $simpbook_dl_ausgeschlossene_raw = get_option('simpbook_ausgeschlossene_tage', '');
            $simpbook_dl_ausgeschlossene = array();
            if (!empty($simpbook_dl_ausgeschlossene_raw)) {
                $simpbook_dl_ausgeschlossene = array_values(array_filter(array_map('trim', explode(',', $simpbook_dl_ausgeschlossene_raw))));
            }
            $simpbook_dl_urlaub_dates = simpbook_expand_urlaub_dates();
            if (!empty($simpbook_dl_urlaub_dates)) {
                $simpbook_dl_ausgeschlossene = array_values(array_unique(array_merge($simpbook_dl_ausgeschlossene, $simpbook_dl_urlaub_dates)));
            }
            // Build special fully-closed dates (Feiertage/Spezielle Öffnungszeiten, Status=geschlossen)
            $simpbook_dl_spezielle_cfg = simpbook_get_option('simpbook_spezielle_tage_konfiguration', array());
            $simpbook_dl_spezielle_schliesstage = array();
            if (is_array($simpbook_dl_spezielle_cfg)) {
                foreach ($simpbook_dl_spezielle_cfg as $simpbook_dl_datum => $simpbook_dl_cfg) {
                    if (isset($simpbook_dl_cfg['status']) && $simpbook_dl_cfg['status'] === 'geschlossen') {
                        $simpbook_dl_spezielle_schliesstage[] = $simpbook_dl_datum;
                    }
                }
            }
            // Build closed weekdays array for the availability datepicker
            $simpbook_dl_wochentag_zeiten = get_option('simpbook_wochentag_zeiten', array());
            $simpbook_dl_geschlossene_wochentage = array();
            $simpbook_dl_tag_keys = array('montag','dienstag','mittwoch','donnerstag','freitag','samstag','sonntag');
            foreach ($simpbook_dl_tag_keys as $simpbook_dl_key) {
                if (isset($simpbook_dl_wochentag_zeiten[$simpbook_dl_key]['aktiv']) && !$simpbook_dl_wochentag_zeiten[$simpbook_dl_key]['aktiv']) {
                    $simpbook_dl_geschlossene_wochentage[] = $simpbook_dl_key;
                }
            }
            wp_localize_script('simpbook-dienstleistungen-js', 'simpbookDienstleistungenData', array(
                'ajaxurl' => admin_url('admin-ajax.php'),
                'reorderNonce' => wp_create_nonce('simpbook_reorder_dienstleistungen'),
                'ausgeschlosseneTage' => $simpbook_dl_ausgeschlossene,
                'spezielleSchliesstage' => $simpbook_dl_spezielle_schliesstage,
                'geschlosseneWochentage' => $simpbook_dl_geschlossene_wochentage,
                'buchungsoptionenAktiv' => get_option('simpbook_buchungsoptionen_aktiv', '0') === '1' ? true : false,
                'currentLanguage' => $simpbook_dl_current_lang,
                'datepickerTranslations' => array(
                    'monthNames'      => $simpbook_dl_month_names['full'],
                    'monthNamesShort' => $simpbook_dl_month_names['short'],
                    'dayNames'        => $simpbook_dl_day_names['full'],
                    'dayNamesShort'   => $simpbook_dl_day_names['short'],
                    'dayNamesMin'     => $simpbook_dl_day_names['min'],
                ),
                'manageOptionenUrl' => admin_url('admin.php?page=simpbook-buchungsoptionen'),
                'i18n' => array(
                    'error_loading_employees' => __('Fehler beim Laden der Mitarbeiter', 'simple-appointment-booking'),
                    'error_occurred' => __('An error occurred', 'simple-appointment-booking'),
                    'error_modal_not_found' => __('Fehler: Modal-Element nicht gefunden', 'simple-appointment-booking'),
                    'error_title' => __('Error', 'simple-appointment-booking'),
                    'select_image' => __('Select Image', 'simple-appointment-booking'),
                    'use_image' => __('Verwenden', 'simple-appointment-booking'),
                    'error_saving' => __('Fehler beim Speichern der Dienstleistung.', 'simple-appointment-booking'),
                    'unknown_error' => __('Ein unbekannter Fehler ist aufgetreten.', 'simple-appointment-booking'),
                    'select_service_first' => __('Please select a service first.', 'simple-appointment-booking'),
                    'security_token_missing' => __('Sicherheitstoken nicht gefunden. Bitte laden Sie die Seite neu.', 'simple-appointment-booking'),
                    'confirm_delete' => __('Do you really want to delete this service?', 'simple-appointment-booking'),
                    'confirmation_title' => __('Confirmation', 'simple-appointment-booking'),
                    'card_view' => __('Card View', 'simple-appointment-booking'),
                    'table_view' => __('Table View', 'simple-appointment-booking'),
                    'error_deleting' => __('Error deleting the service.', 'simple-appointment-booking'),
                    'add_new_service' => __('Add New Service', 'simple-appointment-booking'),
                    'edit_service' => __('Edit Service', 'simple-appointment-booking'),
                    'add_service' => __('Add Service', 'simple-appointment-booking'),
                    'save' => __('Save', 'simple-appointment-booking'),
                    'loading_employees' => __('Loading staff...', 'simple-appointment-booking'),
                    'option_hinzufuegen' => __('Add Option', 'simple-appointment-booking'),
                    'keine_optionen' => __('No booking options available. Please create options first.', 'simple-appointment-booking'),
                    'option_auswaehlen' => __('— Select Option —', 'simple-appointment-booking'),
                    'preis_placeholder' => __('e.g. 49.99', 'simple-appointment-booking'),
                    'optionen_verwalten' => __('Manage Options', 'simple-appointment-booking'),
                    'error_loading_optionen' => __('Fehler beim Laden der Buchungsoptionen.', 'simple-appointment-booking'),
                )
            ));
        }

        // CSS für Gruppierungen/Kategorien-Seite
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters for page routing only
        if (strpos($hook, 'simpbook-gruppierungen') !== false || (isset($_GET['page']) && $_GET['page'] === 'simpbook-gruppierungen')) {
            wp_enqueue_style(
                'simpbook-gruppierungen-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/gruppierungen.css',
                array('simpbook-backend-style'),
                SIMPBOOK_VERSION
            );
            // JavaScript für Gruppierungen-Seite einbinden
            wp_enqueue_script(
                'simpbook-gruppierungen-js',
                plugin_dir_url(dirname(__FILE__)) . 'js/gruppierungen.js',
                array('jquery', 'simpbook-admin-confirm-script'),
                SIMPBOOK_VERSION,
                true
            );

            wp_localize_script('simpbook-gruppierungen-js', 'simpbookGruppierungenL10n', array(
                'ajaxurl' => admin_url('admin-ajax.php'),
                'newTitle' => __('New Category', 'simple-appointment-booking'),
                'editTitle' => __('Edit Category', 'simple-appointment-booking'),
                'deleteTitle' => __('Delete Category', 'simple-appointment-booking'),
                'confirmDeleteQuestion' => __('Are you sure you want to delete the category "{name}"?', 'simple-appointment-booking'),
                'confirmDeleteSimple' => __('Do you really want to delete the category "{name}"?', 'simple-appointment-booking'),
                'oneServiceConnected' => __('There is still <strong>1 service</strong> associated with this category:', 'simple-appointment-booking'),
                'multipleServicesConnected' => __('There are still <strong>{count} services</strong> associated with this category:', 'simple-appointment-booking'),
                'servicesNotDeleted' => __('The services will not be deleted, only the category assignment will be removed.', 'simple-appointment-booking'),
            ));
        }

        // CSS/JS für Buchungsoptionen-Seite
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
        if (isset($_GET['page']) && $_GET['page'] === 'simpbook-buchungsoptionen') {
            wp_enqueue_style(
                'simpbook-buchungsoptionen-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/gruppierungen.css',
                array('simpbook-backend-style'),
                SIMPBOOK_VERSION
            );
            wp_enqueue_script(
                'simpbook-buchungsoptionen-js',
                plugin_dir_url(dirname(__FILE__)) . 'js/buchungsoptionen.js',
                array('jquery', 'simpbook-admin-confirm-script'),
                SIMPBOOK_VERSION,
                true
            );
            wp_localize_script('simpbook-buchungsoptionen-js', 'simpbookBuchungsoptionen', array(
                'ajaxurl'     => admin_url('admin-ajax.php'),
                'pageUrl'     => admin_url('admin.php?page=simpbook-buchungsoptionen'),
                'deleteNonce' => wp_create_nonce('simpbook_delete_buchungsoption'),
                'i18n'        => array(
                    'neueoption'         => __('New Option', 'simple-appointment-booking'),
                    'bearbeiten'         => __('Edit Option', 'simple-appointment-booking'),
                    'loeschenBestaetigen' => __('Really delete booking option? All prices in services will also be removed.', 'simple-appointment-booking'),
                    'fehler'             => __('Ein Fehler ist aufgetreten. Bitte erneut versuchen.', 'simple-appointment-booking'),
                ),
            ));
        }

        // CSS für Mitarbeiter-Seite (Hook oder GET-Parameter prüfen)
        // Nur laden, wenn wir uns auf der Mitarbeiter-Liste befinden (nicht beim Bearbeiten)
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters for page routing only
        if ((strpos($hook, 'simpbook-mitarbeiter') !== false || (isset($_GET['page']) && $_GET['page'] === 'simpbook-mitarbeiter')) && !($aktion === 'bearbeiten' || $id > 0)) {
            wp_enqueue_style(
                'simpbook-mitarbeiter-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/mitarbeiter.css',
                array('simpbook-backend-style'),
                SIMPBOOK_VERSION
            );
            // JavaScript für Mitarbeiter-Seite einbinden
            wp_enqueue_script(
                'simpbook-mitarbeiter-js',
                plugin_dir_url(dirname(__FILE__)) . 'js/mitarbeiter.js',
                array('jquery'),
                SIMPBOOK_VERSION,
                true
            );

            wp_localize_script('simpbook-mitarbeiter-js', 'simpbookMitarbeiterData', array(
                'i18n' => array(
                    'card_view' => __('Card View', 'simple-appointment-booking'),
                    'table_view' => __('Table View', 'simple-appointment-booking'),
                ),
            ));
        }

        // Reservierungen Liste Seite
        if (isset($_GET['page']) && $_GET['page'] === 'simpbook-reservierungen' && !isset($_GET['simpbook_aktion'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
            wp_enqueue_style(
                'simpbook-reservierungen-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/reservierungen.css',
                array('simpbook-backend-style'),
                SIMPBOOK_VERSION
            );

            // Lade auch das Modal-CSS für das Nachrichtenmodal
            wp_enqueue_style(
                'simpbook-kalender-modal-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/kalender-modal.css',
                array('simpbook-reservierungen-style'),
                SIMPBOOK_VERSION
            );

            wp_enqueue_script(
                'simpbook-reservierungen-liste-js',
                plugin_dir_url(dirname(__FILE__)) . 'js/reservierungen-liste.js',
                array('jquery'),
                SIMPBOOK_VERSION,
                true
            );

            // Daten für Lokalisierung
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for pagination only
            $current_page = isset($_GET['simpbook_seite_nr']) ? max(1, intval($_GET['simpbook_seite_nr'])) : 1;
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- GET parameter for sorting only
            $order = isset($_GET['simpbook_order']) ? sanitize_text_field(wp_unslash($_GET['simpbook_order'])) : 'datum';
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- GET parameter for sorting only
            $direction = isset($_GET['simpbook_direction']) ? sanitize_text_field(wp_unslash($_GET['simpbook_direction'])) : 'ASC';
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $simpbook_filter = isset($_GET['simpbook_filter']) ? sanitize_text_field(wp_unslash($_GET['simpbook_filter'])) : 'alle';
            $simpbook_base_url = simpbook_maybe_add_pwa_param(admin_url('admin.php?page=simpbook-reservierungen'));

            wp_localize_script('simpbook-reservierungen-liste-js', 'simpbookReservierungenListe', array(
                'baseUrl' => $simpbook_base_url,
                'currentPage' => $current_page,
                // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Input validated and sanitized on use
                'currentOrder' => $order,
                // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing/filtering only
                // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Input validated and sanitized on use
                'currentDirection' => $direction,
                'currentFilter' => $simpbook_filter,
                'currentLanguage' => simpbook_get_current_language(),
                'ajaxUrl' => admin_url('admin-ajax.php'),
                'hasBulkActions' => in_array($simpbook_filter, ['vergangene', 'storniert'], true),
                'bulkDeleteNonce' => wp_create_nonce('simpbook_delete_multiple_reservierungen_nonce'),
                'updateMitarbeiterNonce' => wp_create_nonce('simpbook_update_mitarbeiter_nonce'),
                'translations' => array(
                    'ausstehend' => __('Pending', 'simple-appointment-booking'),
                    'bestaetigt' => __('Confirmed', 'simple-appointment-booking'),
                    'abgelehnt' => __('Rejected', 'simple-appointment-booking'),
                    'storniert' => __('Cancelled', 'simple-appointment-booking'),
                    'am' => __('at:', 'simple-appointment-booking'),
                    'at' => __('at', 'simple-appointment-booking'),
                    'at' => __('at', 'simple-appointment-booking'),
                    'noSpecificEmployee' => __('No Specific Staff Member', 'simple-appointment-booking'),
                    'confirmBooking' => __('Really confirm booking?', 'simple-appointment-booking'),
                    'rejectBooking' => __('Really reject booking?', 'simple-appointment-booking'),
                    'cancelBooking' => __('Really cancel booking?', 'simple-appointment-booking'),
                    'bestaetigen' => __('Confirm', 'simple-appointment-booking'),
                    'ablehnen' => __('Reject', 'simple-appointment-booking'),
                    'stornieren' => __('Cancel', 'simple-appointment-booking'),
                    'bearbeiten' => __('Edit', 'simple-appointment-booking'),
                    'sendMessage' => __('Send Message', 'simple-appointment-booking'),
                    'loeschen' => __('Delete', 'simple-appointment-booking'),
                    'confirmDelete' => __('Really delete booking?', 'simple-appointment-booking'),
                    'modalNotFound' => __('Fehler: Modal-Element nicht gefunden', 'simple-appointment-booking'),
                    'error' => __('Error', 'simple-appointment-booking'),
                    'deleteError' => __('Error deleting', 'simple-appointment-booking'),
                    'generalError' => __('An error occurred', 'simple-appointment-booking'),
                    'confirmation' => __('Confirmation', 'simple-appointment-booking'),
                    'sending' => __('Sending...', 'simple-appointment-booking'),
                    'messageSent' => __('Message sent successfully!', 'simple-appointment-booking'),
                    'success' => __('Erfolg', 'simple-appointment-booking'),
                    'errorColon' => __('Error:', 'simple-appointment-booking'),
                    'generalErrorRetry' => __('An error occurred. Please try again.', 'simple-appointment-booking'),
                    'selectedSingular' => __('selected', 'simple-appointment-booking'),
                    'selectedPlural' => __('selected', 'simple-appointment-booking'),
                    'selectAtLeastOne' => __('Please select at least one booking.', 'simple-appointment-booking'),
                    'hint' => __('Notice', 'simple-appointment-booking'),
                    'confirmBulkDelete' => __('Are you sure you want to delete all selected bookings? This action cannot be undone.', 'simple-appointment-booking'),
                    'deleteBookings' => __('Delete Bookings', 'simple-appointment-booking'),
                    'deleteErrorPrefix' => __('Error deleting:', 'simple-appointment-booking'),
                    'errorStatusChange' => __('Error changing status', 'simple-appointment-booking'),
                    'errorCancel' => __('Fehler beim Stornieren', 'simple-appointment-booking'),
                    'cardView' => __('Card View', 'simple-appointment-booking'),
                    'tableView' => __('Table View', 'simple-appointment-booking'),
                ),
            ));
        }

        // Scripts für die Bearbeitungsseite laden (wenn simpbook_aktion=bearbeiten in der URL ist)
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters for page routing only, not form data
        if (isset($_GET['page']) && $_GET['page'] === 'simpbook-reservierungen' &&
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters for page routing only, not form data
            isset($_GET['simpbook_aktion']) && $_GET['simpbook_aktion'] === 'bearbeiten') {
            wp_enqueue_script('jquery-ui-datepicker');
            wp_enqueue_style('jquery-ui-style');

            // Datepicker-Farbregeln nach jQuery UI injizieren
            $datepicker_color_css_edit = "
                .ui-datepicker td.urlaub-gesperrt-tag span.ui-state-default,
                .ui-datepicker td.urlaub-gesperrt-tag a.ui-state-default {
                    background: #fff3e0 !important;
                    border-color: #ffb74d !important;
                    color: #e65100 !important;
                    cursor: not-allowed !important;
                    opacity: 1 !important;
                }
                .ui-datepicker td.speziell-geschlossen-tag span.ui-state-default,
                .ui-datepicker td.speziell-geschlossen-tag a.ui-state-default {
                    background: #fce4e4 !important;
                    border-color: #e57373 !important;
                    color: #c62828 !important;
                    cursor: not-allowed !important;
                    opacity: 1 !important;
                }
                .ui-datepicker td.deaktivierter-wochentag span.ui-state-default,
                .ui-datepicker td.deaktivierter-wochentag a.ui-state-default {
                    background: #f5f5f5 !important;
                    border-color: #ddd !important;
                    color: #bbb !important;
                    cursor: not-allowed !important;
                    opacity: 1 !important;
                }
            ";
            wp_add_inline_style('jquery-ui-style', $datepicker_color_css_edit);

            wp_enqueue_style(
                'simpbook-reservierung-bearbeiten-style',
                plugin_dir_url(dirname(__FILE__)) . 'css/reservierung-bearbeiten.css',
                array(),
                SIMPBOOK_VERSION
            );
            // Dynamische CSS-Variablen als Inline-Style hinzufügen
            $dynamic_css_edit = "
                :root {
                    --simpbook-container-bg: " . esc_html(get_option('simpbook_container_background', '#8bbce4')) . ";
                    --simpbook-text-color: " . esc_html(get_option('simpbook_text_color', '#000000')) . ";
                    --simpbook-button-color: " . esc_html(get_option('simpbook_button_color', '#2271b1')) . ";
                    --simpbook-button-hover: " . esc_html(get_option('simpbook_button_hover', '#135e96')) . ";
                    --simpbook-input-text-color: #000000;
                    --simpbook-active-color: " . esc_html(get_option('simpbook_button_color', '#2271b1')) . ";
                }
            ";
            wp_add_inline_style('simpbook-reservierung-bearbeiten-style', $dynamic_css_edit);

            // JS laden
            $simpbook_reservierung_bearbeiten_js_path = plugin_dir_path(dirname(__FILE__)) . 'js/reservierung-bearbeiten.js';
            $simpbook_reservierung_bearbeiten_js_version = file_exists($simpbook_reservierung_bearbeiten_js_path) ? filemtime($simpbook_reservierung_bearbeiten_js_path) : '1.0.0';

            wp_enqueue_script(
                'simpbook-reservierung-bearbeiten-js',
                plugin_dir_url(dirname(__FILE__)) . 'js/reservierung-bearbeiten.js',
                array('jquery', 'jquery-ui-datepicker'),
                $simpbook_reservierung_bearbeiten_js_version,
                true
            );

            // Daten für JS vorbereiten
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Language detection for display only
            $current_lang = simpbook_get_current_language();
            $month_names = simpbook_get_datepicker_month_names($current_lang);
            $day_names = simpbook_get_datepicker_day_names($current_lang);

            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing/filtering only
            $id = isset($_GET['simpbook_id']) ? intval($_GET['simpbook_id']) : 0;
            $simpbook_db_reservierungen_local = new simpbook_DB_Reservierungen();
            $reservierung = $simpbook_db_reservierungen_local->simpbook_reservierung_holen($id);

            if ($reservierung) {
                // Uhrzeit formatieren
                $uhrzeit_raw = $reservierung->uhrzeit;
                if (strlen($uhrzeit_raw) > 5) {
                    $uhrzeit_raw = substr($uhrzeit_raw, 0, 5);
                }
                $uhrzeit_formatiert = simpbook_format_time($uhrzeit_raw, $current_lang);

                $wochentag_zeiten_config = get_option('simpbook_wochentag_zeiten', []);
                $intervall = intval(get_option('simpbook_intervall', 30));
                $ausgeschlossene_tage_config = get_option('simpbook_ausgeschlossene_tage', '');
                $ausgeschlossene_tage_array_config = array();
                if (!empty($ausgeschlossene_tage_config)) {
                    $ausgeschlossene_tage_array_config = array_map('trim', explode(',', $ausgeschlossene_tage_config));
                }
                $simpbook_urlaub_dates_config = simpbook_expand_urlaub_dates();
                if (!empty($simpbook_urlaub_dates_config)) {
                    $ausgeschlossene_tage_array_config = array_values(array_unique(array_merge($ausgeschlossene_tage_array_config, $simpbook_urlaub_dates_config)));
                }
                $default_map = simpbook_get_default_settings_map();
                $spezielle_tage_konfiguration = simpbook_get_option('simpbook_spezielle_tage_konfiguration', $default_map['simpbook_spezielle_tage_konfiguration']);

                $js_data = array(
                    'ajaxUrl' => admin_url('admin-ajax.php'),
                    'timesNonce' => wp_create_nonce('simpbook_get_available_times_nonce'),
                    'mitarbeiterNonce' => wp_create_nonce('simpbook_mitarbeiter_nonce'),
                    'reservierungId' => intval($id),
                    'wochentagZeiten' => $wochentag_zeiten_config,
                    'zeitIntervall' => intval($intervall),
                    'ausgeschlosseneTage' => $ausgeschlossene_tage_array_config,
                    'urlaubTage' => simpbook_expand_urlaub_dates(),
                    'spezielleTageKonfiguration' => $spezielle_tage_konfiguration,
                    'datepickerTranslations' => array(
                        'monthNames' => $month_names['full'],
                        'monthNamesShort' => $month_names['short'],
                        'dayNames' => $day_names['full'],
                        'dayNamesShort' => $day_names['short'],
                        'dayNamesMin' => $day_names['min'],
                        'currentLanguage' => $current_lang
                    ),
                    'translations' => array(
                        'uhrzeit_waehlen' => __('Select time', 'simple-appointment-booking'),
                        'keine_reservierungen_an_diesem_tag' => __('Keine Reservierungen an diesem Tag', 'simple-appointment-booking'),
                        'lade_zeiten' => __('Loading times...', 'simple-appointment-booking'),
                        'bitte_zuerst_dienstleistung' => __('Please select a service first', 'simple-appointment-booking'),
                        'fehler_beim_laden' => __('Error loading', 'simple-appointment-booking'),
                        'kein_bestimmter_mitarbeiter' => __('No Specific Staff Member', 'simple-appointment-booking'),
                        'mitarbeiter_not_available' => __('Staff member no longer available', 'simple-appointment-booking')
                    ),
                    'initialData' => array(
                        'dienstleistungId' => isset($reservierung->dienstleistung_id) ? intval($reservierung->dienstleistung_id) : 0,
                        'mitarbeiterId' => isset($reservierung->mitarbeiter_id) ? intval($reservierung->mitarbeiter_id) : 0,
                        'uhrzeitRaw' => $uhrzeit_raw,
                        'uhrzeitFormatiert' => $uhrzeit_formatiert
                    )
                );

                wp_localize_script('simpbook-reservierung-bearbeiten-js', 'simpbookReservierungBearbeitenData', $js_data);
            }
        }
    }

    /**
     * Verarbeitet die CSV-Export-Aktion.
     */
    public function simpbook_handle_csv_export_action() {
        if (isset($_GET['page']) && $_GET['page'] === 'simpbook-reservierungen' &&
            isset($_GET['action']) && $_GET['action'] === 'export_csv') {

            if (isset($_GET['simpbook_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['simpbook_nonce'])), 'simpbook_export_reservierungen_csv_nonce')) {

                $filter_for_export = isset($_GET['simpbook_filter']) ? sanitize_text_field(wp_unslash($_GET['simpbook_filter'])) : 'alle';

                $valid_orders = ['id', 'name', 'datum', 'uhrzeit', 'personen', 'status', 'erstellungsdatum'];
                $order_for_export = isset($_GET['simpbook_order']) && in_array($_GET['simpbook_order'], $valid_orders) ? sanitize_key($_GET['simpbook_order']) : 'datum';

                $direction_for_export = isset($_GET['simpbook_direction']) && strtoupper(sanitize_key($_GET['simpbook_direction'])) === 'DESC' ? 'DESC' : 'ASC';

                $filter_condition_for_export = '1=1';
                switch ($filter_for_export) {
                    case 'heute':
                        $filter_condition_for_export = "datum = CURDATE()";
                        break;
                    case 'zukuenftige':
                        $filter_condition_for_export = "(datum > CURDATE()) OR (datum = CURDATE() AND uhrzeit >= CURTIME())";
                        break;
                    case 'vergangene':
                        $filter_condition_for_export = "(datum < CURDATE()) OR (datum = CURDATE() AND uhrzeit < CURTIME())";
                        break;
                    case 'ausstehend':
                        $filter_condition_for_export = "status = 'AUSSTEHEND'";
                        break;
                }

                $this->simpbook_export_reservierungen_csv($filter_condition_for_export, $order_for_export, $direction_for_export);
                exit;

            } else {
                wp_die(
                    esc_html__('Security check for the export failed. The nonce is invalid or missing.', 'simple-appointment-booking'),
                    esc_html__('Error', 'simple-appointment-booking'),
                    ['response' => 403, 'back_link' => true]
                );
            }
        }
    }

    /**
     * Wird bei der Plugin-Aktivierung ausgeführt.
     */
    public static function plugin_aktivieren_static() {
        // Migration: Alte Option-Namen zu neuen simpbook_-Namen
        // Dies stellt sicher, dass bestehende Daten bei Updates erhalten bleiben
        $old_wochentag = get_option('simpbook_wochentag_zeiten');
        if ($old_wochentag !== false && get_option('simpbook_wochentag_zeiten') === false) {
            update_option('simpbook_wochentag_zeiten', $old_wochentag);
            delete_option('simpbook_wochentag_zeiten');
        }
        $old_intervall = get_option('simpbook_intervall');
        if ($old_intervall !== false && get_option('simpbook_intervall') === false) {
            update_option('simpbook_intervall', $old_intervall);
            delete_option('simpbook_intervall');
        }
        
        // Cron-Job für Erinnerungs-E-Mails registrieren
        simpbook_schedule_reminder_emails();
        // Aktivierungszeit speichern für Wizard-Autostart
        update_option('simpbook_plugin_activation_time', time());
        delete_transient('simpbook_setup_wizard_completed');
        global $wpdb;
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        $charset_collate = $wpdb->get_charset_collate();

        // 1. Reservierungen-Tabelle erstellen/erweitern
        $tabellen_name = $wpdb->prefix . 'buchungen';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
        $table_exists = ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $tabellen_name)) === $tabellen_name);

        if (!$table_exists) {
            // Neue Tabelle erstellen
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange -- Schema change required for plugin installation
            $sql = "CREATE TABLE `{$tabellen_name}` (
                id mediumint(9) NOT NULL AUTO_INCREMENT,
                erstellungsdatum datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
                name varchar(100) NOT NULL,
                email varchar(100) NOT NULL,
                telefon varchar(20) NOT NULL,
                datum date NOT NULL,
                uhrzeit time NOT NULL,
                nachricht text,
                custom_fields text NULL,
                status varchar(20) DEFAULT 'AUSSTEHEND' NOT NULL,
                dienstleistung_id mediumint(9) NOT NULL,
                mitarbeiter_id mediumint(9) NULL,
                buchungsoption_id mediumint(9) NULL DEFAULT NULL,
                storniert tinyint(1) DEFAULT 0 NOT NULL,
                stornierungs_token varchar(100) NULL,
                stornierungs_datum datetime NULL,
                erinnerung_gesendet tinyint(1) DEFAULT 0 NOT NULL,
                PRIMARY KEY  (id),
                KEY dienstleistung_id (dienstleistung_id),
                KEY mitarbeiter_id (mitarbeiter_id)
            ) $charset_collate;";
            dbDelta($sql);
        } else {
            // Migration für bestehende Tabelle
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
            $columns = $wpdb->get_col($wpdb->prepare("DESCRIBE %i", $tabellen_name));

            // Neue Spalten hinzufügen
            global $wpdb;
            require_once ABSPATH . 'wp-admin/includes/upgrade.php';

            $charset_collate = $wpdb->get_charset_collate();
            $sql = "CREATE TABLE $tabellen_name (
                id mediumint(9) NOT NULL AUTO_INCREMENT,
                status varchar(20) NOT NULL,
                dienstleistung_id mediumint(9) NOT NULL DEFAULT 0,
                mitarbeiter_id mediumint(9) NULL,
                buchungsoption_id mediumint(9) NULL DEFAULT NULL,
                custom_fields text NULL,
                storniert tinyint(1) DEFAULT 0 NOT NULL,
                stornierungs_token varchar(100) NULL,
                stornierungs_datum datetime NULL,
                erinnerung_gesendet tinyint(1) DEFAULT 0 NOT NULL,
                PRIMARY KEY  (id),
                KEY dienstleistung_id (dienstleistung_id),
                KEY mitarbeiter_id (mitarbeiter_id)
            ) $charset_collate;";

            // 2. Tabellenstruktur automatisch abgleichen (Erstellt Tabelle oder fügt Spalten/Indizes hinzu)
            dbDelta( $sql );

            // 3. Spalten entfernen (Das kann dbDelta nicht, das machen wir manuell)
        // Prüfen, ob die Spalte 'personen' existiert
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $columns = $wpdb->get_col( $wpdb->prepare( "DESCRIBE %i", $tabellen_name ) );
        if ( in_array( 'personen', $columns, true ) ) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->query( $wpdb->prepare( "ALTER TABLE %i DROP COLUMN personen", $tabellen_name ) );
        }
        // Buchungsoption-Spalte hinzufügen falls noch nicht vorhanden
        if ( !in_array( 'buchungsoption_id', $columns, true ) ) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->query( $wpdb->prepare( "ALTER TABLE %i ADD COLUMN buchungsoption_id mediumint(9) NULL DEFAULT NULL", $tabellen_name ) );
        }
        // Custom-Fields-Spalte hinzufügen falls noch nicht vorhanden
        if ( !in_array( 'custom_fields', $columns, true ) ) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->query( $wpdb->prepare( "ALTER TABLE %i ADD COLUMN custom_fields longtext NULL AFTER nachricht", $tabellen_name ) );
        }
        }
        // Sicherstellen, dass dbDelta geladen ist (normalerweise in der Aktivierungsfunktion)
        require_once ABSPATH . 'wp-admin/includes/upgrade.php';

        global $wpdb;
        $dienstleistungen_table = $wpdb->prefix . 'dienstleistungen';
        $charset_collate = $wpdb->get_charset_collate();

        /**
         * WICHTIG für dbDelta:
         * 1. Jedes Feld muss in einer eigenen Zeile stehen.
         * 2. Es müssen ZWEI Leerzeichen zwischen PRIMARY KEY und dem Wort (id) stehen.
         * 3. Verwende keine Backticks (`) um Tabellen- oder Spaltennamen.
         */
        $sql = "CREATE TABLE $dienstleistungen_table (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            name varchar(255) NOT NULL,
            dauer_minuten int(11) NOT NULL,
            pufferzeit_minuten int(11) DEFAULT 0 NOT NULL,
            beschreibung text,
            preis varchar(50),
            preis_anzeigen tinyint(1) DEFAULT 0 NOT NULL,
            bild_id bigint(20) DEFAULT 0 NOT NULL,
            aktiv tinyint(1) DEFAULT 1 NOT NULL,
            sortierung int(11) DEFAULT 0 NOT NULL,
            kategorie_id mediumint(9) DEFAULT NULL,
            ohne_mitarbeiter tinyint(1) DEFAULT 0 NOT NULL,
            verfuegbarkeit longtext DEFAULT NULL,
            erstellungsdatum datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
            PRIMARY KEY  (id),
            KEY aktiv (aktiv),
            KEY kategorie_id (kategorie_id)
        ) $charset_collate;";

        // dbDelta prüft automatisch, ob die Tabelle existiert oder ob Spalten fehlen/geändert werden müssen
        dbDelta($sql);

        // 2b. Dienstleistungs-Kategorien Tabelle erstellen
        $kategorien_table = $wpdb->prefix . 'simpbook_dienstleistung_kategorien';
        $sql = "CREATE TABLE $kategorien_table (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            name varchar(255) NOT NULL,
            beschreibung text,
            sortierung int(11) DEFAULT 0 NOT NULL,
            farbe varchar(7) DEFAULT '#2271b1',
            erstellungsdatum datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
            PRIMARY KEY  (id)
        ) $charset_collate;";
        dbDelta($sql);

        // 2c. Buchungsoptionen-Vorlagen Tabelle (globale Templates)
        $buchungsoptionen_table = $wpdb->prefix . 'simpbook_buchungsoptionen';
        $sql = "CREATE TABLE $buchungsoptionen_table (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            name varchar(255) NOT NULL,
            dauer_minuten int(11) NOT NULL,
            sortierung int(11) DEFAULT 0 NOT NULL,
            erstellungsdatum datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
            PRIMARY KEY  (id)
        ) $charset_collate;";
        dbDelta($sql);

        // 2d. Dienstleistung-Buchungsoptionen Zuweisung (pro Service eigene Preise)
        $dl_buchungsoptionen_table = $wpdb->prefix . 'simpbook_dienstleistung_buchungsoptionen';
        $sql = "CREATE TABLE $dl_buchungsoptionen_table (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            dienstleistung_id mediumint(9) NOT NULL,
            buchungsoption_id mediumint(9) NOT NULL,
            preis varchar(50),
            sortierung int(11) DEFAULT 0 NOT NULL,
            PRIMARY KEY  (id),
            KEY dienstleistung_id (dienstleistung_id),
            KEY buchungsoption_id (buchungsoption_id)
        ) $charset_collate;";
        dbDelta($sql);

        // 3. Mitarbeiter-Tabelle erstellen
        $mitarbeiter_table = $wpdb->prefix . 'mitarbeiter';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
        if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $mitarbeiter_table)) !== $mitarbeiter_table) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange -- Schema change required for plugin installation
            $sql = "CREATE TABLE `{$mitarbeiter_table}` (
                id mediumint(9) NOT NULL AUTO_INCREMENT,
                name varchar(255) NOT NULL,
                profilfoto_url varchar(500),
                email varchar(255),
                telefon varchar(50),
                beschreibung text,
                im_frontend_anzeigen tinyint(1) DEFAULT 1 NOT NULL,
                aktiv tinyint(1) DEFAULT 1 NOT NULL,
                arbeitszeiten text,
                sortierung int(11) DEFAULT 0 NOT NULL,
                erstellungsdatum datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
                PRIMARY KEY  (id),
                KEY aktiv (aktiv),
                KEY im_frontend_anzeigen (im_frontend_anzeigen)
            ) $charset_collate;";
            dbDelta($sql);
        }

        // 4. Mitarbeiter-Dienstleistungen Beziehungstabelle erstellen
        $mitarbeiter_dienstleistungen_table = $wpdb->prefix . 'mitarbeiter_dienstleistungen';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
        if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $mitarbeiter_dienstleistungen_table)) !== $mitarbeiter_dienstleistungen_table) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange,WordPress.DB.DirectDatabaseQuery.NoCaching -- Schema change required for plugin installation
            $sql = "CREATE TABLE `{$mitarbeiter_dienstleistungen_table}` (
                id mediumint(9) NOT NULL AUTO_INCREMENT,
                mitarbeiter_id mediumint(9) NOT NULL,
                dienstleistung_id mediumint(9) NOT NULL,
                PRIMARY KEY  (id),
                UNIQUE KEY unique_assignment (mitarbeiter_id, dienstleistung_id),
                KEY mitarbeiter_id (mitarbeiter_id),
                KEY dienstleistung_id (dienstleistung_id)
            ) $charset_collate;";
            dbDelta($sql);
        }

        // 5. Email-Token-Tabelle erstellen (für E-Mail-Aktionslinks mit 7-Tage-Gültigkeit)
        $email_tokens_table = $wpdb->prefix . 'simpbook_email_tokens';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
        if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $email_tokens_table)) !== $email_tokens_table) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange -- Schema change required for plugin installation
            $sql = "CREATE TABLE `{$email_tokens_table}` (
                id mediumint(9) NOT NULL AUTO_INCREMENT,
                token varchar(64) NOT NULL,
                booking_id mediumint(9) NOT NULL,
                action varchar(50) NOT NULL,
                created_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
                expires_at datetime NOT NULL,
                PRIMARY KEY  (id),
                UNIQUE KEY token (token),
                KEY booking_id (booking_id),
                KEY expires_at (expires_at)
            ) $charset_collate;";
            dbDelta($sql);
        }

        // 6. Cron-Job für Token-Cleanup (täglich abgelaufene Tokens löschen)
        if (!wp_next_scheduled('simpbook_cleanup_expired_tokens')) {
            wp_schedule_event(time(), 'daily', 'simpbook_cleanup_expired_tokens');
        }

        // Wichtig: Stelle sicher, dass alle Standard-Einstellungen in wp_options gespeichert sind
        // Das passiert z.B. beim ersten Plugin-Aktivieren oder wenn Optionen gelöscht wurden
        // Prüfe ob Option existiert UND ob sie gültige Daten enthält (nicht nur leeres Array)
        $existing_wochentag_zeiten = simpbook_get_option('simpbook_wochentag_zeiten');
        $needs_defaults = false;
        
        if (empty($existing_wochentag_zeiten)) {
            $needs_defaults = true;
        } elseif (is_array($existing_wochentag_zeiten)) {
            // Prüfe ob mindestens ein Wochentag konfiguriert ist
            $has_valid_day = false;
            foreach (['montag', 'dienstag', 'mittwoch', 'donnerstag', 'freitag', 'samstag', 'sonntag'] as $day) {
                if (isset($existing_wochentag_zeiten[$day]) && is_array($existing_wochentag_zeiten[$day])) {
                    $has_valid_day = true;
                    break;
                }
            }
            if (!$has_valid_day) {
                $needs_defaults = true;
            }
        }
        
        if ($needs_defaults) {
            simpbook_reset_plugin_settings_to_defaults();
        }

        $lizenz_key = simpbook_get_option('simpbook_lizenz_key');
        if (!empty($lizenz_key) && !simpbook_ist_lizenz_aktiv_raw()) {
            simpbook_lizenz_validieren($lizenz_key);
        }

        if (!simpbook_ist_lizenz_aktiv_raw() && !simpbook_get_option('simpbook_trial_ever_started')) {
            simpbook_fetch_and_cache_trial_duration();
            simpbook_update_option('simpbook_trial_start_time', time());
            simpbook_update_option('simpbook_trial_ever_started', true);
            simpbook_delete_option('simpbook_trial_settings_reset_done');
        } else if (!simpbook_ist_lizenz_aktiv_raw() && simpbook_get_option('simpbook_trial_ever_started') && !simpbook_get_option('simpbook_trial_start_time')) {
            // Trial lief bereits, Lizenz nicht aktiv. Keine neue Trial gestartet.
        }
    }

    /**
     * Ändert die Absender-E-Mail-Adresse für Plugin-E-Mails.
     */
    public function simpbook_aendere_mail_absender_email($email) {
        $default_map = simpbook_get_default_settings_map();
        return simpbook_get_option('simpbook_benachrichtigungs_email', $default_map['simpbook_benachrichtigungs_email']);
    }

    /**
     * Ändert den Absendernamen für Plugin-E-Mails.
     */
    public function simpbook_aendere_mail_absender_name($name) {
        $default_map = simpbook_get_default_settings_map();
        return simpbook_get_option('simpbook_firmen_name', $default_map['simpbook_firmen_name']);
    }

    /**
     * Returns the default form field configuration (system fields).
     */
    public static function simpbook_get_default_form_config() {
        return array(
            'fields' => array(
                array(
                    'key'       => 'name',
                    'type'      => 'text',
                    'label'     => __('Name', 'simple-appointment-booking'),
                    'placeholder' => __('Name', 'simple-appointment-booking'),
                    'required'  => true,
                    'removable' => false,
                ),
                array(
                    'key'       => 'email',
                    'type'      => 'email',
                    'label'     => __('Email', 'simple-appointment-booking'),
                    'placeholder' => __('Email', 'simple-appointment-booking'),
                    'required'  => true,
                    'removable' => false,
                ),
                array(
                    'key'       => 'telefon',
                    'type'      => 'tel',
                    'label'     => __('Phone', 'simple-appointment-booking'),
                    'placeholder' => __('Phone', 'simple-appointment-booking'),
                    'required'  => true,
                    'removable' => false,
                ),
            ),
        );
    }

    /**
     * Returns the saved form field configuration or the default if none exists.
     */
    public static function simpbook_get_form_fields_config() {
        $raw = get_option('simpbook_form_fields_config', '');
        if (empty($raw)) {
            return self::simpbook_get_default_form_config();
        }
        $decoded = json_decode($raw, true);
        if (!is_array($decoded) || !isset($decoded['fields']) || !is_array($decoded['fields'])) {
            return self::simpbook_get_default_form_config();
        }
        // Ensure system fields are always present (guards against DB corruption / empty-save).
        $existing_keys = array_column($decoded['fields'], 'key');
        $system_defaults = self::simpbook_get_default_form_config()['fields'];
        $missing = array();
        foreach ( array_reverse( $system_defaults ) as $sys_field ) {
            if ( ! in_array( $sys_field['key'], $existing_keys, true ) ) {
                array_unshift( $missing, $sys_field );
            }
        }
        if ( ! empty( $missing ) ) {
            $decoded['fields'] = array_merge( $missing, $decoded['fields'] );
        }
        return $decoded;
    }

    /**
     * AJAX: Return form field configuration (admin only).
     */
    public function simpbook_get_form_config_ajax() {
        if (!current_user_can('manage_options')) {
            wp_send_json_error('No permission');
        }
        if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'simpbook_form_builder_nonce')) {
            wp_send_json_error('Invalid request');
        }
        $config = self::simpbook_get_form_fields_config();
        // Always overwrite system field labels from current translation
        $sys_labels = array(
            'name'    => array('label' => __('Name', 'simple-appointment-booking'),  'placeholder' => __('Name', 'simple-appointment-booking')),
            'email'   => array('label' => __('Email', 'simple-appointment-booking'), 'placeholder' => __('Email', 'simple-appointment-booking')),
            'telefon' => array('label' => __('Phone', 'simple-appointment-booking'), 'placeholder' => __('Phone', 'simple-appointment-booking')),
        );
        foreach ($config['fields'] as &$field) {
            if (empty($field['removable']) && isset($sys_labels[$field['key']])) {
                $field['label']       = $sys_labels[$field['key']]['label'];
                $field['placeholder'] = $sys_labels[$field['key']]['placeholder'];
            }
        }
        unset($field);
        wp_send_json_success(array('config' => $config));
    }

    /**
     * AJAX: Save form field configuration (admin only).
     */
    public function simpbook_save_form_config_ajax() {
        if (!current_user_can('manage_options')) {
            wp_send_json_error('No permission');
        }
        if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'simpbook_form_builder_nonce')) {
            wp_send_json_error('Invalid request');
        }
        $raw_config = isset($_POST['config']) ? wp_unslash($_POST['config']) : '';
        if (empty($raw_config)) {
            wp_send_json_error('No configuration submitted');
        }
        $config = json_decode($raw_config, true);
        if (!is_array($config) || !isset($config['fields']) || !is_array($config['fields'])) {
            wp_send_json_error('Invalid configuration');
        }
        $allowed_types = array('text', 'textarea', 'tel', 'email', 'date', 'number', 'select', 'checkbox', 'url');
        $clean_fields  = array();
        foreach ($config['fields'] as $field) {
            if (!is_array($field) || empty($field['key'])) { continue; }
            $type = isset($field['type']) && in_array($field['type'], $allowed_types, true) ? $field['type'] : 'text';
            $clean = array(
                'key'         => sanitize_key($field['key']),
                'type'        => $type,
                'label'       => isset($field['label'])       ? sanitize_text_field($field['label'])       : '',
                'placeholder' => isset($field['placeholder']) ? sanitize_text_field($field['placeholder']) : '',
                'required'    => !empty($field['required']),
                'removable'   => !empty($field['removable']),
            );
            if ($type === 'select' && isset($field['options'])) {
                $clean['options'] = sanitize_text_field($field['options']);
            }
            $clean_fields[] = $clean;
        }
        // Ensure the three system fields are always stored, prepending any that are missing.
        $system_defaults   = self::simpbook_get_default_form_config()['fields'];
        $saved_keys        = array_column( $clean_fields, 'key' );
        $missing_sys       = array();
        foreach ( array_reverse( $system_defaults ) as $sys_field ) {
            if ( ! in_array( $sys_field['key'], $saved_keys, true ) ) {
                array_unshift( $missing_sys, $sys_field );
            }
        }
        if ( ! empty( $missing_sys ) ) {
            $clean_fields = array_merge( $missing_sys, $clean_fields );
        }
        $clean_config = array('fields' => $clean_fields);
        update_option('simpbook_form_fields_config', wp_json_encode($clean_config, JSON_UNESCAPED_UNICODE));
        wp_send_json_success(array('message' => __('Form configuration saved.', 'simple-appointment-booking')));
    }

    /**
     * Rendert eine Live-Vorschau des Buchungsformulars mit den angegebenen Formular-Design.
     * Nur für eingeloggte Admins zugänglich (manage_options).
     */
    public function simpbook_get_form_preview_ajax() {
        if (!current_user_can('manage_options')) {
            wp_die('Keine Berechtigung');
        }

        $default_map = simpbook_get_default_settings_map();

        // Design-Parameter aus GET-Daten holen (URL-Parameter aus dem iframe-src)
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Preview only for admin users with manage_options capability
        $button_color = isset($_GET['button_color']) ? sanitize_hex_color(wp_unslash($_GET['button_color'])) : simpbook_get_option('simpbook_button_color', $default_map['simpbook_button_color']);
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Preview only for admin users with manage_options capability
        $button_text_color = isset($_GET['button_text_color']) ? sanitize_hex_color(wp_unslash($_GET['button_text_color'])) : simpbook_get_option('simpbook_button_text_color', $default_map['simpbook_button_text_color'] ?? '#ffffff');
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Preview only for admin users with manage_options capability
        $button_border_radius_preview = isset($_GET['button_border_radius']) ? intval($_GET['button_border_radius']) : intval(simpbook_get_option('simpbook_button_border_radius', $default_map['simpbook_button_border_radius'] ?? 8));
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Preview only for admin users with manage_options capability
        $container_background = isset($_GET['container_background']) ? sanitize_hex_color(wp_unslash($_GET['container_background'])) : simpbook_get_option('simpbook_container_background', $default_map['simpbook_container_background']);
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Preview only for admin users with manage_options capability
        $text_color = isset($_GET['text_color']) ? sanitize_hex_color(wp_unslash($_GET['text_color'])) : simpbook_get_option('simpbook_text_color', $default_map['simpbook_text_color']);
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Preview only for admin users with manage_options capability
        $tile_background = isset($_GET['tile_background']) ? sanitize_hex_color(wp_unslash($_GET['tile_background'])) : simpbook_get_option('simpbook_tile_background', $default_map['simpbook_tile_background']);
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Preview only for admin users with manage_options capability
        $tile_text_color = isset($_GET['tile_text_color']) ? sanitize_hex_color(wp_unslash($_GET['tile_text_color'])) : simpbook_get_option('simpbook_tile_text_color', $default_map['simpbook_tile_text_color'] ?? '#333333');
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Preview only for admin users with manage_options capability
        $border_radius = isset($_GET['border_radius']) ? intval($_GET['border_radius']) : intval(simpbook_get_option('simpbook_border_radius', $default_map['simpbook_border_radius']));
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Preview only for admin users with manage_options capability
        $tile_border_radius = isset($_GET['tile_border_radius']) ? intval($_GET['tile_border_radius']) : intval(simpbook_get_option('simpbook_tile_border_radius', $default_map['simpbook_tile_border_radius']));

        // Überschriften-Parameter für Live-Vorschau
        global $simpbook_preview_headers;
        $simpbook_preview_headers = array();
        $header_keys = array('date', 'service', 'employee', 'time', 'contact', 'booking_option');
        foreach ($header_keys as $key) {
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Preview only for admin users with manage_options capability
            if (isset($_GET['form_header_' . $key]) && $_GET['form_header_' . $key] !== '') {
                $simpbook_preview_headers[$key] = sanitize_text_field(wp_unslash($_GET['form_header_' . $key]));
            }
        }

        $button_hover_color = simpbook_adjust_brightness($button_color, -20);

        // Vollständige HTML-Seite ausgeben
        ?>
        <!DOCTYPE html>
        <html <?php language_attributes(); ?>>
        <head>
            <meta charset="<?php bloginfo('charset'); ?>">
            <!-- Feste Viewport-Breite erzwingt Desktop-Layout unabhängig von der iframe-Breite -->
            <meta name="viewport" content="width=900">
            <title><?php esc_html_e('Formular-Vorschau', 'simple-appointment-booking'); ?></title>
            <?php
            wp_enqueue_style('dashicons');
            wp_register_style('jquery-ui-style-preview', plugin_dir_url(dirname(__FILE__)) . 'vendor/jquery-ui/jquery-ui.min.css', array(), SIMPBOOK_VERSION);
            wp_enqueue_style('jquery-ui-style-preview');
            wp_enqueue_style('formular-style-preview', plugin_dir_url(dirname(__FILE__)) . 'css/formular-style.css', array(), SIMPBOOK_VERSION);
            wp_enqueue_script('jquery');
            wp_enqueue_script('jquery-ui-datepicker');

            $current_lang = simpbook_get_current_language();
            $month_names  = simpbook_get_datepicker_month_names($current_lang);
            $day_names    = simpbook_get_datepicker_day_names($current_lang);

            $preview_ajax_data = array(
                'ajax_url'         => admin_url('admin-ajax.php'),
                'nonce'            => wp_create_nonce('simpbook_nonce'),
                'times_nonce'      => wp_create_nonce('simpbook_get_available_times_nonce'),
                'mitarbeiter_nonce' => wp_create_nonce('simpbook_mitarbeiter_nonce'),
                'wochentagZeiten'  => simpbook_get_option('simpbook_wochentag_zeiten', $default_map['simpbook_wochentag_zeiten']),
                'ausgeschlosseneTage' => array(),
                'verweildauer'     => simpbook_get_option('simpbook_verweildauer', $default_map['simpbook_verweildauer']),
                'max_personen'     => simpbook_get_option('simpbook_max_personen', $default_map['simpbook_max_personen']),
                'translations'     => array(
                    'pleaseSelectDate'    => __('Please select a date.', 'simple-appointment-booking'),
                    'pleaseSelectService' => __('Please select a service first.', 'simple-appointment-booking'),
                    'loadingTimes'        => __('Loading times...', 'simple-appointment-booking'),
                    'noTimesAvailable'    => __('No available times', 'simple-appointment-booking'),
                    'pleaseSelectTime'    => __('Please select a time.', 'simple-appointment-booking'),
                    'sending'             => __('Sending...', 'simple-appointment-booking'),
                    'reservationSent'     => __('Reservation successful!', 'simple-appointment-booking'),
                    'errorOccurred'       => __('An error occurred.', 'simple-appointment-booking'),
                    'selectDate'          => __('Select a date', 'simple-appointment-booking'),
                    'noMessage'           => __('None', 'simple-appointment-booking'),
                    'loadingEmployees'    => __('Loading staff...', 'simple-appointment-booking'),
                    'noSpecificEmployee'  => __('No Specific Staff Member', 'simple-appointment-booking'),
                    'timeOnly'            => __('Time', 'simple-appointment-booking'),
                    'employeeAndTime'     => __('Employee & Time', 'simple-appointment-booking'),
                    'dateAndEmployee'     => __('Date & Employee', 'simple-appointment-booking'),
                    'dateOnly'            => __('Date', 'simple-appointment-booking'),
                ),
                'currentLanguage'  => $current_lang,
                'datepickerTranslations' => array(
                    'monthNames'      => $month_names['full'],
                    'monthNamesShort' => $month_names['short'],
                    'dayNames'        => $day_names['full'],
                    'dayNamesShort'   => $day_names['short'],
                    'dayNamesMin'     => $day_names['min'],
                ),
                'mindestvorlauf_stunden' => intval(simpbook_get_option('simpbook_mindestvorlauf_stunden', $default_map['simpbook_mindestvorlauf_stunden'])),
                'maximale_vorlauf_tage'  => intval(simpbook_get_option('simpbook_maximale_vorlauf_tage', $default_map['simpbook_maximale_vorlauf_tage'])),
                'serverTime'       => current_time('timestamp'),
                'todayYMD'         => current_time('Y-m-d'),
                'spezielle_tage'   => simpbook_get_option('simpbook_spezielle_tage_konfiguration', $default_map['simpbook_spezielle_tage_konfiguration']),
                'dauer_anzeigen'   => simpbook_get_option('simpbook_dauer_anzeigen', '1'),
                'pluginUrl'        => SIMPBOOK_PLUGIN_URL,
                'formFieldsConfig' => self::simpbook_get_form_fields_config(),
                'fbPreviewStep'    => 3,
            );

            wp_enqueue_script('simpbook-formular-preview', plugin_dir_url(dirname(__FILE__)) . 'js/formular-frontend.js', array('jquery', 'jquery-ui-datepicker'), SIMPBOOK_VERSION, true);
            wp_localize_script('simpbook-formular-preview', 'simpbook_ajax', $preview_ajax_data);

            wp_print_styles();
            wp_print_scripts();
            ?>
            <style>
                body {
                    margin: 0;
                    padding: 0;
                    background: #f0f0f1;
                    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
                }
                .preview-wrapper {
                    max-width: 100%;
                    margin: 0;
                }
                :root {
                    --simpbook-container-bg: <?php echo esc_attr($container_background); ?>;
                    --simpbook-text-color: <?php echo esc_attr($text_color); ?>;
                    --simpbook-button-color: <?php echo esc_attr($button_color); ?>;
                    --simpbook-button-text-color: <?php echo esc_attr($button_text_color); ?>;
                    --simpbook-button-border-radius: <?php echo esc_attr($button_border_radius_preview); ?>px;
                    --simpbook-button-hover: <?php echo esc_attr($button_hover_color); ?>;
                    --simpbook-active-color: <?php echo esc_attr($button_color); ?>;
                    --simpbook-tile-bg: <?php echo esc_attr($tile_background); ?>;
                    --simpbook-tile-text-color: <?php echo esc_attr($tile_text_color); ?>;
                    --simpbook-input-text-color: #000000;
                    --simpbook-border-radius: <?php echo esc_attr($border_radius); ?>px;
                    --simpbook-tile-border-radius: <?php echo esc_attr($tile_border_radius); ?>px;
                }
                .preview-notice {
                    background: #2271b1;
                    color: white;
                    padding: 15px;
                    text-align: center;
                    border-radius: 8px;
                    margin: 0 auto 20px;
                    font-weight: 600;
                    width: 70%;
                }
                <?php
                // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Preview only for admin users
                if ( isset( $_GET['fb_preview'] ) ) :
                ?>
                /* Form builder preview: hide step indicator and all steps except step 3 */
                .reservierung-steps {
                    display: none !important;
                }
                .reservierung-form-step:not([data-step="3"]) {
                    display: none !important;
                }
                .reservierung-form-step[data-step="3"] {
                    display: block !important;
                }
                <?php else : ?>
                /* Design tab preview: show all steps stacked */
                .reservierung-steps {
                    display: flex !important;
                }
                .reservierung-form-step {
                    display: block !important;
                    opacity: 1 !important;
                    margin-bottom: 24px;
                    border-bottom: 2px dashed rgba(0,0,0,0.1);
                    padding-bottom: 16px;
                }
                .reservierung-form-step:last-child {
                    border-bottom: none;
                }
                .form-button.back,
                .form-button.next,
                .form-button.submit {
                    pointer-events: none !important;
                    opacity: 0.5 !important;
                    cursor: not-allowed !important;
                }
                <?php endif; ?>
            </style>
        </head>
        <body>
            <div class="preview-wrapper">
                <div class="preview-notice">
                    <?php esc_html_e('Live Preview - Changes are displayed immediately', 'simple-appointment-booking'); ?>
                </div>
                <?php
                $formular_pfad = plugin_dir_path(dirname(__FILE__)) . 'templates/formular.php';
                if (file_exists($formular_pfad)) {
                    include $formular_pfad;
                } else {
                    echo '<p>Fehler: Formular-Template nicht gefunden.</p>';
                }
                ?>
            </div>
            <?php wp_print_footer_scripts(); ?>
            <script>
            jQuery(document).ready(function($) {
                <?php
                // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Preview only for admin users
                if ( isset( $_GET['fb_preview'] ) ) :
                ?>
                // Form builder mode: activate only step 3
                $('.reservierung-form-step').removeClass('active');
                $('.reservierung-form-step[data-step="3"]').addClass('active');

                // Render custom fields for preview
                if (typeof simpbookRenderCustomFields === 'function') {
                    simpbookRenderCustomFields();
                }
                <?php else : ?>
                // Design tab mode: show all steps
                $('.reservierung-form-step').addClass('active').show();

                // Render custom fields for preview
                if (typeof simpbookRenderCustomFields === 'function') {
                    simpbookRenderCustomFields();
                }
                <?php endif; ?>

                // Formular-Submit in der Preview komplett blockieren
                $('#reservierung-formular').on('submit', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    e.stopImmediatePropagation();
                    return false;
                });

                // Submit-Button deaktivieren
                $('.form-button.submit').prop('disabled', true).css({
                    'opacity': '0.5',
                    'cursor': 'not-allowed',
                    'pointer-events': 'none'
                });

                // AJAX-Requests für Buchung blockieren
                var originalAjax = $.ajax;
                $.ajax = function(options) {
                    if (options.url && options.url.indexOf('admin-ajax.php') !== -1) {
                        if (options.data && (
                            (typeof options.data === 'string' && options.data.indexOf('action=simpbook_reservierung_speichern') !== -1) ||
                            (typeof options.data === 'object' && options.data.action === 'simpbook_reservierung_speichern')
                        )) {
                            return $.Deferred().reject().promise();
                        }
                    }
                    return originalAjax.call(this, options);
                };
            });
            </script>
        </body>
        </html>
        <?php
        exit;
    }

    /**
     * Lädt Skripte und Stile für das Frontend.
     */
    public function simpbook_skripte_laden() {
        $default_map = simpbook_get_default_settings_map();
        wp_enqueue_script('jquery-ui-datepicker');
        // Register and enqueue local jQuery UI styles for the frontend
        wp_register_style('jquery-ui-style', plugin_dir_url(dirname(__FILE__)) . 'vendor/jquery-ui/jquery-ui.min.css', array(), SIMPBOOK_VERSION);
        wp_enqueue_style('jquery-ui-style');

        wp_enqueue_style('reservierungen-style', plugin_dir_url(dirname(__FILE__)) . 'css/reservierungen.css', array(), SIMPBOOK_VERSION);
        wp_enqueue_style('formular-style', plugin_dir_url(dirname(__FILE__)) . 'css/formular-style.css', array(), SIMPBOOK_VERSION);
        wp_enqueue_style('stornierung-style', plugin_dir_url(dirname(__FILE__)) . 'css/stornierung.css', array('formular-style'), SIMPBOOK_VERSION);
        
        $bg_color = simpbook_get_option('simpbook_container_background', $default_map['simpbook_container_background']);
        $text_color_val = simpbook_get_option('simpbook_text_color', $default_map['simpbook_text_color']);
        $button_color_val = simpbook_get_option('simpbook_button_color', $default_map['simpbook_button_color']);
        $button_text_color_val = simpbook_get_option('simpbook_button_text_color', $default_map['simpbook_button_text_color'] ?? '#ffffff');
        $button_border_radius_val = simpbook_get_option('simpbook_button_border_radius', $default_map['simpbook_button_border_radius'] ?? 8);
        $tile_bg_color = simpbook_get_option('simpbook_tile_background', $default_map['simpbook_tile_background']);
        $tile_text_color_val = simpbook_get_option('simpbook_tile_text_color', $default_map['simpbook_tile_text_color'] ?? '#333333');
        $button_hover_color_val = simpbook_adjust_brightness($button_color_val, -20);
        $border_radius_val = simpbook_get_option('simpbook_border_radius', $default_map['simpbook_border_radius']);
        $tile_border_radius_val = simpbook_get_option('simpbook_tile_border_radius', $default_map['simpbook_tile_border_radius']);

        $custom_css = "
            :root {
                --simpbook-container-bg: " . esc_html($bg_color) . ";
                --simpbook-text-color: " . esc_html($text_color_val) . ";
                --simpbook-button-color: " . esc_html($button_color_val) . ";
                --simpbook-button-text-color: " . esc_html($button_text_color_val) . ";
                --simpbook-button-border-radius: " . intval($button_border_radius_val) . "px;
                --simpbook-button-hover: " . esc_html($button_hover_color_val) . ";
                --simpbook-active-color: " . esc_html($button_color_val) . ";
                --simpbook-tile-bg: " . esc_html($tile_bg_color) . ";
                --simpbook-tile-text-color: " . esc_html($tile_text_color_val) . ";
                --simpbook-input-text-color: #000000;
                --simpbook-border-radius: " . intval($border_radius_val) . "px;
                --simpbook-tile-border-radius: " . intval($tile_border_radius_val) . "px;
            }
        ";
        wp_add_inline_style('formular-style', $custom_css);

        // Übersetzungsstrings für JavaScript
        $translations = array(
            'pleaseSelectDateAndPeople' => __('Please first select date and people', 'simple-appointment-booking'),
            'loadingTimes' => __('Loading times...', 'simple-appointment-booking'),
            'noTimesAvailable' => __('No available times', 'simple-appointment-booking'),
            'pleaseSelectDate' => __('Please select a date.', 'simple-appointment-booking'),
            'pleaseSelectPeople' => __('Please select the number of people.', 'simple-appointment-booking'),
            'pleaseSelectService' => __('Please select a service first.', 'simple-appointment-booking'),
            'pleaseSelectDateAndService' => __('Please first select date and service', 'simple-appointment-booking'),
            'pleaseSelectTime' => __('Please select a time.', 'simple-appointment-booking'),
            'pleaseFillAllFields' => __('Please fill in all required fields (Name, Email, Phone).', 'simple-appointment-booking'),
            'invalidEmail' => __('Please enter a valid email address.', 'simple-appointment-booking'),
            'invalidPhone' => __('Please enter a valid phone number.', 'simple-appointment-booking'),
            'pleaseFillAllSteps' => __('Please fill in all steps and required fields correctly.', 'simple-appointment-booking'),
            'sending' => __('Sending...', 'simple-appointment-booking'),
            'reservationSent' => __('Reservation successful!', 'simple-appointment-booking'),
            'errorOccurred' => __('An error occurred.', 'simple-appointment-booking'),
            'errorOccurredTryLater' => __('An error occurred. Please try again later.', 'simple-appointment-booking'),
            'submitReservation' => __('Submit Reservation', 'simple-appointment-booking'),
            'noMessage' => __('None', 'simple-appointment-booking'),
            'selectedDate' => __('Selected Date:', 'simple-appointment-booking'),
            'date' => __('Date:', 'simple-appointment-booking'),
            'time' => __('Time:', 'simple-appointment-booking'),
            'people' => __('People:', 'simple-appointment-booking'),
            'name' => __('Name:', 'simple-appointment-booking'),
            'email' => __('Email:', 'simple-appointment-booking'),
            'phone' => __('Phone:', 'simple-appointment-booking'),
            'comment' => __('Comment:', 'simple-appointment-booking'),
            'notAvailable' => __('Not available', 'simple-appointment-booking'),
            'available' => __('Available', 'simple-appointment-booking'),
            'selectDate' => __('Select a date', 'simple-appointment-booking'),
            'errorLoading' => __('Error loading', 'simple-appointment-booking'),
            'error' => __('Error', 'simple-appointment-booking'),
            'loadingEmployees' => __('Loading staff...', 'simple-appointment-booking'),
            'noSpecificEmployee' => __('No Specific Staff Member', 'simple-appointment-booking'),
            'noEmployeesAvailable' => __('No staff available', 'simple-appointment-booking'),
            'noEmployeesAvailableDesc' => __('No staff members are available for the selected day who can provide this service. Please choose a different day.', 'simple-appointment-booking'),
            'serviceOfferedOnDays' => __('This service is only offered on the following days:', 'simple-appointment-booking'),
            'pleaseSelectAnotherDay' => __('Please select a different day', 'simple-appointment-booking'),
            'dayClosedLabel' => __('Closed', 'simple-appointment-booking'),
            'weekdayMo' => __('Mon', 'simple-appointment-booking'),
            'weekdayDi' => __('Tu', 'simple-appointment-booking'),
            'weekdayMi' => __('We', 'simple-appointment-booking'),
            'weekdayDo' => __('Th', 'simple-appointment-booking'),
            'weekdayFr' => __('Fri', 'simple-appointment-booking'),
            'weekdaySa' => __('Sat', 'simple-appointment-booking'),
            'weekdaySo' => __('Su', 'simple-appointment-booking'),
        );

        // Datepicker-Übersetzungen basierend auf der aktuellen Plugin-Sprache
        $current_lang = simpbook_get_current_language();
        $month_names = simpbook_get_datepicker_month_names($current_lang);
        $day_names = simpbook_get_datepicker_day_names($current_lang);

        // Mitarbeiter-Arbeitszeiten für Frontend-Datumsprüfung (Schließzeit-Check)
        $simpbook_mitarbeiter_az_list = [];
        foreach (simpbook_get_all_mitarbeiter(true, false) as $simpbook_ma) {
            if (!empty($simpbook_ma->arbeitszeiten)) {
                $simpbook_az = json_decode($simpbook_ma->arbeitszeiten, true);
                if (is_array($simpbook_az)) {
                    $simpbook_mitarbeiter_az_list[] = $simpbook_az;
                }
            }
        }

        // Daten direkt inline ausgeben statt via wp_localize_script
        $simpbook_ajax_data = array(
            'ajax_url' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('simpbook_nonce'),
            'times_nonce' => wp_create_nonce('simpbook_get_available_times_nonce'),
            'mitarbeiter_nonce' => wp_create_nonce('simpbook_mitarbeiter_nonce'),
            'wochentagZeiten' => simpbook_get_option('simpbook_wochentag_zeiten', $default_map['simpbook_wochentag_zeiten']),
            'ausgeschlosseneTage' => array_values(array_unique(array_merge(
                array_filter(array_map('trim', explode("\n", str_replace("\r", "", simpbook_get_option('simpbook_ausgeschlossene_tage', ''))))),
                simpbook_expand_urlaub_dates()
            ))),
            'verweildauer' => simpbook_get_option('simpbook_verweildauer', $default_map['simpbook_verweildauer']),
            'max_personen' => simpbook_get_option('simpbook_max_personen', $default_map['simpbook_max_personen']),
            'translations' => $translations,
            'currentLanguage' => $current_lang,
            'datepickerTranslations' => array(
                'monthNames' => $month_names['full'],
                'monthNamesShort' => $month_names['short'],
                'dayNames' => $day_names['full'],
                'dayNamesShort' => $day_names['short'],
                'dayNamesMin' => $day_names['min']
            ),
            'serverTime' => current_time('H:i'),
            'serverDate' => current_time('Y-m-d'),
            'mitarbeiterArbeitszeiten' => $simpbook_mitarbeiter_az_list,
            'pluginUrl' => SIMPBOOK_PLUGIN_URL,
            'formFieldsConfig' => self::simpbook_get_form_fields_config(),
        );

        wp_enqueue_script('formular-frontend-js', plugin_dir_url(dirname(__FILE__)) . 'js/formular-frontend.js', array('jquery', 'jquery-ui-datepicker'), SIMPBOOK_VERSION, true);
        wp_localize_script('formular-frontend-js', 'simpbook_ajax', $simpbook_ajax_data);
    }

    /**
     * Zeigt das Reservierungsformular an.
     */
    public function simpbook_reservierungsformular_anzeigen($atts) {
        $atts = shortcode_atts(array('kategorie' => ''), $atts, 'simpbook_bookingform');
        $simpbook_shortcode_kategorie_filter = sanitize_text_field($atts['kategorie']);
        ob_start();
        $formular_pfad = plugin_dir_path(dirname(__FILE__)) . 'templates/formular.php';
        if (file_exists($formular_pfad)) {
            include $formular_pfad;
        } else {
            return "Fehler: Formular-Template nicht gefunden.";
        }
        $output = ob_get_clean();

        // Dekodiere HTML-Entities, die von Themes wie Twenty Twenty-Three/Four/Five escapiert wurden
        // Dies behebt das Problem mit &#038; statt & in JavaScript
        $output = str_replace('&#038;', '&', $output);
        $output = str_replace('&#x26;', '&', $output);
        $output = str_replace('&amp;', '&', $output);

        return $output;
    }

    /**
     * Sendet eine manuelle Nachricht an einen Gast.
     */
    public function simpbook_sende_nachricht_an_gast() {
         if (!isset($_POST['simpbook_form_data'])) { wp_send_json_error('Ungültige Anfrage'); exit; }
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- form_data wird in parse_str() verarbeitet und dann validiert
        parse_str(wp_unslash($_POST['simpbook_form_data']), $form_data);
        // Anpassung hier: Nonce vor der Überprüfung bereinigen.
        if (!isset($form_data['nachricht_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($form_data['nachricht_nonce'])), 'simpbook_sende_nachricht_action')) {
            wp_send_json_error('Security check failed.'); exit;
        }
        $email = isset($form_data['simpbook_email']) ? sanitize_email($form_data['simpbook_email']) : '';
        $betreff = isset($form_data['betreff']) ? sanitize_text_field($form_data['betreff']) : '';
        $nachricht_text = isset($form_data['nachricht']) ? sanitize_textarea_field($form_data['nachricht']) : '';
        if (empty($email) || empty($betreff) || empty($nachricht_text)) { wp_send_json_error('Please fill in all fields'); exit; }
        $headers = array('Content-Type: text/plain; charset=UTF-8');
        $versendet = wp_mail($email, $betreff, $nachricht_text, $headers);
        if ($versendet) wp_send_json_success('Nachricht wurde erfolgreich versendet');
        else wp_send_json_error('E-Mail konnte nicht versendet werden');
        exit;
    }

    /**
     * Gibt Email-Templates für eine bestimmte Sprache per AJAX zurück.
     */
    public function simpbook_get_email_templates_ajax() {
        // Sicherheitsüberprüfung: Nur für eingeloggte Administratoren
        if (!current_user_can('manage_options')) {
            wp_send_json_error('Keine Berechtigung');
            exit;
        }

        // Nonce-Überprüfung
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_email_templates_nonce')) {
            wp_send_json_error('Security check failed');
            exit;
        }

        // Sprache aus POST-Daten holen
        $language = isset($_POST['simpbook_language']) ? sanitize_text_field(wp_unslash($_POST['simpbook_language'])) : 'en_US';
        $valid_languages = array('de_DE', 'en_US', 'en_US_AMPM', 'en_GB', 'it_IT', 'es_ES', 'fr_FR', 'pl_PL', 'ru_RU', 'sv_SE');
        if (!in_array($language, $valid_languages, true)) {
            $language = 'en_US';
        }

        // Alle Email-Templates für die angegebene Sprache laden
        // Die Standardwerte werden als Fallback verwendet, aber simpbook_get_email_template() verwendet
        // automatisch die sprachspezifischen Standardwerte aus simpbook_get_email_template_defaults()
        $templates = array(
            'email_bestaetigungs_betreff' => simpbook_get_email_template(
                'simpbook_email_bestaetigungs_betreff',
                '', // Fallback wird nicht benötigt, da sprachspezifische Standardwerte vorhanden sind
                $language
            ),
            'email_bestaetigungs_nachricht' => simpbook_get_email_template(
                'simpbook_email_bestaetigungs_nachricht',
                '', // Fallback wird nicht benötigt
                $language
            ),
            'email_bestaetigt_betreff' => simpbook_get_email_template(
                'simpbook_email_bestaetigt_betreff',
                '', // Fallback wird nicht benötigt
                $language
            ),
            'email_bestaetigt_nachricht' => simpbook_get_email_template(
                'simpbook_email_bestaetigt_nachricht',
                '', // Fallback wird nicht benötigt
                $language
            ),
            'email_abgelehnt_betreff' => simpbook_get_email_template(
                'simpbook_email_abgelehnt_betreff',
                '', // Fallback wird nicht benötigt
                $language
            ),
            'email_abgelehnt_nachricht' => simpbook_get_email_template(
                'simpbook_email_abgelehnt_nachricht',
                '', // Fallback wird nicht benötigt
                $language
            ),
            'email_erinnerung_betreff' => simpbook_get_email_template(
                'simpbook_email_erinnerung_betreff',
                '',
                $language
            ),
            'email_erinnerung_nachricht' => simpbook_get_email_template(
                'simpbook_email_erinnerung_nachricht',
                '',
                $language
            ),
            'email_storniert_betreff' => simpbook_get_email_template(
                'simpbook_email_storniert_betreff',
                '',
                $language
            ),
            'email_storniert_nachricht' => simpbook_get_email_template(
                'simpbook_email_storniert_nachricht',
                '',
                $language
            )
        );

        wp_send_json_success($templates);
        exit;
    }

    /**
     * Speichert eine neue Reservierung.
     */
    public function simpbook_reservierung_speichern() {
        // Anpassung hier: Nonce vor der Überprüfung bereinigen.
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_nonce')) {
            wp_send_json_error('Security check failed'); exit;
        }
        $name = isset($_POST['simpbook_name']) ? sanitize_text_field(wp_unslash($_POST['simpbook_name'])) : '';
        $email = isset($_POST['simpbook_email']) ? sanitize_email(wp_unslash($_POST['simpbook_email'])) : '';
        $telefon = isset($_POST['simpbook_telefon']) ? sanitize_text_field(wp_unslash($_POST['simpbook_telefon'])) : '';
        $datum_input = isset($_POST['simpbook_datum']) ? sanitize_text_field(wp_unslash($_POST['simpbook_datum'])) : '';
        $uhrzeit_input = isset($_POST['simpbook_uhrzeit']) ? sanitize_text_field(wp_unslash($_POST['simpbook_uhrzeit'])) : '';
        $dienstleistung_id = isset($_POST['simpbook_dienstleistung_id']) ? intval($_POST['simpbook_dienstleistung_id']) : 0;
        $mitarbeiter_id = isset($_POST['simpbook_mitarbeiter_id']) ? intval($_POST['simpbook_mitarbeiter_id']) : 0;
        $buchungsoption_id_save = isset($_POST['simpbook_buchungsoption_id']) ? intval($_POST['simpbook_buchungsoption_id']) : 0;
        $nachricht_text = isset($_POST['simpbook_nachricht']) ? sanitize_textarea_field(wp_unslash($_POST['simpbook_nachricht'])) : '';

        if (empty($name) || empty($email) || empty($datum_input) || empty($uhrzeit_input) || $dienstleistung_id < 1) {
            wp_send_json_error('Please fill in all required fields.'); exit;
        }
        // Flexible Datum-Validierung: Unterstütze d.m.Y, m/d/Y, Y-m-d
        $datum_obj = false;
        $formats = array('d.m.Y', 'd.m.y', 'm/d/Y', 'm/d/y', 'Y-m-d', 'd.m.y', 'dd.mm.yy', 'mm/dd/yy');
        foreach ($formats as $fmt) {
            $datum_obj = DateTime::createFromFormat($fmt, $datum_input);
            if ($datum_obj !== false) {
                break;
            }
        }
        if ($datum_obj === false) {
            $timestamp = strtotime($datum_input);
            if ($timestamp !== false) {
                $datum_obj = new DateTime();
                $datum_obj->setTimestamp($timestamp);
            }
        }
        if ($datum_obj === false) {
            $error_msg = __('Invalid date format. Please use MM/DD/YYYY.', 'simple-appointment-booking');
            if (simpbook_get_current_language() === 'de_DE') {
                $error_msg = __('Invalid date format. Please use DD.MM.YYYY.', 'simple-appointment-booking');
            }
            wp_send_json_error($error_msg); exit;
        }
        $datum_mysql = $datum_obj->format('Y-m-d');

        // Konvertiere Zeit von 12h-Format (falls vorhanden) zu 24h-Format
        $uhrzeit_input_24h = simpbook_parse_time_12h($uhrzeit_input);
        $uhrzeit_obj = DateTime::createFromFormat('H:i', $uhrzeit_input_24h);
        if($uhrzeit_obj === false){ wp_send_json_error('Invalid time format (HH:MM expected).'); exit; }
        $uhrzeit_mysql = $uhrzeit_obj->format('H:i:s');

        global $wpdb;
        $tabellen_name = $wpdb->prefix . 'buchungen';

        // Stornierungs-Token generieren
        $stornierungs_token = simpbook_generiere_stornierungs_token();

        // Prüfen ob Auto-Bestätigung aktiviert ist
        $auto_bestaetigung = get_option('simpbook_auto_bestaetigung', '0') === '1';
        $initial_status = $auto_bestaetigung ? 'BESTÄTIGT' : 'AUSSTEHEND';

        // Collect custom field values from POST data
        $custom_values = array();
        $form_config = self::simpbook_get_form_fields_config();
        if (!empty($form_config['fields'])) {
            foreach ($form_config['fields'] as $cf) {
                if (empty($cf['removable']) || empty($cf['key'])) { continue; }
                $cf_key = sanitize_key($cf['key']);
                if (isset($_POST[$cf_key])) {
                    $custom_values[$cf_key] = sanitize_text_field(wp_unslash($_POST[$cf_key]));
                }
            }
        }

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Plugin-specific table
        $erfolg = $wpdb->insert( $tabellen_name,
            [
                'name' => $name,
                'email' => $email,
                'telefon' => $telefon,
                'datum' => $datum_mysql,
                'uhrzeit' => $uhrzeit_mysql,
                'dienstleistung_id' => $dienstleistung_id,
                'mitarbeiter_id' => $mitarbeiter_id > 0 ? $mitarbeiter_id : null,
                'buchungsoption_id' => $buchungsoption_id_save > 0 ? $buchungsoption_id_save : null,
                'nachricht' => $nachricht_text,
                'custom_fields' => !empty($custom_values) ? wp_json_encode($custom_values, JSON_UNESCAPED_UNICODE) : '',
                'status' => $initial_status,
                'storniert' => 0,
                'stornierungs_token' => $stornierungs_token,
                'erinnerung_gesendet' => 0
            ],
            ['%s', '%s', '%s', '%s', '%s', '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%s', '%d']
        );

        if ($erfolg) {
            $reservierung_id = $wpdb->insert_id;
            $default_map = simpbook_get_default_settings_map();
            $firmen_name = simpbook_get_option('simpbook_firmen_name', $default_map['simpbook_firmen_name']);
            $admin_email_ziel = simpbook_get_option('simpbook_benachrichtigungs_email', $default_map['simpbook_benachrichtigungs_email']);
            
            // Hole aktuelle Sprache für Admin-E-Mails
            $current_language_for_admin = simpbook_get_current_language();
            
            // Erstelle sichere Tokens für E-Mail-Aktionslinks (7 Tage gültig)
            $token_accept = simpbook_create_email_token($reservierung_id, 'accept');
            $token_reject = simpbook_create_email_token($reservierung_id, 'reject');
            
            // URL-safe Status-Codes verwenden (keine Umlaute für Gmail-Kompatibilität)
            $accept_url = add_query_arg([
                'page' => 'simpbook-reservierungen',
                'simpbook_aktion' => 'simpbook_status_aendern',
                'simpbook_id' => $reservierung_id,
                'simpbook_status' => 'BESTAETIGT',  // URL-safe (kein Umlaut)
                'simpbook_token' => $token_accept
            ], admin_url('admin.php'));
            
            $reject_url = add_query_arg([
                'page' => 'simpbook-reservierungen',
                'simpbook_aktion' => 'simpbook_status_aendern',
                'simpbook_id' => $reservierung_id,
                'simpbook_status' => 'ABGELEHNT',  // URL-safe (kein Umlaut)
                'simpbook_token' => $token_reject
            ], admin_url('admin.php'));
            
            $view_url = add_query_arg([
                'page' => 'simpbook-reservierungen',
                'simpbook_aktion' => 'bearbeiten',
                'simpbook_id' => $reservierung_id
            ], admin_url('admin.php'));
            
            // Sprachspezifische Admin-E-Mail Labels
            $admin_labels = array(
                'de_DE' => array(
                    'new_booking_title' => 'Es gibt eine neue Buchungsanfrage',
                    'subject' => 'Neue Buchungsanfrage von %1$s für %2$s',
                    'company' => 'Firma',
                    'name' => 'Name',
                    'email' => 'E-Mail',
                    'phone' => 'Telefon',
                    'date' => 'Datum',
                    'time' => 'Uhrzeit',
                    'service' => 'Dienstleistung',
                    'employee' => 'Mitarbeiter',
                    'booking_option' => 'Buchungsoption',
                    'price' => 'Preis',
                    'message' => 'Nachricht',
                    'no_message' => 'Keine Nachricht angegeben'
                ),
                'en_US' => array(
                    'new_booking_title' => 'New booking request',
                    'subject' => 'New booking request from %1$s for %2$s',
                    'company' => 'Company',
                    'name' => 'Name',
                    'email' => 'Email',
                    'phone' => 'Phone',
                    'date' => 'Date',
                    'time' => 'Time',
                    'service' => 'Service',
                    'employee' => 'Employee',
                    'booking_option' => 'Booking Option',
                    'price' => 'Price',
                    'message' => 'Message',
                    'no_message' => 'No message provided'
                ),
                'en_US_AMPM' => array(
                    'new_booking_title' => 'New booking request',
                    'subject' => 'New booking request from %1$s for %2$s',
                    'company' => 'Company',
                    'name' => 'Name',
                    'email' => 'Email',
                    'phone' => 'Phone',
                    'date' => 'Date',
                    'time' => 'Time',
                    'service' => 'Service',
                    'employee' => 'Employee',
                    'booking_option' => 'Booking Option',
                    'price' => 'Price',
                    'message' => 'Message',
                    'no_message' => 'No message provided'
                ),
                'it_IT' => array(
                    'new_booking_title' => 'Nuova richiesta di prenotazione',
                    'subject' => 'Nuova richiesta di prenotazione da %1$s per %2$s',
                    'company' => 'Azienda',
                    'name' => 'Nome',
                    'email' => 'Email',
                    'phone' => 'Telefono',
                    'date' => 'Data',
                    'time' => 'Ora',
                    'service' => 'Servizio',
                    'employee' => 'Dipendente',
                    'booking_option' => 'Opzione di prenotazione',
                    'price' => 'Prezzo',
                    'message' => 'Messaggio',
                    'no_message' => 'Nessun messaggio fornito'
                ),
                'es_ES' => array(
                    'new_booking_title' => 'Nueva solicitud de reserva',
                    'subject' => 'Nueva solicitud de reserva de %1$s para %2$s',
                    'company' => 'Empresa',
                    'name' => 'Nombre',
                    'email' => 'Correo electrónico',
                    'phone' => 'Teléfono',
                    'date' => 'Fecha',
                    'time' => 'Hora',
                    'service' => 'Servicio',
                    'employee' => 'Empleado',
                    'booking_option' => 'Opción de reserva',
                    'price' => 'Precio',
                    'message' => 'Mensaje',
                    'no_message' => 'No se proporcionó ningún mensaje'
                ),
                'fr_FR' => array(
                    'new_booking_title' => 'Nouvelle demande de réservation',
                    'subject' => 'Nouvelle demande de réservation de %1$s pour %2$s',
                    'company' => 'Entreprise',
                    'name' => 'Nom',
                    'email' => 'E-mail',
                    'phone' => 'Téléphone',
                    'date' => 'Date',
                    'time' => 'Heure',
                    'service' => 'Service',
                    'employee' => 'Employé',
                    'booking_option' => 'Option de réservation',
                    'price' => 'Prix',
                    'message' => 'Message',
                    'no_message' => 'Aucun message fourni'
                ),
                'pl_PL' => array(
                    'new_booking_title' => 'Nowa prośba o rezerwację',
                    'subject' => 'Nowa prośba o rezerwację od %1$s dla %2$s',
                    'company' => 'Firma',
                    'name' => 'Nazwa',
                    'email' => 'E-mail',
                    'phone' => 'Telefon',
                    'date' => 'Data',
                    'time' => 'Godzina',
                    'service' => 'Usługa',
                    'employee' => 'Pracownik',
                    'booking_option' => 'Opcja rezerwacji',
                    'price' => 'Cena',
                    'message' => 'Wiadomość',
                    'no_message' => 'Nie podano wiadomości'
                ),
                'en_GB' => array(
                    'new_booking_title' => 'New booking request',
                    'subject' => 'New booking request from %1$s for %2$s',
                    'company' => 'Company',
                    'name' => 'Name',
                    'email' => 'Email',
                    'phone' => 'Phone',
                    'date' => 'Date',
                    'time' => 'Time',
                    'service' => 'Service',
                    'employee' => 'Employee',
                    'booking_option' => 'Booking Option',
                    'price' => 'Price',
                    'message' => 'Message',
                    'no_message' => 'No message provided'
                ),
                'ru_RU' => array(
                    'new_booking_title' => 'Новый запрос на бронирование',
                    'subject' => 'Новый запрос на бронирование от %1$s для %2$s',
                    'company' => 'Компания',
                    'name' => 'Имя',
                    'email' => 'Email',
                    'phone' => 'Телефон',
                    'date' => 'Дата',
                    'time' => 'Время',
                    'service' => 'Услуга',
                    'employee' => 'Сотрудник',
                    'booking_option' => 'Вариант бронирования',
                    'price' => 'Цена',
                    'message' => 'Сообщение',
                    'no_message' => 'Сообщение не предоставлено'
                ),
                'sv_SE' => array(
                    'new_booking_title' => 'Ny bokningsförfrågan',
                    'subject' => 'Ny bokningsförfrågan från %1$s för %2$s',
                    'company' => 'Företag',
                    'name' => 'Namn',
                    'email' => 'E-post',
                    'phone' => 'Telefon',
                    'date' => 'Datum',
                    'time' => 'Tid',
                    'service' => 'Tjänst',
                    'employee' => 'Anställd',
                    'booking_option' => 'Bokningsalternativ',
                    'price' => 'Pris',
                    'message' => 'Meddelande',
                    'no_message' => 'Inget meddelande angivet'
                )
            );
            
            // Fallback auf Deutsch wenn Sprache nicht gefunden
            $labels = isset($admin_labels[$current_language_for_admin]) ? $admin_labels[$current_language_for_admin] : $admin_labels['de_DE'];
            
            // Dienstleistung und Mitarbeiter laden für Admin-E-Mail
            $dienstleistung_admin = simpbook_get_dienstleistung($dienstleistung_id);
            $mitarbeiter_admin = $mitarbeiter_id > 0 ? simpbook_get_mitarbeiter($mitarbeiter_id) : null;
            $service_name_admin = $dienstleistung_admin ? $dienstleistung_admin->name : '';
            $employee_name_admin = $mitarbeiter_admin ? $mitarbeiter_admin->name : '';

            // Buchungsoption laden
            $buchungsoption_name_for_email = '';
            if ($buchungsoption_id_save > 0) {
                $bo_table_name = $wpdb->prefix . 'simpbook_buchungsoptionen';
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                $bo_row_email = $wpdb->get_row($wpdb->prepare("SELECT name FROM %i WHERE id = %d", $bo_table_name, $buchungsoption_id_save));
                $buchungsoption_name_for_email = $bo_row_email ? $bo_row_email->name : '';
            }

            // Buchungsoption-Preis laden
            $buchungsoption_preis_for_email = '';
            if ($buchungsoption_id_save > 0 && $dienstleistung_id > 0) {
                $dl_bo_table_email = $wpdb->prefix . 'simpbook_dienstleistung_buchungsoptionen';
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                $bo_preis_row = $wpdb->get_row($wpdb->prepare("SELECT preis FROM %i WHERE dienstleistung_id = %d AND buchungsoption_id = %d LIMIT 1", $dl_bo_table_email, $dienstleistung_id, $buchungsoption_id_save));
                if ($bo_preis_row && !empty($bo_preis_row->preis)) {
                    $buchungsoption_preis_for_email = $bo_preis_row->preis;
                }
            }

            // Sprachspezifischer Betreff
            $betreff_admin = sprintf($labels['subject'], $name, $firmen_name);
            
            // Erstelle E-Mail mit HTML-Formatierung und sprachspezifischen Labels
            $nachricht_admin_body = '<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">';
            $nachricht_admin_body .= '<h2 style="color: #1f2937; margin-bottom: 20px;">' . $labels['new_booking_title'] . '</h2>';
            $nachricht_admin_body .= '<div style="background: #f9fafb; padding: 20px; border-radius: 8px; margin-bottom: 20px;">';
            $nachricht_admin_body .= '<p style="margin: 8px 0;"><strong>' . $labels['company'] . ':</strong> ' . esc_html($firmen_name) . '</p>';
            $nachricht_admin_body .= '<p style="margin: 8px 0;"><strong>' . $labels['name'] . ':</strong> ' . esc_html($name) . '</p>';
            $nachricht_admin_body .= '<p style="margin: 8px 0;"><strong>' . $labels['email'] . ':</strong> ' . esc_html($email) . '</p>';
            $nachricht_admin_body .= '<p style="margin: 8px 0;"><strong>' . $labels['phone'] . ':</strong> ' . esc_html($telefon) . '</p>';
            $nachricht_admin_body .= '<p style="margin: 8px 0;"><strong>' . $labels['date'] . ':</strong> ' . esc_html($datum_input) . '</p>';
            $nachricht_admin_body .= '<p style="margin: 8px 0;"><strong>' . $labels['time'] . ':</strong> ' . esc_html($uhrzeit_input) . '</p>';
            $nachricht_admin_body .= '<p style="margin: 8px 0;"><strong>' . $labels['service'] . ':</strong> ' . esc_html($service_name_admin) . '</p>';
            if (!empty($employee_name_admin)) {
                $nachricht_admin_body .= '<p style="margin: 8px 0;"><strong>' . $labels['employee'] . ':</strong> ' . esc_html($employee_name_admin) . '</p>';
            }
            if (!empty($buchungsoption_name_for_email)) {
                $nachricht_admin_body .= '<p style="margin: 8px 0;"><strong>' . $labels['booking_option'] . ':</strong> ' . esc_html($buchungsoption_name_for_email) . '</p>';
            }
            $admin_preis_display = !empty($buchungsoption_preis_for_email) ? $buchungsoption_preis_for_email : (!empty($dienstleistung_admin->preis) ? $dienstleistung_admin->preis : '');
            if (!empty($admin_preis_display)) {
                $nachricht_admin_body .= '<p style="margin: 8px 0;"><strong>' . $labels['price'] . ':</strong> ' . esc_html($admin_preis_display) . '</p>';
            }
            // Custom field values
            if (!empty($custom_values)) {
                $form_fields_for_email = self::simpbook_get_form_fields_config();
                foreach ($custom_values as $cf_key => $cf_val) {
                    // Find the label from the form config
                    $cf_label = ucfirst(str_replace(['_', '-'], ' ', $cf_key));
                    if (!empty($form_fields_for_email['fields'])) {
                        foreach ($form_fields_for_email['fields'] as $cff) {
                            if (!empty($cff['key']) && sanitize_key($cff['key']) === $cf_key) {
                                $cf_label = !empty($cff['placeholder']) ? $cff['placeholder'] : (!empty($cff['label']) ? $cff['label'] : $cf_label);
                                break;
                            }
                        }
                    }
                    $nachricht_admin_body .= '<p style="margin: 8px 0;"><strong>' . esc_html($cf_label) . ':</strong> ' . esc_html($cf_val) . '</p>';
                }
            }

            $nachricht_admin_body .= '</div>';
            
            // Füge HTML-Buttons hinzu (mit Sprache)
            $button_html = $this->simpbook_generate_email_action_buttons($accept_url, $reject_url, $view_url, $current_language_for_admin);
            $nachricht_admin_body .= $button_html;
            $nachricht_admin_body .= '</div>';

            // Wrap in HTML email template mit Design-Farben
            $nachricht_admin_body = simpbook_build_admin_html_email($betreff_admin, $nachricht_admin_body, $firmen_name);
            
            // Headers für HTML-E-Mail
            $headers = array('Content-Type: text/html; charset=UTF-8');
            wp_mail($admin_email_ziel, $betreff_admin, $nachricht_admin_body, $headers);

            // Verwende leere Strings als Fallback, da simpbook_get_email_template() automatisch sprachspezifische Standardwerte verwendet
            $current_language_for_email = simpbook_get_current_language();
            // Formatiere Datum und Zeit für E-Mail basierend auf Sprache
            $datum_formatted = simpbook_format_date($datum_mysql, $current_language_for_email);
            $uhrzeit_formatted = simpbook_format_time($uhrzeit_input, $current_language_for_email);

            // Dienstleistung und Mitarbeiter laden für E-Mail-Platzhalter
            $dienstleistung = simpbook_get_dienstleistung($dienstleistung_id);
            $mitarbeiter = $mitarbeiter_id > 0 ? simpbook_get_mitarbeiter($mitarbeiter_id) : null;

            $service_name = $dienstleistung ? $dienstleistung->name : '';
            $employee_name = $mitarbeiter ? $mitarbeiter->name : '';
            $employee_name_label = __('Staff', 'simple-appointment-booking');

            // Stornierungslink generieren (nur für bestätigte Buchungen)
            $cancellation_link = '';
            if ($auto_bestaetigung) {
                $cancellation_link = home_url('/?simpbook_cancel=' . urlencode($stornierungs_token));
            }

            // Custom-Felder als Textblock aufbereiten (ersetzt {simpbook_nachricht} im E-Mail-Template)
            $custom_fields_email_block = '';
            if (!empty($custom_values)) {
                $cf_config_labels = self::simpbook_get_form_fields_config();
                foreach ($custom_values as $cf_key => $cf_val_block) {
                    $cf_lbl = ucfirst(str_replace(['_', '-'], ' ', $cf_key));
                    if (!empty($cf_config_labels['fields'])) {
                        foreach ($cf_config_labels['fields'] as $cff_item) {
                            if (!empty($cff_item['key']) && sanitize_key($cff_item['key']) === $cf_key) {
                                $cf_lbl = !empty($cff_item['placeholder']) ? $cff_item['placeholder'] : (!empty($cff_item['label']) ? $cff_item['label'] : $cf_lbl);
                                break;
                            }
                        }
                    }
                    $custom_fields_email_block .= $cf_lbl . ': ' . $cf_val_block . "\n";
                }
            }

            // Nachrichtenfeld (nicht mehr Systemfeld) + Custom-Felder kombinieren
            $gast_nachricht_fuer_email = $nachricht_text;
            if (!empty($custom_fields_email_block)) {
                $gast_nachricht_fuer_email .= (!empty($nachricht_text) ? "\n" : '') . rtrim($custom_fields_email_block);
            }

            $gast_daten = [
                'name' => $name,
                'email' => $email,
                'phone' => $telefon,
                'telefon' => $telefon,
                'date' => $datum_formatted,
                'datum' => $datum_formatted,
                'time' => $uhrzeit_formatted,
                'uhrzeit' => $uhrzeit_formatted,
                'message' => $gast_nachricht_fuer_email,
                'simpbook_nachricht' => $gast_nachricht_fuer_email,
                'service_name' => $service_name,
                'employee_name' => $employee_name,
                'employee_name_label' => $employee_name_label,
                'booking_option' => !empty($buchungsoption_name_for_email) ? (__('Booking Option', 'simple-appointment-booking') . ': ' . $buchungsoption_name_for_email) : '',
                'booking_price' => !empty($buchungsoption_preis_for_email) ? $buchungsoption_preis_for_email : (!empty($dienstleistung->preis) ? $dienstleistung->preis : ''),
                'company_name' => $firmen_name,
                'firmen_name' => $firmen_name, // Rückwärtskompatibilität
                'restaurant_name' => $firmen_name, // Fallback für Kompatibilität
                'cancellation_link' => $cancellation_link
            ];

            // Custom field values als individuelle Platzhalter {field_key} verfügbar machen
            if (!empty($custom_values)) {
                foreach ($custom_values as $cf_key => $cf_value) {
                    $gast_daten[$cf_key] = $cf_value;
                }
            }
            
            // Bestimme welche E-Mail-Vorlage an den Kunden gesendet wird
            if ($auto_bestaetigung) {
                // Bei Auto-Bestätigung: Sende Bestätigungs-E-Mail (wie manuell bestätigt)
                $gast_betreff = $this->simpbook_ersetze_platzhalter(simpbook_get_email_template('simpbook_email_bestaetigt_betreff', '', $current_language_for_email), $gast_daten);
                $gast_nachricht_body = $this->simpbook_ersetze_platzhalter(simpbook_get_email_template('simpbook_email_bestaetigt_nachricht', '', $current_language_for_email), $gast_daten);
                $gast_email_option_key = 'simpbook_email_bestaetigt_nachricht';
            } else {
                // Bei manueller Bestätigung: Sende Buchungsbestätigungs-E-Mail (Warten auf Admin)
                $gast_betreff = $this->simpbook_ersetze_platzhalter(simpbook_get_email_template('simpbook_email_bestaetigungs_betreff', '', $current_language_for_email), $gast_daten);
                $gast_nachricht_body = $this->simpbook_ersetze_platzhalter(simpbook_get_email_template('simpbook_email_bestaetigungs_nachricht', '', $current_language_for_email), $gast_daten);
                $gast_email_option_key = 'simpbook_email_bestaetigungs_nachricht';
            }

            // Prüfe ob E-Mail-Benachrichtigungen aktiviert sind
            if (simpbook_get_option('simpbook_email_benachrichtigungen', '1') === '1') {
                $gast_html_body = simpbook_build_guest_html_email($gast_betreff, $gast_nachricht_body, $firmen_name, $gast_email_option_key);
                $gast_html_headers = array('Content-Type: text/html; charset=UTF-8');
                wp_mail($email, $gast_betreff, $gast_html_body, $gast_html_headers);
            }

            // 🔔 Push-Notification an PWA senden (falls aktiviert)
            if (get_option('simpbook_pwa_push_enabled', '0') === '1') {
                // PWA Controller laden und Push senden
                if (class_exists('Simpbook_PWA_Controller')) {
                    $pwa_controller = Simpbook_PWA_Controller::get_instance();
                    
                    // Hole aktuelle Plugin-Sprache
                    $language = simpbook_get_current_language();
                    
                    // Push-Titel mit Übersetzung
                    $push_title = simpbook_get_push_translation('push_new_booking_title', $language);
                    
                    // Push-Body mit Name (verwendet Translation Key 'push_new_booking_body')
                    $body_template = simpbook_get_push_translation('push_new_booking_body', $language);
                    $push_body_line1 = sprintf($body_template, $name);
                    
                    // Details mit Service, Datum, Uhrzeit (verwendet Translation Key 'push_booking_details')
                    $details_template = simpbook_get_push_translation('push_booking_details', $language);
                    $push_body_line2 = sprintf($details_template, $service_name, $datum_formatted, $uhrzeit_formatted);
                    
                    // Kombiniere beide Zeilen
                    $push_body = $push_body_line1 . "\n" . $push_body_line2;
                    
                    // URL zur Reservierung (direkt zur Bearbeitung)
                    $push_url = admin_url('admin.php?page=simpbook-reservierungen&simpbook_aktion=bearbeiten&simpbook_id=' . $reservierung_id . '&pwa=1');
                    
                    // Push senden
                    $pwa_controller->send_push_notification($push_title, $push_body, $push_url);
                    
                    // error_log('[Simpbook Push] New reservation push sent: ' . $push_title);
                }
            }

            wp_send_json_success(__('Your reservation has been successfully sent and a confirmation has been sent to your email address.', 'simple-appointment-booking'));
        } else {
            wp_send_json_error(__('There was a problem saving your reservation. Please try again later.', 'simple-appointment-booking'));
        }
        exit;
    }

    /**
     * Ruft verfügbare Zeiten für ein bestimmtes Datum ab.
     * Berücksichtigt jetzt spezielle Tagesöffnungszeiten.
     */
    /**
     * AJAX-Handler: Lädt Mitarbeiter für eine Dienstleistung
     */
    /**
     * AJAX-Handler: Lädt Mitarbeiter für eine Dienstleistung
     */
    /**
     * AJAX-Handler: Speichert eine Dienstleistung
     */
    public function simpbook_ajax_save_dienstleistung() {
        // Nonce-Prüfung
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_dienstleistung_speichern')) {
            wp_send_json_error(__('Security check failed', 'simple-appointment-booking'));
            exit;
        }

        global $wpdb;
        $table_name = $wpdb->prefix . 'dienstleistungen';
        $relation_table = $wpdb->prefix . 'mitarbeiter_dienstleistungen';

        $dienstleistung_id = isset($_POST['simpbook_dienstleistung_id']) ? intval($_POST['simpbook_dienstleistung_id']) : 0;
        $name = isset($_POST['simpbook_name']) ? sanitize_text_field(wp_unslash($_POST['simpbook_name'])) : '';
        $kategorie_id = isset($_POST['simpbook_kategorie_id']) && !empty($_POST['simpbook_kategorie_id']) ? intval($_POST['simpbook_kategorie_id']) : null;
        $dauer_minuten = isset($_POST['simpbook_dauer_minuten']) ? intval($_POST['simpbook_dauer_minuten']) : 30;
        $pufferzeit_minuten = isset($_POST['simpbook_pufferzeit_minuten']) ? intval($_POST['simpbook_pufferzeit_minuten']) : 0;
        $beschreibung = isset($_POST['simpbook_beschreibung']) ? wp_kses_post(wp_unslash($_POST['simpbook_beschreibung'])) : '';
        $aktiv = isset($_POST['simpbook_aktiv']) ? intval($_POST['simpbook_aktiv']) : 0;
        $sortierung = isset($_POST['simpbook_sortierung']) ? intval($_POST['simpbook_sortierung']) : 0;
        $preis = isset($_POST['simpbook_preis']) ? sanitize_text_field(wp_unslash($_POST['simpbook_preis'])) : '';
        $preis_anzeigen = isset($_POST['simpbook_preis_anzeigen']) ? intval($_POST['simpbook_preis_anzeigen']) : 0;
        $bild_id = isset($_POST['simpbook_bild_id']) ? intval($_POST['simpbook_bild_id']) : 0;
        $ohne_mitarbeiter = (isset($_POST['simpbook_ohne_mitarbeiter']) && $_POST['simpbook_ohne_mitarbeiter'] === '1') ? 1 : 0;

        // Verfügbarkeit speichern
        $verfuegbarkeit_type = 'regular';
        if (isset($_POST['simpbook_verfuegbarkeit_type'])) {
            $vt = sanitize_text_field(wp_unslash($_POST['simpbook_verfuegbarkeit_type']));
            if (in_array($vt, ['regular', 'weekdays', 'special_dates'], true)) {
                $verfuegbarkeit_type = $vt;
            }
        }
        $verfuegbarkeit_weekday_times = [];
        if ($verfuegbarkeit_type === 'weekdays' && isset($_POST['simpbook_weekday_times']) && is_array($_POST['simpbook_weekday_times'])) {
            foreach (wp_unslash($_POST['simpbook_weekday_times']) as $day_num => $wt) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
                $day_num = intval($day_num);
                if ($day_num < 1 || $day_num > 7) continue;
                if (empty($wt['enabled'])) continue;
                $time_from = sanitize_text_field($wt['time_from'] ?? '09:00');
                $time_to   = sanitize_text_field($wt['time_to']   ?? '17:00');
                if (!preg_match('/^\d{2}:\d{2}$/', $time_from)) $time_from = '09:00';
                if (!preg_match('/^\d{2}:\d{2}$/', $time_to))   $time_to   = '17:00';
                $verfuegbarkeit_weekday_times[$day_num] = [
                    'time_from' => $time_from,
                    'time_to'   => $time_to,
                ];
            }
        }
        $verfuegbarkeit_special_dates = [];
        if ($verfuegbarkeit_type === 'special_dates' && isset($_POST['simpbook_special_dates']) && is_array($_POST['simpbook_special_dates'])) {
            foreach (wp_unslash($_POST['simpbook_special_dates']) as $sd) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
                if (empty($sd['date'])) continue;
                $date = sanitize_text_field($sd['date']);
                if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) continue;
                $time_from = sanitize_text_field($sd['time_from'] ?? '09:00');
                $time_to   = sanitize_text_field($sd['time_to']   ?? '17:00');
                if (!preg_match('/^\d{2}:\d{2}$/', $time_from)) $time_from = '09:00';
                if (!preg_match('/^\d{2}:\d{2}$/', $time_to))   $time_to   = '17:00';
                $verfuegbarkeit_special_dates[] = [
                    'date'      => $date,
                    'time_from' => $time_from,
                    'time_to'   => $time_to,
                ];
            }
        }
        $verfuegbarkeit_json = wp_json_encode([
            'type'          => $verfuegbarkeit_type,
            'weekday_times' => $verfuegbarkeit_weekday_times,
            'special_dates' => $verfuegbarkeit_special_dates,
        ]);

        // Mitarbeiter-Array aus POST holen
        $mitarbeiter_ids = [];
        if (isset($_POST['simpbook_mitarbeiter']) && is_array($_POST['simpbook_mitarbeiter'])) {
            $mitarbeiter_ids = array_map('intval', wp_unslash($_POST['simpbook_mitarbeiter']));
        }

        if (empty($name)) {
            wp_send_json_error(__('Bitte geben Sie einen Namen ein.', 'simple-appointment-booking'));
            exit;
        }

        $data = [
            'name' => $name,
            'kategorie_id' => $kategorie_id,
            'dauer_minuten' => $dauer_minuten,
            'pufferzeit_minuten' => $pufferzeit_minuten,
            'beschreibung' => $beschreibung,
            'aktiv' => $aktiv,
            'sortierung' => $sortierung,
            'preis' => $preis,
            'preis_anzeigen' => $preis_anzeigen,
            'bild_id' => $bild_id,
            'ohne_mitarbeiter' => $ohne_mitarbeiter,
            'verfuegbarkeit' => $verfuegbarkeit_json,
        ];

        // Format-Array für $data
        $data_format = ['%s', '%d', '%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%s'];
        if ($kategorie_id === null) {
            $data['kategorie_id'] = null;
            // NULL-Wert benötigt kein Format
        }

        if ($dienstleistung_id > 0) {
            // Aktualisieren
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $result = $wpdb->update($table_name, $data, ['id' => $dienstleistung_id], $data_format, ['%d']);
            if ($result !== false) {
                // Mitarbeiter-Verknüpfungen aktualisieren
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                $wpdb->delete($relation_table, ['dienstleistung_id' => $dienstleistung_id], ['%d']);
                foreach ($mitarbeiter_ids as $mitarbeiter_id) {
                    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                    $wpdb->insert($relation_table, ['mitarbeiter_id' => $mitarbeiter_id, 'dienstleistung_id' => $dienstleistung_id], ['%d', '%d']);
                }
                $this->simpbook_save_buchungsoptionen_for_dienstleistung($dienstleistung_id);
                wp_send_json_success(__('Service successfully updated.', 'simple-appointment-booking'));
            } else {
                wp_send_json_error(__('Fehler beim Aktualisieren der Dienstleistung.', 'simple-appointment-booking'));
            }
        } else {
            // Neu erstellen
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $result = $wpdb->insert($table_name, $data, $data_format);
            if ($result !== false) {
                $new_id = $wpdb->insert_id;
                // Mitarbeiter-Verknüpfungen erstellen
                foreach ($mitarbeiter_ids as $mitarbeiter_id) {
                    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                    $wpdb->insert($relation_table, ['mitarbeiter_id' => $mitarbeiter_id, 'dienstleistung_id' => $new_id], ['%d', '%d']);
                }
                $this->simpbook_save_buchungsoptionen_for_dienstleistung($new_id);
                wp_send_json_success(__('Dienstleistung erfolgreich erstellt.', 'simple-appointment-booking'));
            } else {
                wp_send_json_error(__('Fehler beim Erstellen der Dienstleistung.', 'simple-appointment-booking'));
            }
        }
        exit;
    }

    /**
     * Speichert Buchungsoptionen für eine Dienstleistung (aus POST-Daten).
     */
    private function simpbook_save_buchungsoptionen_for_dienstleistung($dienstleistung_id) {
        global $wpdb;
        $bo_table = $wpdb->prefix . 'simpbook_dienstleistung_buchungsoptionen';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->delete($bo_table, ['dienstleistung_id' => $dienstleistung_id], ['%d']);
        if (!isset($_POST['simpbook_buchungsoption_ids']) || !is_array($_POST['simpbook_buchungsoption_ids'])) {
            return;
        }
        $bo_ids    = array_map('intval', wp_unslash($_POST['simpbook_buchungsoption_ids']));
        $bo_preise = isset($_POST['simpbook_buchungsoption_preise']) && is_array($_POST['simpbook_buchungsoption_preise'])
            ? array_map('sanitize_text_field', array_map('wp_unslash', $_POST['simpbook_buchungsoption_preise']))
            : [];
        foreach ($bo_ids as $idx => $bo_id) {
            if ($bo_id > 0) {
                $preis = isset($bo_preise[$idx]) ? $bo_preise[$idx] : '';
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                $wpdb->insert($bo_table, [
                    'dienstleistung_id' => $dienstleistung_id,
                    'buchungsoption_id' => $bo_id,
                    'preis'             => $preis,
                    'sortierung'        => $idx,
                ], ['%d', '%d', '%s', '%d']);
            }
        }
    }

    public function simpbook_ajax_get_mitarbeiter_zuweisung_for_dienstleistung() {
        // Nonce-Prüfung (optional, da öffentlich zugänglich)
        if (isset($_POST['simpbook_nonce'])) {
            $nonce = sanitize_text_field(wp_unslash($_POST['simpbook_nonce']));
            // Prüfe simpbook_ Nonce-Namen
            if (!wp_verify_nonce($nonce, 'simpbook_get_available_times_nonce') &&
                !wp_verify_nonce($nonce, 'simpbook_mitarbeiter_nonce')) {
                // Nonce-Prüfung optional für öffentliche Anfragen
            }
        }

        global $wpdb;
        $relation_table = $wpdb->prefix . 'mitarbeiter_dienstleistungen';
        $mitarbeiter_table = $wpdb->prefix . 'mitarbeiter';

        $dienstleistung_id = isset($_POST['simpbook_dienstleistung_id']) ? intval($_POST['simpbook_dienstleistung_id']) : 0;

        // Alle Mitarbeiter laden
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
        $alle_mitarbeiter = $wpdb->get_results($wpdb->prepare("SELECT * FROM %i ORDER BY sortierung ASC, name ASC", $mitarbeiter_table));

        // Zugewiesene Mitarbeiter laden
        $zugewiesene = [];
        if ($dienstleistung_id > 0) {
            $zugewiesene = $wpdb->get_col($wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
                "SELECT mitarbeiter_id FROM %i WHERE dienstleistung_id = %d",
                $relation_table,
                $dienstleistung_id
            ));
            $zugewiesene = array_map('intval', $zugewiesene);
        }

        // HTML für Checkboxes generieren
        $html = '';
        if (empty($alle_mitarbeiter)) {
            $html = '<p style="color: #999;">' . esc_html__('No staff members available. Please create staff members first.', 'simple-appointment-booking') . '</p>';
        } else {
            foreach ($alle_mitarbeiter as $mitarbeiter) {
                $checked = in_array($mitarbeiter->id, $zugewiesene) ? 'checked' : '';
                $html .= '<label style="display: block; padding: 8px 0; border-bottom: 1px solid #eee;">';
                $html .= '<input type="checkbox" name="simpbook_mitarbeiter[]" value="' . esc_attr($mitarbeiter->id) . '" ' . esc_attr($checked) . '> ';
                $html .= esc_html($mitarbeiter->name);
                $html .= '</label>';
            }
        }

        wp_send_json_success(['html' => $html]); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- AJAX response only
        exit;
    }

    public function simpbook_ajax_toggle_dienstleistung_status() {
        $simpbook_id = isset($_POST['simpbook_id']) ? intval($_POST['simpbook_id']) : 0;
        // Nonce-Prüfung
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Input validated and sanitized on use
        if (!isset($_POST['_wpnonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce'])), 'toggle_dienstleistung_' . $simpbook_id)) {
            wp_send_json_error(__('Security check failed', 'simple-appointment-booking'));
            exit;
        }

        global $wpdb;
        $table_name = $wpdb->prefix . 'dienstleistungen';
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- isset check performed
        $id = $simpbook_id;
        $status = isset($_POST['simpbook_status']) ? intval($_POST['simpbook_status']) : 0;

        if ($id < 1) {
            wp_send_json_error(__('Invalid service ID', 'simple-appointment-booking'));
            exit;
        }

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $result = $wpdb->update($table_name, ['aktiv' => $status], ['id' => $id], ['%d'], ['%d']);

        if ($result !== false) {
            wp_send_json_success(__('Status changed successfully.', 'simple-appointment-booking'));
        } else {
            wp_send_json_error(__('Error changing the status.', 'simple-appointment-booking'));
        }
        exit;
    }

    public function simpbook_ajax_delete_dienstleistung() {
        global $wpdb;
        $table_name = $wpdb->prefix . 'dienstleistungen';
        $id = isset($_POST['simpbook_id']) ? intval($_POST['simpbook_id']) : 0;

        // Nonce-Prüfung
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'delete_dienstleistung_' . $id)) {
            wp_send_json_error(__('Security check failed', 'simple-appointment-booking'));
            exit;
        }

        if ($id < 1) {
            wp_send_json_error(__('Invalid service ID', 'simple-appointment-booking'));
            exit;
        }

        // Prüfe ob Dienstleistung in Reservierungen verwendet wird
        $reservierungen_table = $wpdb->prefix . 'buchungen';
        $in_use = $wpdb->get_var($wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
            "SELECT COUNT(*) FROM %i WHERE dienstleistung_id = %d",
            $reservierungen_table,
            $id
        ));

        if ($in_use > 0) {
            wp_send_json_error(__('This service cannot be deleted because it is used in reservations.', 'simple-appointment-booking'));
            exit;
        }

        // Lösche auch die Verknüpfungen in mitarbeiter_dienstleistungen
        $mitarbeiter_dienstleistungen_table = $wpdb->prefix . 'mitarbeiter_dienstleistungen';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->delete($mitarbeiter_dienstleistungen_table, ['dienstleistung_id' => $id], ['%d']);

        // Lösche die Dienstleistung
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $result = $wpdb->delete($table_name, ['id' => $id], ['%d']);

        if ($result !== false) {
            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- AJAX success response
            wp_send_json_success(__('Service successfully deleted.', 'simple-appointment-booking'));
        } else {
            wp_send_json_error(__('Error deleting the service.', 'simple-appointment-booking'));
        }
        exit;
    }

    public function simpbook_ajax_duplicate_dienstleistung() {
        $id = isset($_POST['simpbook_id']) ? intval($_POST['simpbook_id']) : 0;
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_duplicate_dienstleistung_' . $id)) {
            wp_send_json_error(__('Security check failed', 'simple-appointment-booking'));
            exit;
        }
        if (!current_user_can('read') || $id < 1) {
            wp_send_json_error(__('No permission or invalid ID', 'simple-appointment-booking'));
            exit;
        }
        global $wpdb;
        $table = $wpdb->prefix . 'dienstleistungen';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $original = $wpdb->get_row($wpdb->prepare("SELECT * FROM %i WHERE id = %d", $table, $id));
        if (!$original) {
            wp_send_json_error(__('Dienstleistung nicht gefunden', 'simple-appointment-booking'));
            exit;
        }
        $data = [
            'name'               => $original->name . ' ' . __('(Kopie)', 'simple-appointment-booking'),
            'dauer_minuten'      => $original->dauer_minuten,
            'pufferzeit_minuten' => $original->pufferzeit_minuten,
            'beschreibung'       => $original->beschreibung,
            'aktiv'              => $original->aktiv,
            'sortierung'         => $original->sortierung + 1,
            'preis'              => $original->preis,
            'preis_anzeigen'     => $original->preis_anzeigen,
            'bild_id'            => $original->bild_id,
            'kategorie_id'       => $original->kategorie_id,
            'ohne_mitarbeiter'   => $original->ohne_mitarbeiter,
            'verfuegbarkeit'     => isset($original->verfuegbarkeit) ? $original->verfuegbarkeit : null,
        ];
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
        $result = $wpdb->insert($table, $data);
        if ($result === false) {
            wp_send_json_error(__('Fehler beim Duplizieren', 'simple-appointment-booking'));
            exit;
        }
        $new_id = $wpdb->insert_id;

        // Mitarbeiter-Zuweisungen duplizieren
        $relation_table = $wpdb->prefix . 'mitarbeiter_dienstleistungen';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $mitarbeiter_rows = $wpdb->get_results($wpdb->prepare(
            "SELECT mitarbeiter_id FROM %i WHERE dienstleistung_id = %d",
            $relation_table, $id
        ));
        foreach ($mitarbeiter_rows as $row) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
            $wpdb->insert($relation_table, [
                'mitarbeiter_id'    => $row->mitarbeiter_id,
                'dienstleistung_id' => $new_id,
            ], ['%d', '%d']);
        }

        // Buchungsoptionen duplizieren
        $bo_table = $wpdb->prefix . 'simpbook_dienstleistung_buchungsoptionen';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $bo_rows = $wpdb->get_results($wpdb->prepare(
            "SELECT buchungsoption_id, preis, sortierung FROM %i WHERE dienstleistung_id = %d ORDER BY sortierung ASC",
            $bo_table, $id
        ));
        foreach ($bo_rows as $bo) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
            $wpdb->insert($bo_table, [
                'dienstleistung_id' => $new_id,
                'buchungsoption_id' => $bo->buchungsoption_id,
                'preis'             => $bo->preis,
                'sortierung'        => $bo->sortierung,
            ], ['%d', '%d', '%s', '%d']);
        }

        wp_send_json_success(['new_id' => $new_id]);
        exit;
    }

    public function simpbook_ajax_reorder_dienstleistungen() {
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_reorder_dienstleistungen')) {
            wp_send_json_error(__('Security check failed', 'simple-appointment-booking'));
            exit;
        }
        if (!current_user_can('read')) {
            wp_send_json_error(__('Keine Berechtigung', 'simple-appointment-booking'));
            exit;
        }
        if (!isset($_POST['simpbook_ids']) || !is_array($_POST['simpbook_ids'])) {
            wp_send_json_error(__('Invalid data', 'simple-appointment-booking'));
            exit;
        }
        global $wpdb;
        $table = $wpdb->prefix . 'dienstleistungen';
        $ids = array_map('intval', wp_unslash($_POST['simpbook_ids']));
        foreach ($ids as $order => $id) {
            if ($id < 1) continue;
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->update($table, ['sortierung' => $order], ['id' => $id], ['%d'], ['%d']);
        }
        wp_send_json_success();
        exit;
    }

    public function simpbook_ajax_delete_mitarbeiter() {
        $simpbook_id = isset($_POST['simpbook_id']) ? intval($_POST['simpbook_id']) : 0;
        // Nonce-Prüfung
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Input validated and sanitized on use
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_delete_mitarbeiter_' . $simpbook_id)) {
            wp_send_json_error(__('Security check failed', 'simple-appointment-booking'));
            exit;
        }

        global $wpdb;
        $table_name = $wpdb->prefix . 'mitarbeiter';
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- isset check performed
        $id = $simpbook_id;

        if ($id < 1) {
            wp_send_json_error(__('Invalid staff member ID', 'simple-appointment-booking'));
            exit;
        }

        // Prüfe ob Mitarbeiter in Reservierungen verwendet wird
        $reservierungen_table = $wpdb->prefix . 'buchungen';
        $in_use = $wpdb->get_var($wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
            "SELECT COUNT(*) FROM %i WHERE mitarbeiter_id = %d",
            $reservierungen_table,
            $id
        ));

        if ($in_use > 0) {
            wp_send_json_error(__('This staff member cannot be deleted because they are used in reservations.', 'simple-appointment-booking'));
            exit;
        }

        // Profilfoto löschen wenn vorhanden
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
        $mitarbeiter = $wpdb->get_row($wpdb->prepare("SELECT profilfoto_url FROM %i WHERE id = %d", $table_name, $id));
        if ($mitarbeiter && !empty($mitarbeiter->profilfoto_url)) {
            $attachment_id = attachment_url_to_postid($mitarbeiter->profilfoto_url);
            if ($attachment_id) {
                wp_delete_attachment($attachment_id, true);
            }
        }

        // Lösche auch die Verknüpfungen in mitarbeiter_dienstleistungen
        $mitarbeiter_dienstleistungen_table = $wpdb->prefix . 'mitarbeiter_dienstleistungen';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->delete($mitarbeiter_dienstleistungen_table, ['mitarbeiter_id' => $id], ['%d']);

        // Lösche den Mitarbeiter
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $result = $wpdb->delete($table_name, ['id' => $id], ['%d']);

        if ($result !== false) {
            wp_send_json_success(__('Staff member successfully deleted.', 'simple-appointment-booking'));
        } else {
            wp_send_json_error(__('Error deleting the staff member.', 'simple-appointment-booking'));
        }
        exit;
    }

    public function simpbook_ajax_get_mitarbeiter_fuer_dienstleistung() {
        // Nonce-Prüfung (optional, da öffentlich zugänglich)
        if (isset($_POST['simpbook_nonce'])) {
            $nonce = sanitize_text_field(wp_unslash($_POST['simpbook_nonce']));
            // Prüfe simpbook_ Nonce-Namen
            if (!wp_verify_nonce($nonce, 'simpbook_get_available_times_nonce') &&
                !wp_verify_nonce($nonce, 'simpbook_mitarbeiter_nonce')) {
                // Nonce-Prüfung optional für öffentliche Anfragen
            }
        }

        $dienstleistung_id = isset($_POST['simpbook_dienstleistung_id']) ? intval($_POST['simpbook_dienstleistung_id']) : 0;
        $datum_input = isset($_POST['simpbook_datum']) ? sanitize_text_field(wp_unslash($_POST['simpbook_datum'])) : '';

        if ($dienstleistung_id < 1) {
            wp_send_json_error(__('Invalid service ID', 'simple-appointment-booking'));
            exit;
        }

        // Mitarbeiter für diese Dienstleistung laden
        // $only_active = true: Nur aktive Mitarbeiter
        // $only_frontend = false: Im Backend alle aktiven Mitarbeiter anzeigen (nicht nur Frontend-Mitarbeiter)
        $is_admin = is_admin();
        $only_frontend = !$is_admin; // Im Frontend nur Frontend-Mitarbeiter, im Backend alle
        $mitarbeiter = simpbook_get_mitarbeiter_fuer_dienstleistung($dienstleistung_id, true, $only_frontend);

        // Wenn ein Datum angegeben wurde, prüfe individuelle Arbeitszeiten
        $gefilterte_mitarbeiter = [];
        if (!empty($datum_input)) {
            // Datum parsen
            $datum_obj = false;
            // Format 1: d.m.Y oder dd.mm.yyyy (europäische Schreibweise)
            $datum_obj = DateTime::createFromFormat('d.m.Y', $datum_input);
            // Format 2: d.m.y oder dd.mm.yy
            if ($datum_obj === false) {
                $datum_obj = DateTime::createFromFormat('d.m.y', $datum_input);
            }
            // Format 3: m/d/Y oder mm/dd/yyyy (US-Format)
            if ($datum_obj === false) {
                $datum_obj = DateTime::createFromFormat('m/d/Y', $datum_input);
            }
            // Format 4: m/d/y oder mm/dd/yy
            if ($datum_obj === false) {
                $datum_obj = DateTime::createFromFormat('m/d/y', $datum_input);
            }
            // Format 5: Y-m-d (ISO-Format)
            if ($datum_obj === false) {
                $datum_obj = DateTime::createFromFormat('Y-m-d', $datum_input);
            }
            // Fallback: strtotime
            if ($datum_obj === false) {
                $timestamp = strtotime($datum_input);
                if ($timestamp !== false) {
                    $datum_obj = new DateTime();
                    $datum_obj->setTimestamp($timestamp);
                }
            }

            if ($datum_obj !== false) {
                // Wochentag bestimmen
                $wochentag_php = strtolower($datum_obj->format('l'));
                $wochentag_key_map = [
                    'monday' => 'montag',
                    'tuesday' => 'dienstag',
                    'wednesday' => 'mittwoch',
                    'thursday' => 'donnerstag',
                    'friday' => 'freitag',
                    'saturday' => 'samstag',
                    'sunday' => 'sonntag'
                ];
                $wochentag_key = $wochentag_key_map[$wochentag_php] ?? 'montag';

                foreach ($mitarbeiter as $m) {
                    // Prüfe individuelle Arbeitszeiten
                    $arbeitszeiten = simpbook_get_mitarbeiter_arbeitszeiten($m->id);
                    if ($arbeitszeiten) {
                        // Mitarbeiter hat individuelle Arbeitszeiten
                        if (isset($arbeitszeiten[$wochentag_key]) && $arbeitszeiten[$wochentag_key]['aktiv'] === '1') {
                            // Mitarbeiter arbeitet an diesem Tag
                            $gefilterte_mitarbeiter[] = $m;
                        }
                        // Wenn nicht aktiv, wird Mitarbeiter nicht hinzugefügt
                    } else {
                        // Keine individuellen Arbeitszeiten - globale Öffnungszeiten verwenden
                        // Prüfe globale Öffnungszeiten
                        $default_map = simpbook_get_default_settings_map();
                        $wochentag_zeiten_cfg = simpbook_get_option('simpbook_wochentag_zeiten', $default_map['simpbook_wochentag_zeiten']);
                        if (isset($wochentag_zeiten_cfg[$wochentag_key]) && $wochentag_zeiten_cfg[$wochentag_key]['aktiv'] === '1') {
                            // Globaler Tag ist aktiv
                            $gefilterte_mitarbeiter[] = $m;
                        }
                    }
                }
            } else {
                // Datum konnte nicht geparst werden - alle Mitarbeiter zurückgeben
                $gefilterte_mitarbeiter = $mitarbeiter;
            }
        } else {
            // Kein Datum angegeben - alle Mitarbeiter zurückgeben
            $gefilterte_mitarbeiter = $mitarbeiter;
        }

        // Daten für JSON vorbereiten
        $mitarbeiter_data = [];
        $has_employee_without_custom_hours = false; // Prüfe ob mindestens einer ohne individuelle Arbeitszeiten ist

        foreach ($gefilterte_mitarbeiter as $m) {
            // Prüfe ob dieser Mitarbeiter individuelle Arbeitszeiten hat
            $arbeitszeiten = simpbook_get_mitarbeiter_arbeitszeiten($m->id);
            $has_custom_hours = !empty($arbeitszeiten);

            if (!$has_custom_hours) {
                $has_employee_without_custom_hours = true;
            }

            $mitarbeiter_data[] = [
                'id' => intval($m->id),
                'name' => $m->name,
                'profilfoto_url' => !empty($m->profilfoto_url) ? $m->profilfoto_url : '',
                'has_custom_hours' => $has_custom_hours
            ];
        }

        // Wenn ein Datum angegeben wurde und keine Mitarbeiter verfügbar sind, zusätzliche Info mitsenden
        $has_available_employees = count($mitarbeiter_data) > 0;
        
        // Prüfe ob überhaupt Mitarbeiter in der Datenbank existieren (unabhängig von der Dienstleistung)
        $has_any_employees = count($mitarbeiter) > 0;
        
        $response_data = [
            'mitarbeiter' => $mitarbeiter_data,
            'has_available_employees' => $has_available_employees,
            'has_employee_without_custom_hours' => $has_employee_without_custom_hours,
            'has_employees' => $has_any_employees // Ob überhaupt Mitarbeiter existieren
        ];

        wp_send_json_success($response_data);
        exit;
    }

    /**
     * AJAX Handler: Get available employees for a specific service and date
     * Used in the backend reservation form to filter employees by date availability
     */
    public function simpbook_ajax_get_available_employees_for_service_date() {
        // Nonce-Prüfung
        if (isset($_POST['simpbook_nonce'])) {
            $nonce = sanitize_text_field(wp_unslash($_POST['simpbook_nonce']));
            if (!wp_verify_nonce($nonce, 'simpbook_mitarbeiter_nonce')) {
                wp_send_json_error(__('Security check failed', 'simple-appointment-booking'));
                exit;
            }
        }

        // Backend only
        if (!is_admin()) {
            wp_send_json_error(__('Zugriff verweigert', 'simple-appointment-booking'));
            exit;
        }

        $dienstleistung_id = isset($_POST['simpbook_dienstleistung_id']) ? intval($_POST['simpbook_dienstleistung_id']) : 0;
        $datum_input = isset($_POST['simpbook_datum']) ? sanitize_text_field(wp_unslash($_POST['simpbook_datum'])) : '';

        if ($dienstleistung_id < 1) {
            wp_send_json_error(__('Invalid service ID', 'simple-appointment-booking'));
            exit;
        }

        if (empty($datum_input)) {
            wp_send_json_error(__('Datum erforderlich', 'simple-appointment-booking'));
            exit;
        }

        // Mitarbeiter für diese Dienstleistung laden
        $mitarbeiter = simpbook_get_mitarbeiter_fuer_dienstleistung($dienstleistung_id, true, false);

        // Datum parsen
        $datum_obj = false;
        $formats = ['d.m.Y', 'd.m.y', 'm/d/Y', 'm/d/y', 'Y-m-d'];

        foreach ($formats as $format) {
            $datum_obj = DateTime::createFromFormat($format, $datum_input);
            if ($datum_obj !== false) {
                break;
            }
        }

        // Fallback: strtotime
        if ($datum_obj === false) {
            $timestamp = strtotime($datum_input);
            if ($timestamp !== false) {
                $datum_obj = new DateTime();
                $datum_obj->setTimestamp($timestamp);
            }
        }

        if ($datum_obj === false) {
            wp_send_json_error(__('Datum konnte nicht geparst werden', 'simple-appointment-booking'));
            exit;
        }

        // Wochentag bestimmen
        $wochentag_php = strtolower($datum_obj->format('l'));
        $wochentag_key_map = [
            'monday' => 'montag',
            'tuesday' => 'dienstag',
            'wednesday' => 'mittwoch',
            'thursday' => 'donnerstag',
            'friday' => 'freitag',
            'saturday' => 'samstag',
            'sunday' => 'sonntag'
        ];
        $wochentag_key = $wochentag_key_map[$wochentag_php] ?? 'montag';

        // Gefilterte Mitarbeiter für dieses Datum
        $gefilterte_mitarbeiter = [];

        foreach ($mitarbeiter as $m) {
            // Prüfe individuelle Arbeitszeiten
            $arbeitszeiten = simpbook_get_mitarbeiter_arbeitszeiten($m->id);
            if ($arbeitszeiten) {
                // Mitarbeiter hat individuelle Arbeitszeiten
                if (isset($arbeitszeiten[$wochentag_key]) && $arbeitszeiten[$wochentag_key]['aktiv'] === '1') {
                    // Mitarbeiter arbeitet an diesem Tag
                    $gefilterte_mitarbeiter[] = $m;
                }
            } else {
                // Keine individuellen Arbeitszeiten - globale Öffnungszeiten verwenden
                $default_map = simpbook_get_default_settings_map();
                $wochentag_zeiten_cfg = simpbook_get_option('simpbook_wochentag_zeiten', $default_map['simpbook_wochentag_zeiten']);
                if (isset($wochentag_zeiten_cfg[$wochentag_key]) && $wochentag_zeiten_cfg[$wochentag_key]['aktiv'] === '1') {
                    // Globaler Tag ist aktiv
                    $gefilterte_mitarbeiter[] = $m;
                }
            }
        }

        // Daten für JSON vorbereiten
        $mitarbeiter_data = [];
        $has_employee_without_custom_hours = false; // Prüfe ob mindestens einer ohne individuelle Arbeitszeiten ist

        foreach ($gefilterte_mitarbeiter as $m) {
            // Prüfe ob dieser Mitarbeiter individuelle Arbeitszeiten hat
            $arbeitszeiten = simpbook_get_mitarbeiter_arbeitszeiten($m->id);
            $has_custom_hours = !empty($arbeitszeiten);

            if (!$has_custom_hours) {
                $has_employee_without_custom_hours = true;
            }

            $mitarbeiter_data[] = [
                'id' => intval($m->id),
                'name' => $m->name,
                'notice' => '',
                'has_custom_hours' => $has_custom_hours
            ];
        }

        $response_data = [
            'mitarbeiter' => $mitarbeiter_data,
            'wochentag' => $wochentag_key,
            'datum' => $datum_obj->format('d.m.Y'),
            'has_employee_without_custom_hours' => $has_employee_without_custom_hours
        ];

        wp_send_json_success($response_data);
        exit;
    }

    public function simpbook_ajax_get_available_dates_for_service() {
        // Nonce-Prüfung (optional, da öffentlich zugänglich)
        if (isset($_POST['simpbook_nonce'])) {
            $nonce = sanitize_text_field(wp_unslash($_POST['simpbook_nonce']));
            if (!wp_verify_nonce($nonce, 'simpbook_get_available_times_nonce') &&
                !wp_verify_nonce($nonce, 'simpbook_mitarbeiter_nonce')) {
                // Nonce-Prüfung optional für öffentliche Anfragen
            }
        }

        $dienstleistung_id = isset($_POST['simpbook_dienstleistung_id']) ? intval($_POST['simpbook_dienstleistung_id']) : 0;

        if ($dienstleistung_id < 1) {
            wp_send_json_error(__('Invalid service ID', 'simple-appointment-booking'));
            exit;
        }

        // Alle Mitarbeiter für diese Dienstleistung laden
        $is_admin = is_admin();
        $only_frontend = !$is_admin;
        $mitarbeiter = simpbook_get_mitarbeiter_fuer_dienstleistung($dienstleistung_id, true, $only_frontend);

        if (empty($mitarbeiter)) {
            wp_send_json_error(__('No staff members found for this service', 'simple-appointment-booking'));
            exit;
        }

        // Dienstleistungs-eigene Verfügbarkeit prüfen
        $dienstleistung_row = simpbook_get_dienstleistung($dienstleistung_id);
        $svc_type = 'regular';
        $svc_avail = [];
        if ($dienstleistung_row && !empty($dienstleistung_row->verfuegbarkeit)) {
            $svc_avail = json_decode($dienstleistung_row->verfuegbarkeit, true);
            if (!empty($svc_avail['type'])) {
                $svc_type = $svc_avail['type'];
            }
        }

        // Spezielle Termine: einfach Liste zurückgeben
        if ($svc_type === 'special_dates') {
            $special_dates_out = [];
            if (!empty($svc_avail['special_dates']) && is_array($svc_avail['special_dates'])) {
                foreach ($svc_avail['special_dates'] as $sd) {
                    if (!empty($sd['date'])) {
                        $special_dates_out[] = $sd['date'];
                    }
                }
            }
            wp_send_json_success([
                'verfuegbarkeit_type' => 'special_dates',
                'special_dates' => $special_dates_out,
            ]);
            exit;
        }

        // Bestimmte Wochentage: konfigurierte Tage zurückgeben
        if ($svc_type === 'weekdays') {
            $weekday_num_to_key = ['1' => 'montag', '2' => 'dienstag', '3' => 'mittwoch', '4' => 'donnerstag', '5' => 'freitag', '6' => 'samstag', '7' => 'sonntag'];
            $wochentage_namen = [
                'montag' => __('Monday', 'simple-appointment-booking'),
                'dienstag' => __('Tuesday', 'simple-appointment-booking'),
                'mittwoch' => __('Wednesday', 'simple-appointment-booking'),
                'donnerstag' => __('Thursday', 'simple-appointment-booking'),
                'freitag' => __('Friday', 'simple-appointment-booking'),
                'samstag' => __('Saturday', 'simple-appointment-booking'),
                'sonntag' => __('Sunday', 'simple-appointment-booking'),
            ];
            $wochentage_abk = [
                'montag' => __('Mon', 'simple-appointment-booking'), 'dienstag' => __('Tu', 'simple-appointment-booking'),
                'mittwoch' => __('We', 'simple-appointment-booking'), 'donnerstag' => __('Th', 'simple-appointment-booking'),
                'freitag' => __('Fri', 'simple-appointment-booking'), 'samstag' => __('Sat', 'simple-appointment-booking'),
                'sonntag' => __('Su', 'simple-appointment-booking'),
            ];
            $verfuegbare_wochentage = [];
            $weekday_times_cfg = !empty($svc_avail['weekday_times']) && is_array($svc_avail['weekday_times']) ? $svc_avail['weekday_times'] : [];
            foreach ($weekday_times_cfg as $iso_num => $wt) {
                $key = isset($weekday_num_to_key[(string)$iso_num]) ? $weekday_num_to_key[(string)$iso_num] : null;
                if (!$key) continue;
                $verfuegbare_wochentage[] = [
                    'key'  => $key,
                    'name' => $wochentage_namen[$key],
                    'abbr' => $wochentage_abk[$key],
                ];
            }
            wp_send_json_success([
                'verfuegbarkeit_type' => 'weekdays',
                'wochentage' => $verfuegbare_wochentage,
            ]);
            exit;
        }

        // Reguläre Öffnungszeiten: Wochentage aus Mitarbeiter/global-Konfiguration ermitteln
        $verfuegbare_wochentage = [];
        $default_map = simpbook_get_default_settings_map();
        $wochentag_zeiten_cfg = simpbook_get_option('simpbook_wochentag_zeiten', $default_map['simpbook_wochentag_zeiten']);

        $wochentage = ['montag', 'dienstag', 'mittwoch', 'donnerstag', 'freitag', 'samstag', 'sonntag'];
        $wochentage_namen = [
            'montag' => __('Monday', 'simple-appointment-booking'),
            'dienstag' => __('Tuesday', 'simple-appointment-booking'),
            'mittwoch' => __('Wednesday', 'simple-appointment-booking'),
            'donnerstag' => __('Thursday', 'simple-appointment-booking'),
            'freitag' => __('Friday', 'simple-appointment-booking'),
            'samstag' => __('Saturday', 'simple-appointment-booking'),
            'sonntag' => __('Sunday', 'simple-appointment-booking')
        ];

        // Abkürzungen mit Übersetzungen
        $wochentage_abk = [
            'montag' => __('Mon', 'simple-appointment-booking'),
            'dienstag' => __('Tu', 'simple-appointment-booking'),
            'mittwoch' => __('We', 'simple-appointment-booking'),
            'donnerstag' => __('Th', 'simple-appointment-booking'),
            'freitag' => __('Fri', 'simple-appointment-booking'),
            'samstag' => __('Sat', 'simple-appointment-booking'),
            'sonntag' => __('Su', 'simple-appointment-booking')
        ];

        foreach ($wochentage as $wochentag_key) {
            $tag_verfuegbar = false;

            // Prüfe ob mindestens ein Mitarbeiter an diesem Tag arbeitet
            foreach ($mitarbeiter as $m) {
                $arbeitszeiten = simpbook_get_mitarbeiter_arbeitszeiten($m->id);
                if ($arbeitszeiten) {
                    // Mitarbeiter hat individuelle Arbeitszeiten
                    if (isset($arbeitszeiten[$wochentag_key]) && $arbeitszeiten[$wochentag_key]['aktiv'] === '1') {
                        $tag_verfuegbar = true;
                        break;
                    }
                } else {
                    // Keine individuellen Arbeitszeiten - globale Öffnungszeiten verwenden
                    if (isset($wochentag_zeiten_cfg[$wochentag_key]) && $wochentag_zeiten_cfg[$wochentag_key]['aktiv'] === '1') {
                        $tag_verfuegbar = true;
                        break;
                    }
                }
            }

            if ($tag_verfuegbar) {
                $verfuegbare_wochentage[] = [
                    'key' => $wochentag_key,
                    'name' => $wochentage_namen[$wochentag_key],
                    'abbr' => $wochentage_abk[$wochentag_key]
                ];
            }
        }

        wp_send_json_success([
            'verfuegbarkeit_type' => 'regular',
            'wochentage' => $verfuegbare_wochentage,
        ]);
        exit;
    }

    public function simpbook_ajax_get_calendar_events() {
        // Nonce-Prüfung
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_calendar_events_nonce')) {
            wp_send_json_error(__('Security check failed', 'simple-appointment-booking'));
            exit;
        }

        $start = isset($_POST['simpbook_start']) ? sanitize_text_field(wp_unslash($_POST['simpbook_start'])) : '';
        $end = isset($_POST['simpbook_end']) ? sanitize_text_field(wp_unslash($_POST['simpbook_end'])) : '';
        $filter_mitarbeiter = isset($_POST['simpbook_filter_mitarbeiter']) ? intval($_POST['simpbook_filter_mitarbeiter']) : 0;
        $filter_dienstleistung = isset($_POST['simpbook_filter_dienstleistung']) ? intval($_POST['simpbook_filter_dienstleistung']) : 0;

        if (empty($start) || empty($end)) {
            wp_send_json_error(__('Invalid date entries', 'simple-appointment-booking'));
            exit;
        }

        global $wpdb;
        $table_name = $wpdb->prefix . 'buchungen';

        // Basis-Query
        $where_conditions = [
            "datum >= %s",
            "datum <= %s",
            "storniert = 0",
            "status != %s" // Abgelehnte Buchungen ausschließen
        ];
        $where_values = [$start, $end, 'ABGELEHNT'];

        // Filter für Mitarbeiter
        if ($filter_mitarbeiter > 0) {
            $where_conditions[] = "mitarbeiter_id = %d";
            $where_values[] = $filter_mitarbeiter;
        }

        // Filter für Dienstleistung
        if ($filter_dienstleistung > 0) {
            $where_conditions[] = "dienstleistung_id = %d";
            $where_values[] = $filter_dienstleistung;
        }

        $where_clause = implode(' AND ', $where_conditions);

        // SQL-Query zusammenbauen
        $query = "SELECT * FROM {$table_name} WHERE {$where_clause} ORDER BY datum ASC, uhrzeit ASC";

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $reservierungen = $wpdb->get_results($wpdb->prepare($query, ...$where_values));

        // Events für FullCalendar formatieren
        $events = [];
        foreach ($reservierungen as $reservierung) {
            // Dienstleistung und Mitarbeiter laden
            $dienstleistung = $reservierung->dienstleistung_id > 0
                ? simpbook_get_dienstleistung($reservierung->dienstleistung_id)
                : null;
            $mitarbeiter = $reservierung->mitarbeiter_id > 0
                ? simpbook_get_mitarbeiter($reservierung->mitarbeiter_id)
                : null;

            $title = $reservierung->name;
            if ($dienstleistung) {
                $title .= ' - ' . $dienstleistung->name;
            }
            if ($mitarbeiter) {
                $title .= ' (' . $mitarbeiter->name . ')';
            }

            // Status-basierte Farbe (wie in der Übersicht)
            $color = '#ffc107'; // Gelb (ausstehend) - wie in der Übersicht
            if ($reservierung->status === 'BESTÄTIGT' || $reservierung->status === 'BESTAETIGT') {
                $color = '#28a745'; // Grün
            } elseif ($reservierung->status === 'STORNIERT') {
                $color = '#6c757d'; // Grau
            }
            // ABGELEHNT wird bereits in der Query ausgeschlossen

            $events[] = [
                'id' => intval($reservierung->id),
                'title' => $title,
                'start' => $reservierung->datum . 'T' . $reservierung->uhrzeit,
                'color' => $color,
                'extendedProps' => [
                    'status' => $reservierung->status,
                    'email' => $reservierung->email,
                    'telefon' => $reservierung->telefon
                ]
            ];
        }

        wp_send_json_success($events);
        exit;
    }

    /**
     * AJAX Handler to get reservation details for modal
     */
    public function simpbook_ajax_get_reservierung_details() {
        // Nonce-Prüfung
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_reservierung_details_nonce')) {
            wp_send_json_error(['message' => esc_html__('Invalid request.', 'simple-appointment-booking')]);
            return;
        }

        $id = isset($_POST['simpbook_id']) ? intval($_POST['simpbook_id']) : 0;
        if ($id <= 0) {
            wp_send_json_error(['message' => esc_html__('Invalid reservation ID.', 'simple-appointment-booking')]);
            return;
        }

        global $wpdb;
        $table_name = $wpdb->prefix . 'buchungen';

        // Reservierung abrufen
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $reservierung = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM %i WHERE id = %d",
            $table_name,
            $id
        ));

        if (!$reservierung) {
            wp_send_json_error(['message' => esc_html__('Reservation not found.', 'simple-appointment-booking')]);
            return;
        }

        // Daten formatieren
        $uhrzeit_formatiert = substr($reservierung->uhrzeit, 0, 5); // HH:MM

        // Dienstleistung und Mitarbeiter laden
        $dienstleistung_name = '';
        if ($reservierung->dienstleistung_id > 0) {
            $dienstleistung = simpbook_get_dienstleistung($reservierung->dienstleistung_id);
            if ($dienstleistung) {
                $dienstleistung_name = $dienstleistung->name;
            }
        }

        $mitarbeiter_name = '';
        if ($reservierung->mitarbeiter_id > 0) {
            $mitarbeiter = simpbook_get_mitarbeiter($reservierung->mitarbeiter_id);
            if ($mitarbeiter) {
                $mitarbeiter_name = $mitarbeiter->name;
            }
        }

        // Generiere Nonces für Aktionen
        $nonce_status = wp_create_nonce('simpbook_status_change_nonce_' . $id);
        $nonce_delete = wp_create_nonce('simpbook_delete_nonce_' . $id);

        // Verfügbare Mitarbeiter für dieses Datum und diese Dienstleistung laden
        $verfuegbare_mitarbeiter = simpbook_get_verfuegbare_mitarbeiter_fuer_buchung(
            $reservierung->dienstleistung_id,
            $reservierung->datum,
            $reservierung->uhrzeit
        );

        $details = [
            'id' => (int) $reservierung->id,
            'name' => $reservierung->name,
            'email' => $reservierung->email,
            'telefon' => $reservierung->telefon,
            'datum' => $reservierung->datum,
            'uhrzeit' => $uhrzeit_formatiert,
            'dienstleistung' => $dienstleistung_name,
            'dienstleistung_id' => (int) $reservierung->dienstleistung_id,
            'mitarbeiter' => $mitarbeiter_name,
            'mitarbeiter_id' => (int) $reservierung->mitarbeiter_id,
            'verfuegbare_mitarbeiter' => $verfuegbare_mitarbeiter,
            'simpbook_nachricht' => !empty($reservierung->nachricht) ? $reservierung->nachricht : '-',
            'status' => $reservierung->status,
            'storniert' => (int) $reservierung->storniert,
            'status_geaendert_datum' => $reservierung->status_geaendert_datum,
            'erstellungsdatum' => $reservierung->erstellungsdatum,
            'nonce_status' => $nonce_status,
            'nonce_delete' => $nonce_delete
        ];

        wp_send_json_success($details);
    }

    /**
     * Update Mitarbeiter für eine Reservierung
     */
    public function simpbook_ajax_update_reservierung_mitarbeiter() {
        // Nonce-Prüfung
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_update_mitarbeiter_nonce')) {
            wp_send_json_error(esc_html__('Invalid request.', 'simple-appointment-booking'));
            return;
        }

        $reservierung_id = isset($_POST['reservierung_id']) ? intval($_POST['reservierung_id']) : 0;
        $mitarbeiter_id = isset($_POST['mitarbeiter_id']) ? intval($_POST['mitarbeiter_id']) : 0;

        if ($reservierung_id <= 0) {
            wp_send_json_error(esc_html__('Invalid reservation ID.', 'simple-appointment-booking'));
            return;
        }

        // 0 ist erlaubt für "No Specific Staff Member"
        if ($mitarbeiter_id < 0) {
            wp_send_json_error(esc_html__('Invalid staff member ID.', 'simple-appointment-booking'));
            return;
        }

        global $wpdb;
        $table_name = $wpdb->prefix . 'buchungen';

        // Wenn Mitarbeiter-ID > 0, prüfen ob Mitarbeiter existiert
        if ($mitarbeiter_id > 0) {
            $mitarbeiter = simpbook_get_mitarbeiter($mitarbeiter_id);
            if (!$mitarbeiter) {
                wp_send_json_error(esc_html__('Mitarbeiter nicht gefunden.', 'simple-appointment-booking'));
                return;
            }
        }

        // Aktualisiere Reservierung
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $result = $wpdb->update(
            $table_name,
            ['mitarbeiter_id' => $mitarbeiter_id],
            ['id' => $reservierung_id],
            ['%d'],
            ['%d']
        );

        if ($result === false) {
            wp_send_json_error(esc_html__('Error updating reservation.', 'simple-appointment-booking'));
            return;
        }

        wp_send_json_success(esc_html__('Mitarbeiter erfolgreich zugewiesen.', 'simple-appointment-booking'));
    }

    /**
     * Generiere einen Token für Kalender-Abonnement
     */
    public function simpbook_ajax_generate_calendar_token() {
        // Nonce-Prüfung
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_calendar_token')) {
            wp_send_json_error(__('Security check failed', 'simple-appointment-booking'));
            exit;
        }

        // Token generieren
        $token = bin2hex(random_bytes(32));
        $include_past = isset($_POST['simpbook_include_past']) && $_POST['simpbook_include_past'] === '1';
        $calendar_app = isset($_POST['simpbook_calendar_app']) ? sanitize_text_field(wp_unslash($_POST['simpbook_calendar_app'])) : 'google';

        // Token in Option speichern
        $calendar_tokens = get_option('simpbook_calendar_tokens', []);
        $calendar_tokens[$token] = [
            'created' => current_time('mysql'),
            'include_past' => $include_past,
            'calendar_app' => $calendar_app,
            'user_id' => get_current_user_id()
        ];
        update_option('simpbook_calendar_tokens', $calendar_tokens);

        // URL generieren
        $feed_url = add_query_arg([
            'simpbook_calendar_feed' => '1',
            'token' => $token
        ], home_url('/'));

        wp_send_json_success([
            'token' => $token,
            'url' => $feed_url
        ]);
        exit;
    }

    /**
     * Lösche einen Kalender-Token
     */
    public function simpbook_ajax_delete_calendar_token() {
        // Nonce-Prüfung
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_calendar_token')) {
            wp_send_json_error(__('Security check failed', 'simple-appointment-booking'));
            exit;
        }

        $token = isset($_POST['simpbook_token']) ? sanitize_text_field(wp_unslash($_POST['simpbook_token'])) : '';

        if (empty($token)) {
            wp_send_json_error(__('No token provided', 'simple-appointment-booking'));
            exit;
        }

        $calendar_tokens = get_option('simpbook_calendar_tokens', []);
        if (isset($calendar_tokens[$token])) {
            unset($calendar_tokens[$token]);
            update_option('simpbook_calendar_tokens', $calendar_tokens);
            wp_send_json_success(__('Token successfully deleted', 'simple-appointment-booking'));
        } else {
            wp_send_json_error(__('Token not found', 'simple-appointment-booking'));
        }
        exit;
    }

    /**
     * AJAX Handler to update language override
     */
    public function simpbook_ajax_update_language_override() {
        // Nonce-Prüfung
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_language_override_nonce')) {
            wp_send_json_error(array('message' => 'Security check failed'));
            exit;
        }

        // Capability-Prüfung
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => 'Nicht berechtigt'));
            exit;
        }

        $language = isset($_POST['simpbook_language']) ? sanitize_text_field(wp_unslash($_POST['simpbook_language'])) : '';

        // Validiere gegen Whitelist
        $supported = simpbook_get_supported_languages();
        if (!$language || ($language !== 'auto' && !in_array($language, $supported, true))) {
            wp_send_json_error(array('message' => 'Ungültige Sprache'));
            exit;
        }

        // Speichere die Sprachoption
        simpbook_update_option('simpbook_language_override', $language);

        // Reload textdomain sofort
        self::reload_plugin_textdomain();

        wp_send_json_success(array(
            'message' => 'Sprache aktualisiert',
            'language' => $language,
            'language_name' => simpbook_get_language_name(simpbook_get_current_language())
        ));
        exit;
    }

    /**
     * ICS Feed Handler
     */
    public function simpbook_handle_ics_feed() {
        // Prüfe ob es eine Feed-Anfrage ist
        if (!isset($_GET['simpbook_calendar_feed']) || $_GET['simpbook_calendar_feed'] !== '1') { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing/filtering only
            return;
        }

        $token = isset($_GET['simpbook_token']) ? sanitize_text_field(wp_unslash($_GET['simpbook_token'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing/filtering only

        if (empty($token)) {
            status_header(403);
            die(esc_html__('Invalid Token', 'simple-appointment-booking'));
        }

        // Token prüfen
        $calendar_tokens = get_option('simpbook_calendar_tokens', []);
        if (!isset($calendar_tokens[$token])) {
            status_header(403);
            die(esc_html__('Invalid Token', 'simple-appointment-booking'));
        }

        $token_data = $calendar_tokens[$token];
        $include_past = isset($token_data['simpbook_include_past']) && $token_data['simpbook_include_past'] === '1';

        // Reservierungen laden
        global $wpdb;
        $table_name = $wpdb->prefix . 'buchungen';

        // Datumsbereich bestimmen
        $start_date = $include_past
            ? wp_date('Y-m-d', strtotime('-14 days'))
            : wp_date('Y-m-d');
        $end_date = wp_date('Y-m-d', strtotime('+1 year'));

        $simpbook_where_conditions = [
            "datum >= %s",
            "datum <= %s",
            "storniert = 0",
            "status != %s"
        ];
        $simpbook_where_values = [$start_date, $end_date, 'ABGELEHNT'];

        $simpbook_where_clause = implode(' AND ', $simpbook_where_conditions);

        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $simpbook_reservierungen = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM %i WHERE $simpbook_where_clause ORDER BY datum ASC, uhrzeit ASC",
            array_merge([$simpbook_table_name], $simpbook_where_values)
        ));
        // phpcs:enable

        // ICS-Datei generieren
        header('Content-Type: text/calendar; charset=utf-8');
        header('Content-Disposition: attachment; filename="reservierungen.ics"');
        header('Cache-Control: no-cache, must-revalidate, max-age=0');
        header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
        header('Pragma: no-cache');
        header('X-Content-Type-Options: nosniff');

        echo "BEGIN:VCALENDAR\r\n";
        echo "VERSION:2.0\r\n";
        echo "PRODID:-//PocketBooking Calendar//Reservierungen//DE\r\n";
        echo "CALSCALE:GREGORIAN\r\n";
        echo "METHOD:PUBLISH\r\n";
        echo "X-WR-CALNAME:" . esc_html(get_bloginfo('name')) . " - Reservierungen\r\n";
        echo "X-WR-CALDESC:Reservierungen aus PocketBooking Calendar\r\n";
        echo "X-WR-TIMEZONE:" . esc_html(wp_timezone_string()) . "\r\n";

        foreach ($simpbook_reservierungen as $reservierung) {
            $dienstleistung = $reservierung->dienstleistung_id > 0
                ? simpbook_get_dienstleistung($reservierung->dienstleistung_id)
                : null;
            $mitarbeiter = $reservierung->mitarbeiter_id > 0
                ? simpbook_get_mitarbeiter($reservierung->mitarbeiter_id)
                : null;

            $title = $reservierung->name;
            if ($dienstleistung) {
                $title .= ' - ' . $dienstleistung->name;
            }
            if ($mitarbeiter) {
                $title .= ' (' . $mitarbeiter->name . ')';
            }

            // Datum und Zeit formatieren (ICS Format: YYYYMMDDTHHMMSS)
            $start_datetime = $reservierung->datum . 'T' . str_replace(':', '', $reservierung->uhrzeit) . '00';
            $end_time = gmdate('H:i:s', strtotime($reservierung->uhrzeit) + ($dienstleistung ? $dienstleistung->dauer_minuten * 60 : 30 * 60));
            $end_datetime = $reservierung->datum . 'T' . str_replace(':', '', $end_time) . '00';

            // UID generieren
            $uid = 'reservierung-' . $reservierung->id . '@' . wp_parse_url(home_url(), PHP_URL_HOST);

            // Beschreibung zusammenstellen
            $description = '';
            if ($dienstleistung) {
                $description .= __('Service', 'simple-appointment-booking') . ': ' . $dienstleistung->name . '\\n';
            }
            if ($mitarbeiter) {
                $description .= __('Staff', 'simple-appointment-booking') . ': ' . $mitarbeiter->name . '\\n';
            }
            $description .= __('Email', 'simple-appointment-booking') . ': ' . $reservierung->email . '\\n';
            $description .= __('phone', 'simple-appointment-booking') . ': ' . $reservierung->telefon;
            if (!empty($reservierung->nachricht)) {
                $description .= '\\n\\n' . __('Message', 'simple-appointment-booking') . ': ' . $reservierung->nachricht;
            }

            echo "BEGIN:VEVENT\r\n";
            echo "UID:" . esc_html($uid) . "\r\n";
            echo "DTSTART:" . esc_html($start_datetime) . "\r\n";
            echo "DTEND:" . esc_html($end_datetime) . "\r\n";
            echo "DTSTAMP:" . esc_html(gmdate('Ymd\THis\Z', current_time('timestamp'))) . "\r\n";
            echo "SUMMARY:" . esc_html($this->simpbook_ics_escape($title)) . "\r\n";
            echo "DESCRIPTION:" . esc_html($this->simpbook_ics_escape($description)) . "\r\n";
            echo "STATUS:CONFIRMED\r\n";
            echo "SEQUENCE:0\r\n";
            echo "END:VEVENT\r\n";
        }

        echo "END:VCALENDAR\r\n";
        exit;
    }

    /**
     * Escape String für ICS Format
     */
    private function simpbook_ics_escape($string) {
        $string = str_replace('\\', '\\\\', $string);
        $string = str_replace(',', '\\,', $string);
        $string = str_replace(';', '\\;', $string);
        $string = str_replace("\n", '\\n', $string);
        $string = str_replace("\r", '', $string);
        return $string;
    }

    public function simpbook_get_available_times() {
        // Anpassung hier: Nonce vor der Überprüfung bereinigen.
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_get_available_times_nonce')) {
            wp_send_json_error('Security check failed'); exit;
        }
        $datum_input = isset($_POST['simpbook_datum']) ? sanitize_text_field(wp_unslash($_POST['simpbook_datum'])) : '';
        $dienstleistung_id = isset($_POST['simpbook_dienstleistung_id']) ? intval($_POST['simpbook_dienstleistung_id']) : 0;
        $mitarbeiter_id = isset($_POST['simpbook_mitarbeiter_id']) ? intval($_POST['simpbook_mitarbeiter_id']) : 0; // Optional, 0 = egal welcher Mitarbeiter
        $simpbook_exclude_simpbook_reservierung_id = isset($_POST['simpbook_exclude_simpbook_reservierung_id']) ? intval($_POST['simpbook_exclude_simpbook_reservierung_id']) : 0;
        if (empty($datum_input)) { wp_send_json_error('No date specified'); exit; }
        if ($dienstleistung_id <= 0) { wp_send_json_error('Keine Dienstleistung angegeben'); exit; }

        // Dienstleistung prüfen
        $dienstleistung = simpbook_get_dienstleistung($dienstleistung_id);
        if (!$dienstleistung || !$dienstleistung->aktiv) {
            wp_send_json_error('Dienstleistung nicht gefunden oder nicht aktiv'); exit;
        }

        // Unterstütze verschiedene Datumsformate: d.m.Y (europäische Schreibweise) und m/d/Y (US-Format)
        // Versuche verschiedene Formate
        $datum_obj = false;
        $current_language_for_date = simpbook_get_current_language();

        // Format 1: d.m.Y oder dd.mm.yyyy (europäische Schreibweise - bevorzugt)
        $datum_obj = DateTime::createFromFormat('d.m.Y', $datum_input);

        // Format 2: d.m.y oder dd.mm.yy (europäische Schreibweise mit 2-stelligem Jahr)
        if ($datum_obj === false) {
            $datum_obj = DateTime::createFromFormat('d.m.y', $datum_input);
        }

        // Format 3: m/d/Y oder mm/dd/yyyy (US-Format)
        if ($datum_obj === false && $current_language_for_date === 'en_US_AMPM') {
            $datum_obj = DateTime::createFromFormat('m/d/Y', $datum_input);
        }

        // Format 4: m/d/y oder mm/dd/yy (US-Format mit 2-stelligem Jahr)
        if ($datum_obj === false && $current_language_for_date === 'en_US_AMPM') {
            $datum_obj = DateTime::createFromFormat('m/d/y', $datum_input);
        }

        // Format 5: d-m-y oder dd-mm-yy (Fallback für alte Formate)
        if ($datum_obj === false) {
            $datum_obj = DateTime::createFromFormat('d-m-y', $datum_input);
        }

        // Format 6: d-m-Y oder dd-mm-yyyy (Fallback für alte Formate)
        if ($datum_obj === false) {
            $datum_obj = DateTime::createFromFormat('d-m-Y', $datum_input);
        }

        // Format 5: Flexibler Versuch mit strtotime (für verschiedene Formate)
        if ($datum_obj === false) {
            // Ersetze Punkte durch Bindestriche für strtotime
            $normalized_date = str_replace('.', '-', $datum_input);
            $timestamp = strtotime($normalized_date);
            if ($timestamp !== false) {
                $datum_obj = new DateTime();
                $datum_obj->setTimestamp($timestamp);
            }
        }

        if ($datum_obj === false) {
            wp_send_json_error('Ungültiges Datumsformat: ' . esc_html($datum_input));
            exit;
        }
        $mysql_datum = $datum_obj->format('Y-m-d');

        // Maximale Vorlaufzeit prüfen (Mindestvorlaufzeit wird später pro Slot geprüft)
        if (!simpbook_pruefe_maximale_vorlauf($mysql_datum)) {
            wp_send_json_error('Maximale Buchungsvorlauf überschritten'); exit;
        }

        $default_map = simpbook_get_default_settings_map();
        $spezielle_tage_konfiguration = simpbook_get_option('simpbook_spezielle_tage_konfiguration', $default_map['simpbook_spezielle_tage_konfiguration']);

        // Arbeitszeiten bestimmen: Mitarbeiter-spezifisch oder global
        $beginn_zeit_final_str = null;
        $ende_zeit_final_str = null;
        $tag_aktiv_final = false;

        if ($mitarbeiter_id > 0) {
            // Mitarbeiter-spezifische Arbeitszeiten prüfen
            $mitarbeiter = simpbook_get_mitarbeiter($mitarbeiter_id);
            if (!$mitarbeiter || !$mitarbeiter->aktiv) {
                wp_send_json_error('Mitarbeiter nicht gefunden oder nicht aktiv'); exit;
            }

            $arbeitszeiten = simpbook_get_mitarbeiter_arbeitszeiten($mitarbeiter_id);
            if ($arbeitszeiten) {
                // Mitarbeiter hat individuelle Arbeitszeiten
                $wochentag_php = strtolower($datum_obj->format('l'));
                $wochentag_key_map = ['monday'=>'montag', 'tuesday'=>'dienstag', 'wednesday'=>'mittwoch', 'thursday'=>'donnerstag', 'friday'=>'freitag', 'saturday'=>'samstag', 'sunday'=>'sonntag'];
                $wochentag_key = $wochentag_key_map[$wochentag_php] ?? 'montag';

                if (isset($arbeitszeiten[$wochentag_key]) && $arbeitszeiten[$wochentag_key]['aktiv'] === '1') {
                    $beginn_zeit_final_str = $arbeitszeiten[$wochentag_key]['beginn'];
                    $ende_zeit_final_str = $arbeitszeiten[$wochentag_key]['ende'];
                    $tag_aktiv_final = true;
                }
            }
        }

        // Falls keine Mitarbeiter-Arbeitszeiten, globale Öffnungszeiten verwenden
        if ($beginn_zeit_final_str === null) {
            $wochentag_php = strtolower($datum_obj->format('l'));
            $wochentag_key_map = ['monday'=>'montag', 'tuesday'=>'dienstag', 'wednesday'=>'mittwoch', 'thursday'=>'donnerstag', 'friday'=>'freitag', 'saturday'=>'samstag', 'sunday'=>'sonntag'];
            $wochentag_key = $wochentag_key_map[$wochentag_php] ?? 'montag';
            $wochentag_zeiten_cfg = simpbook_get_option('simpbook_wochentag_zeiten', $default_map['simpbook_wochentag_zeiten']);
            $tag_cfg_standard = $wochentag_zeiten_cfg[$wochentag_key] ?? $default_map['simpbook_wochentag_zeiten']['montag'];

            $beginn_zeit_final_str = $tag_cfg_standard['beginn'];
            $ende_zeit_final_str = $tag_cfg_standard['ende'];
            $tag_aktiv_final = ($tag_cfg_standard['aktiv'] === '1');
        }

        // Dienstleistungs-eigene Verfügbarkeit prüfen und ggf. Zeiten überschreiben
        $service_verfuegbarkeit = simpbook_get_dienstleistung($dienstleistung_id);
        if ($service_verfuegbarkeit && !empty($service_verfuegbarkeit->verfuegbarkeit)) {
            $svc_avail = json_decode($service_verfuegbarkeit->verfuegbarkeit, true);
            $svc_type = isset($svc_avail['type']) ? $svc_avail['type'] : 'regular';
            if ($svc_type === 'weekdays') {
                // ISO-Wochentag: 1=Mo ... 7=So (date('N'))
                $iso_dow = intval($datum_obj->format('N'));
                if (isset($svc_avail['weekday_times'][$iso_dow])) {
                    $wt = $svc_avail['weekday_times'][$iso_dow];
                    $beginn_zeit_final_str = $wt['time_from'];
                    $ende_zeit_final_str   = $wt['time_to'];
                    $tag_aktiv_final = true;
                } else {
                    $tag_aktiv_final = false;
                }
            } elseif ($svc_type === 'special_dates') {
                $sd_times = [];
                if (!empty($svc_avail['special_dates']) && is_array($svc_avail['special_dates'])) {
                    foreach ($svc_avail['special_dates'] as $sd) {
                        $sd_times[$sd['date']] = $sd;
                    }
                }
                if (isset($sd_times[$mysql_datum])) {
                    $beginn_zeit_final_str = $sd_times[$mysql_datum]['time_from'];
                    $ende_zeit_final_str   = $sd_times[$mysql_datum]['time_to'];
                    $tag_aktiv_final = true;
                } else {
                    $tag_aktiv_final = false;
                }
            }
            // 'regular' type: no override — use global/mitarbeiter settings as-is
        }

        // Urlaubs-Zeiträume prüfen
        $simpbook_urlaub_closed = simpbook_expand_urlaub_dates();
        if (in_array($mysql_datum, $simpbook_urlaub_closed, true)) {
            wp_send_json_success('<option value="">-- ' . esc_html__('An diesem Tag geschlossen (Urlaub)', 'simple-appointment-booking') . ' --</option>');
            exit;
        }

        // Prüfe spezielle Tageskonfiguration
        if (isset($spezielle_tage_konfiguration[$mysql_datum])) {
            $spezieller_tag_cfg = $spezielle_tage_konfiguration[$mysql_datum];
            if ($spezieller_tag_cfg['status'] === 'geschlossen') {
                wp_send_json_success('<option value="">-- ' . __('Closed on this day (Special)', 'simple-appointment-booking') . ' --</option>');
                exit;
            } elseif ($spezieller_tag_cfg['status'] === 'speziell' && !empty($spezieller_tag_cfg['beginn']) && !empty($spezieller_tag_cfg['ende'])) {
                $beginn_zeit_final_str = $spezieller_tag_cfg['beginn'];
                $ende_zeit_final_str = $spezieller_tag_cfg['ende'];
                $tag_aktiv_final = true; // Überschreibt Wochentag-Aktivität
            }
        }

        if (!$tag_aktiv_final) {
            wp_send_json_success('<option value="">-- ' . __('Closed on this day', 'simple-appointment-booking') . ' --</option>');
            exit;
        }

        global $wpdb;
        $table_reservierungen = $wpdb->prefix . 'buchungen';
        $intervall_cfg = intval(simpbook_get_option('simpbook_intervall', $default_map['simpbook_intervall']));

        // Dauer der Dienstleistung (ggf. aus Buchungsoption überschreiben)
        $buchungsoption_id = isset($_POST['simpbook_buchungsoption_id']) ? intval($_POST['simpbook_buchungsoption_id']) : 0;
        if ($buchungsoption_id > 0) {
            $simpbook_bo_table = $wpdb->prefix . 'simpbook_buchungsoptionen';
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $simpbook_bo = $wpdb->get_row($wpdb->prepare('SELECT dauer_minuten FROM `' . $simpbook_bo_table . '` WHERE id = %d', $buchungsoption_id));
            if ($simpbook_bo) {
                $dienstleistungs_dauer_minuten = intval($simpbook_bo->dauer_minuten) + intval($dienstleistung->pufferzeit_minuten);
            } else {
                $dienstleistungs_dauer_minuten = simpbook_get_dienstleistungs_dauer($dienstleistung_id);
            }
        } else {
            $dienstleistungs_dauer_minuten = simpbook_get_dienstleistungs_dauer($dienstleistung_id);
        }

        // Reservierungen am Tag laden (nur nicht-stornierte, relevante für diesen Mitarbeiter/Dienstleistung)
        $where_parts = ["datum = %s", "storniert = 0", "status NOT IN ('ABGELEHNT', 'ERLEDIGT')"];
        $prepare_values = [$mysql_datum];

        if ($mitarbeiter_id > 0) {
            $where_parts[] = "mitarbeiter_id = %d";
            $prepare_values[] = $mitarbeiter_id;
        } else {
            // Standalone-Dienst (kein Mitarbeiter): nur Buchungen derselben Dienstleistung laden
            $where_parts[] = "dienstleistung_id = %d";
            $prepare_values[] = $dienstleistung_id;
        }

        if ($simpbook_exclude_simpbook_reservierung_id > 0) {
            $where_parts[] = "id != %d";
            $prepare_values[] = $simpbook_exclude_simpbook_reservierung_id;
        }

        $simpbook_where_clause = implode(' AND ', $where_parts);
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $simpbook_bo_join_table = $wpdb->prefix . 'simpbook_buchungsoptionen';
        $simpbook_dl_join_table = $wpdb->prefix . 'dienstleistungen';
        $simpbook_reservierungen_am_tag = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT r.id, r.uhrzeit, r.dienstleistung_id, r.mitarbeiter_id, r.buchungsoption_id,
                        bo.dauer_minuten AS option_dauer_minuten, dl.pufferzeit_minuten AS dl_pufferzeit_minuten
                 FROM `{$table_reservierungen}` r
                 LEFT JOIN `{$simpbook_bo_join_table}` bo ON r.buchungsoption_id = bo.id
                 LEFT JOIN `{$simpbook_dl_join_table}` dl ON r.dienstleistung_id = dl.id
                 WHERE $simpbook_where_clause",
                $prepare_values
            )
        );
        // phpcs:enable

        $options_html_out = '';
        $slot_gefunden = false;
        $start_ts_slot = strtotime($mysql_datum . ' ' . $beginn_zeit_final_str);
        $ende_ts_restaurant = strtotime($mysql_datum . ' ' . $ende_zeit_final_str);
        $intervall_sek = $intervall_cfg * 60;
        $mindestvorlauf_stunden = intval(simpbook_get_option('simpbook_mindestvorlauf_stunden', 2));
        $mindestvorlauf_sek = $mindestvorlauf_stunden * 3600;
        $jetzt_ts_server = current_time('timestamp');

        // Hole aktuelle Sprache für Zeitformatierung
        $current_language = simpbook_get_current_language();

        // Dauer in Sekunden
        $dienstleistungs_dauer_sek = $dienstleistungs_dauer_minuten * 60;

        for ($current_slot_start_ts = $start_ts_slot; $current_slot_start_ts < $ende_ts_restaurant; $current_slot_start_ts += $intervall_sek) {
            // Prüfe ob Slot innerhalb der Arbeitszeiten liegt
            $slot_ende_ts = $current_slot_start_ts + $dienstleistungs_dauer_sek;
            if ($slot_ende_ts > $ende_ts_restaurant) {
                continue; // Slot würde über Arbeitszeit hinausgehen
            }

            // Mindestvorlaufzeit prüfen
            if ($jetzt_ts_server + $mindestvorlauf_sek >= $current_slot_start_ts) {
                continue;
            }

            // Wert immer im 24h-Format für DB (value-Attribut)
            $slot_uhrzeit_value = gmdate('H:i', $current_slot_start_ts);
            // Anzeige basierend auf Sprache formatieren
            $slot_uhrzeit_display = simpbook_format_time($slot_uhrzeit_value, $current_language);
            $slot_ende_fuer_simpbook_reservierung_ts = $current_slot_start_ts + $dienstleistungs_dauer_sek;

            // Prüfe ob Slot mit bestehenden Reservierungen kollidiert
            $slot_verfuegbar = true;
            foreach ($simpbook_reservierungen_am_tag as $reservierung) {
                $simpbook_reservierung_start_ts = strtotime($mysql_datum . ' ' . $reservierung->uhrzeit);
                // Dauer der bestehenden Buchung: Buchungsoption-Dauer verwenden wenn vorhanden
                if (!empty($reservierung->buchungsoption_id) && $reservierung->option_dauer_minuten !== null) {
                    $simpbook_reservierung_dauer = intval($reservierung->option_dauer_minuten) + intval($reservierung->dl_pufferzeit_minuten);
                } else {
                    $simpbook_reservierung_dauer = simpbook_get_dienstleistungs_dauer($reservierung->dienstleistung_id);
                }
                $simpbook_reservierung_ende_ts = $simpbook_reservierung_start_ts + ($simpbook_reservierung_dauer * 60);

                // Kollisionsprüfung: Slot überlappt mit bestehender Reservierung?
                // Wenn ein Mitarbeiter spezifiziert ist, prüfe nur Reservierungen dieses Mitarbeiters
                if ($mitarbeiter_id > 0 && $reservierung->mitarbeiter_id != $mitarbeiter_id) {
                    continue; // Anderer Mitarbeiter, keine Kollision
                }
                // Standalone-Dienst (kein Mitarbeiter): nur gleiche Dienstleistung blockiert
                if ($mitarbeiter_id == 0 && $reservierung->dienstleistung_id != $dienstleistung_id) {
                    continue; // Andere Dienstleistung, keine Kollision
                }

                // Kollision wenn: Slot-Start liegt innerhalb bestehender Reservierung ODER Slot-Ende liegt innerhalb bestehender Reservierung ODER Slot umschließt bestehende Reservierung
                if (($current_slot_start_ts < $simpbook_reservierung_ende_ts && $slot_ende_fuer_simpbook_reservierung_ts > $simpbook_reservierung_start_ts)) {
                    $slot_verfuegbar = false;
                    break;
                }
            }

            if ($slot_verfuegbar) {
                $options_html_out .= '<option value="' . esc_attr($slot_uhrzeit_value) . '">' . esc_html($slot_uhrzeit_display) . '</option>';
                $slot_gefunden = true;
            } else {
                $options_html_out .= '<option value="' . esc_attr($slot_uhrzeit_value) . '" disabled>' . esc_html($slot_uhrzeit_display) . ' (' . __('Fully booked', 'simple-appointment-booking') . ')</option>';
            }
        }

        if (!$slot_gefunden) {
            $options_html_out = '<option value="">-- ' . __('No times available', 'simple-appointment-booking') . ' --</option>';
        } else {
            $options_html_out = '<option value="">-- ' . __('Select time', 'simple-appointment-booking') . ' --</option>' . $options_html_out;
        }
        wp_send_json_success($options_html_out);
        exit;
    }

    /**
     * Erstellt das Admin-Menü.
     */
    public function simpbook_admin_menu_erstellen() {
         add_menu_page(__('PocketBooking','simple-appointment-booking'), __('PocketBooking','simple-appointment-booking'), 'read', 'simpbook-dashboard', [$this,'simpbook_dashboard_seite_anzeigen'], 'dashicons-calendar-alt', 30);
        add_submenu_page('simpbook-dashboard', __('Dashboard','simple-appointment-booking'), '📊 ' . __('Dashboard','simple-appointment-booking'), 'read', 'simpbook-dashboard', [$this,'simpbook_dashboard_seite_anzeigen']);
        add_submenu_page('simpbook-dashboard', __('Bookings','simple-appointment-booking'), '📋 ' . __('Bookings','simple-appointment-booking'), 'read', 'simpbook-reservierungen', [$this,'simpbook_admin_seite_anzeigen']);
        add_submenu_page('simpbook-dashboard', __('New Booking','simple-appointment-booking'), '➕ ' . __('New Booking','simple-appointment-booking'), 'read', 'simpbook-reservierungen-neu', [$this,'simpbook_neue_reservierung_seite']);
        add_submenu_page('simpbook-dashboard', __('Services','simple-appointment-booking'), '⚙️ ' . __('Services','simple-appointment-booking'), 'read', 'simpbook-dienstleistungen', [$this,'simpbook_dienstleistungen_seite']);
        add_submenu_page('simpbook-dashboard', __('Category/Group','simple-appointment-booking'), '&nbsp;&nbsp;&nbsp;└─ ' . __('Category','simple-appointment-booking'), 'read', 'simpbook-gruppierungen', [$this,'simpbook_gruppierungen_seite']);
        if (get_option('simpbook_buchungsoptionen_aktiv', '0') === '1') {
            add_submenu_page('simpbook-dashboard', __('Booking Options','simple-appointment-booking'), '&nbsp;&nbsp;&nbsp;└─ ' . __('Options','simple-appointment-booking'), 'read', 'simpbook-buchungsoptionen', [$this,'simpbook_buchungsoptionen_seite']);
        }
        add_submenu_page('simpbook-dashboard', __('Dienstleistungen Einstellungen','simple-appointment-booking'), '&nbsp;&nbsp;&nbsp;└─ ' . __('Settings','simple-appointment-booking'), 'read', 'simpbook-dienstleistungen-einstellungen', [$this,'simpbook_dienstleistungen_einstellungen_seite']);
        add_submenu_page('simpbook-dashboard', __('Staff','simple-appointment-booking'), '👥 ' . __('Staff','simple-appointment-booking'), 'read', 'simpbook-mitarbeiter', [$this,'simpbook_mitarbeiter_seite']);
        add_submenu_page('simpbook-dashboard', __('Calendar','simple-appointment-booking'), '📅 ' . __('Calendar','simple-appointment-booking'), 'read', 'simpbook-kalender', [$this,'simpbook_kalender_seite']);
        add_submenu_page('simpbook-dashboard', __('Statistics','simple-appointment-booking'), '📈 ' . __('Statistics','simple-appointment-booking'), 'read', 'simpbook-statistiken', [$this,'simpbook_statistiken_seite']);
        if (simpbook_has_full_access()) {
            add_submenu_page('simpbook-dashboard', __('Settings','simple-appointment-booking'), '🔧 ' . __('Settings','simple-appointment-booking'), 'read', 'simpbook-reservierungen-einstellungen', [$this,'simpbook_einstellungen_seite_anzeigen_wrapper']);
        }
    }

    /**
     * Zeigt die Dienstleistungen-Einstellungsseite an.
     */
    public function simpbook_dienstleistungen_einstellungen_seite() {
        $pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/dienstleistungen-einstellungen.php';
        if (file_exists($pfad)) include $pfad;
        else wp_die('Seitendatei nicht gefunden.');
    }

    /**
     * Wrapper für die Anzeige der Einstellungsseite.
     */
    public function simpbook_einstellungen_seite_anzeigen_wrapper() {
        if (!simpbook_has_full_access()) {
            wp_die(esc_html__('You do not have permission to view this page. Please activate your license or contact support.', 'simple-appointment-booking'));
            return;
        }
        $einstellungen_pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/einstellungen.php';
        if (file_exists($einstellungen_pfad)) include $einstellungen_pfad;
        else wp_die('Einstellungsdatei nicht gefunden.');
    }

    /**
     * Zeigt die Dienstleistungen-Seite an.
     */
    public function simpbook_dienstleistungen_seite() {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for action check only
        $aktion = isset($_GET['simpbook_aktion']) ? sanitize_text_field(wp_unslash($_GET['simpbook_aktion'])) : '';
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for action check only
        $id = isset($_GET['simpbook_id']) ? intval($_GET['simpbook_id']) : 0;

        if ($aktion === 'bearbeiten' || $id > 0) {
            $bearbeiten_pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/dienstleistung-bearbeiten.php';
            if (file_exists($bearbeiten_pfad)) {
                include $bearbeiten_pfad;
            } else {
                wp_die('Datei nicht gefunden.');
            }
        } else {
            $liste_pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/dienstleistungen.php';
            if (file_exists($liste_pfad)) {
                include $liste_pfad;
            } else {
                wp_die('Datei nicht gefunden.');
            }
        }
    }

    /**
     * Zeigt die Gruppierungen/Kategorien-Seite an.
     */
    public function simpbook_gruppierungen_seite() {
        $gruppierungen_pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/gruppierungen.php';
        if (file_exists($gruppierungen_pfad)) {
            include $gruppierungen_pfad;
        } else {
            wp_die('Datei nicht gefunden.');
        }
    }

    /**
     * Zeigt die Buchungsoptionen-Seite an.
     */
    public function simpbook_buchungsoptionen_seite() {
        $pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/buchungsoptionen.php';
        if (file_exists($pfad)) {
            include $pfad;
        } else {
            wp_die('Datei nicht gefunden.');
        }
    }

    /**
     * AJAX: Alle Buchungsoptionen-Vorlagen laden (für das Service-Modal).
     */
    public function simpbook_ajax_get_buchungsoptionen() {
        if (!check_ajax_referer('simpbook_dienstleistung_speichern', 'simpbook_nonce', false)) {
            wp_send_json_error('Invalid nonce');
            exit;
        }
        global $wpdb;
        $table = $wpdb->prefix . 'simpbook_buchungsoptionen';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $optionen = $wpdb->get_results($wpdb->prepare('SELECT * FROM %i ORDER BY sortierung ASC, name ASC', $table));
        wp_send_json_success(array('optionen' => $optionen));
        exit;
    }

    /**
     * AJAX: Buchungsoptionen für eine bestimmte Dienstleistung laden.
     */
    public function simpbook_ajax_get_dienstleistung_buchungsoptionen() {
        if (!check_ajax_referer('simpbook_dienstleistung_speichern', 'simpbook_nonce', false)) {
            wp_send_json_error('Invalid nonce');
            exit;
        }
        global $wpdb;
        $dienstleistung_id = isset($_POST['simpbook_dienstleistung_id']) ? intval($_POST['simpbook_dienstleistung_id']) : 0;
        $bo_table  = $wpdb->prefix . 'simpbook_buchungsoptionen';
        $dl_bo_table = $wpdb->prefix . 'simpbook_dienstleistung_buchungsoptionen';

        // Alle globalen Optionen (für das Select-Dropdown)
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $all = $wpdb->get_results($wpdb->prepare(
            'SELECT id, name, dauer_minuten, sortierung FROM %i ORDER BY sortierung ASC, name ASC',
            $bo_table
        ));

        // Zugewiesene Optionen für diese Dienstleistung
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $assigned = $wpdb->get_results($wpdb->prepare(
            'SELECT dbo.id, dbo.buchungsoption_id, dbo.preis, dbo.sortierung, bo.name, bo.dauer_minuten
             FROM %i dbo
             JOIN %i bo ON dbo.buchungsoption_id = bo.id
             WHERE dbo.dienstleistung_id = %d
             ORDER BY dbo.sortierung ASC',
            $dl_bo_table,
            $bo_table,
            $dienstleistung_id
        ));

        wp_send_json_success(array('assigned' => $assigned, 'all' => $all));
        exit;
    }

    /**
     * AJAX: Buchungsoption-Vorlage löschen (verknüpfte Dienstleistungsoptionen mitlöschen).
     */
    public function simpbook_ajax_delete_buchungsoption() {
        if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_delete_buchungsoption')) {
            wp_send_json_error('Invalid nonce');
            exit;
        }
        global $wpdb;
        $id = isset($_POST['buchungsoption_id']) ? intval($_POST['buchungsoption_id']) : 0;
        if ($id <= 0) {
            wp_send_json_error('Invalid ID');
            exit;
        }
        $dl_bo_table = $wpdb->prefix . 'simpbook_dienstleistung_buchungsoptionen';
        $bo_table    = $wpdb->prefix . 'simpbook_buchungsoptionen';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->delete($dl_bo_table, array('buchungsoption_id' => $id), array('%d'));
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->delete($bo_table, array('id' => $id), array('%d'));
        wp_send_json_success();
        exit;
    }

    /**
     * Zeigt die Mitarbeiter-Seite an.
     */
    public function simpbook_mitarbeiter_seite() {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing/filtering only
        $aktion = isset($_GET['simpbook_aktion']) ? sanitize_text_field(wp_unslash($_GET['simpbook_aktion'])) : '';
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing/filtering only
        $id = isset($_GET['simpbook_id']) ? intval($_GET['simpbook_id']) : 0;

        if ($aktion === 'bearbeiten' || $id > 0) {
            $bearbeiten_pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/mitarbeiter-bearbeiten.php';
            if (file_exists($bearbeiten_pfad)) {
                include $bearbeiten_pfad;
            } else {
                wp_die('Datei nicht gefunden.');
            }
        } else {
            $liste_pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/mitarbeiter.php';
            if (file_exists($liste_pfad)) {
                include $liste_pfad;
            } else {
                wp_die('Datei nicht gefunden.');
            }
        }
    }

    /**
     * Zeigt die Dashboard-Seite an.
     */
    public function simpbook_dashboard_seite_anzeigen() {
        // Prüfe ob Wizard angezeigt werden soll
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing only
        if (isset($_GET['simpbook_wizard'])) {
            $wizard_pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/setup-wizard.php';
            if (file_exists($wizard_pfad)) {
                include $wizard_pfad;
                return;
            }
        }

        // Dashboard immer anzeigen, Wizard-Info nur bei Bedarf
        // Automatischer Redirect zum Wizard deaktiviert - Dashboard soll immer zugänglich sein
        $dashboard_pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/dashboard.php';
        if (file_exists($dashboard_pfad)) {
            include $dashboard_pfad;
        } else {
            echo '<div class="notice notice-error"><p>' . esc_html__('Dashboard-Datei nicht gefunden.', 'simple-appointment-booking') . '</p></div>';
        }
    }
    /**
     * Zeigt die Haupt-Adminseite für Reservierungen an.
     */
    public function simpbook_admin_seite_anzeigen() {
        // Debug für Mitarbeiter-Speicherung
        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- POST data checked in handler function
        if (isset($_POST['simpbook_mitarbeiter_speichern'])) {
            // Disabled for production
            // if (defined('WP_DEBUG') && WP_DEBUG) {
            //     error_log('PocketBooking: Mitarbeiter save detected');
            // }
        }

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- GET parameter for routing only, sanitized on use
        $aktion = isset($_GET['simpbook_aktion']) ? $_GET['simpbook_aktion'] : '';
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for routing only
        $id     = isset($_GET['simpbook_id']) ? intval($_GET['simpbook_id']) : 0;

        if ($aktion === 'bearbeiten' && $id > 0) {
            $bearbeiten_pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/reservierung-bearbeiten.php';
            if (file_exists($bearbeiten_pfad)) {
                 include $bearbeiten_pfad;
            } else {
                 echo '<div class="notice notice-error"><p>Bearbeitungsdatei nicht gefunden.</p></div>';
                 $liste_pfad_fallback = plugin_dir_path(dirname(__FILE__)) . 'admin/reservierungen-liste.php';
                 if (file_exists($liste_pfad_fallback)) {
                    include $liste_pfad_fallback;
                 }
            }
            return;
        }

        // Aktionen (loeschen, stornieren, simpbook_status_aendern) werden jetzt früh in admin_init verarbeitet
        // siehe simpbook_handle_admin_actions_early()

        $liste_pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/reservierungen-liste.php';
        if (file_exists($liste_pfad)) {
            include $liste_pfad;
        } else {
            echo '<div class="notice notice-error"><p>Listendatei nicht gefunden.</p></div>';
        }
    }

    /**
     * Zeigt die Seite zum Erstellen einer neuen Reservierung im Adminbereich an.
     */
    public function simpbook_neue_reservierung_seite() {
        $pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/neue-reservierung.php';
        if (file_exists($pfad)) include $pfad; else echo '<div class="notice notice-error"><p>Datei für neue Reservierung nicht gefunden.</p></div>';
    }

    /**
     * Zeigt die Kalender-Seite an.
     */
    public function simpbook_kalender_seite() {
        // Aktionen (loeschen, stornieren, simpbook_status_aendern) werden jetzt früh in admin_init verarbeitet
        // siehe simpbook_handle_admin_actions_early()
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page display only
        $pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/kalender.php';
        if (file_exists($pfad)) include $pfad; else echo '<div class="notice notice-error"><p>Datei für Kalender nicht gefunden.</p></div>';
    }
    /**
     * Zeigt die Statistiken-Seite an.
     */
    public function simpbook_statistiken_seite() {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Statistics page display only
        $pfad = plugin_dir_path(dirname(__FILE__)) . 'admin/statistiken.php';
        if (file_exists($pfad)) include $pfad; else echo '<div class="notice notice-error"><p>Datei für Statistiken nicht gefunden.</p></div>';
    }
    /**
     * Löscht eine Reservierung.
     */
    public function simpbook_reservierung_loeschen($id) {
        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Plugin-specific table
        $wpdb->delete($wpdb->prefix . 'buchungen', ['id' => $id], ['%d']);
        
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing/filtering only
        $redirect_url = isset($_GET['simpbook_redirect_to']) ? esc_url_raw(wp_unslash($_GET['simpbook_redirect_to'])) : admin_url('admin.php?page=simpbook-reservierungen&simpbook_view=list&simpbook_nachricht=geloescht');
        wp_safe_redirect($redirect_url); exit;
    }
    /**
     * Storniert eine Reservierung (Backend).
     */
    public function simpbook_reservierung_stornieren($id) {
        global $wpdb;
        $tabellen_name = $wpdb->prefix . 'buchungen';

        // Reservierung laden
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
        $reservierung = $wpdb->get_row($wpdb->prepare("SELECT * FROM %i WHERE id = %d", $tabellen_name, $id));
        if (!$reservierung) {
        wp_safe_redirect(admin_url('admin.php?page=simpbook-reservierungen&simpbook_view=list&simpbook_nachricht=fehler'));
            exit;
        }

        // Als storniert markieren
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Cancellation verified by token
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->update($tabellen_name, [
            'storniert' => 1,
            'stornierungs_datum' => current_time('mysql')
        ], ['id' => $id], ['%d', '%s'], ['%d']);

        // E-Mail an Gast senden (wenn E-Mail-Benachrichtigungen aktiviert sind)
        if (simpbook_get_option('simpbook_email_benachrichtigungen', '1') === '1') {
            $this->simpbook_sende_stornierungs_email($id);
        }

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for page routing/filtering only
        $redirect_url = isset($_GET['simpbook_redirect_to']) ? esc_url_raw(wp_unslash($_GET['simpbook_redirect_to'])) : admin_url('admin.php?page=simpbook-reservierungen&simpbook_view=list&simpbook_nachricht=storniert');
        wp_safe_redirect($redirect_url);
        exit;
    }

    /**
     * Storniert eine Reservierung per Token (Frontend).
     * @param string $token Stornierungs-Token
     * @return bool True bei Erfolg, False bei Fehler
     */
    public function simpbook_frontend_reservierung_stornieren($token) {
        global $wpdb;
        $tabellen_name = $wpdb->prefix . 'buchungen';

        // Reservierung anhand Token finden
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $reservierung = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM %i WHERE stornierungs_token = %s AND storniert = 0",
            $tabellen_name,
            $token
        ));

        if (!$reservierung) {
            return false;
        }

        // Als storniert markieren
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $result = $wpdb->update($tabellen_name, [
            'storniert' => 1,
            'stornierungs_datum' => current_time('mysql')
        ], ['id' => $reservierung->id], ['%d', '%s'], ['%d']);

        if ($result === false) {
            return false;
        }

        // E-Mail an Gast senden (wenn E-Mail-Benachrichtigungen aktiviert sind)
        if (simpbook_get_option('simpbook_email_benachrichtigungen', '1') === '1') {
            $this->simpbook_sende_stornierungs_email($reservierung->id);
        }

        return true;
    }

    /**
     * AJAX-Handler für Frontend-Stornierung.
     */
    public function simpbook_ajax_cancel_reservation() {
        if (!isset($_POST['simpbook_token']) || !isset($_POST['simpbook_nonce'])) {
            wp_send_json_error('Token oder Nonce fehlt');
            exit;
        }

        $token = sanitize_text_field(wp_unslash($_POST['simpbook_token']));
        $nonce = sanitize_text_field(wp_unslash($_POST['simpbook_nonce']));

        if (!wp_verify_nonce($nonce, 'simpbook_cancel_' . $token)) {
            wp_send_json_error('Security check failed');
            exit;
        }

        $result = $this->simpbook_frontend_reservierung_stornieren($token);

        if ($result) {
            wp_send_json_success(__('Reservierung wurde erfolgreich storniert.', 'simple-appointment-booking'));
        } else {
            wp_send_json_error(__('The reservation could not be cancelled. It may have already been cancelled.', 'simple-appointment-booking'));
        }
        exit;
    }

    /**
     * Behandelt Stornierungs-Anfragen über URL-Parameter.
     */
    public function simpbook_handle_cancellation_request() {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter for cancellation detection only
        if (!isset($_GET['simpbook_cancel'])) {
            return;
        }
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameter validated by token check
        $token = sanitize_text_field(wp_unslash($_GET['simpbook_cancel']));

        if (empty($token)) {
            return;
        }

        // Template laden
        $template_path = plugin_dir_path(dirname(__FILE__)) . 'templates/stornierung.php';

        if (file_exists($template_path)) {
            // GET-Parameter für Template setzen
            $_GET['simpbook_token'] = $token;
            include $template_path;
            exit;
        }
    }

    /**
     * Ändert den Status einer Reservierung.
     */
    public function simpbook_status_aendern($id, $neuer_status_val) {
        global $wpdb; $tabellen_name = $wpdb->prefix . 'buchungen';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Plugin-specific table
        $alter_status_db_val = $wpdb->get_var($wpdb->prepare("SELECT status FROM %i WHERE id = %d", $tabellen_name, $id));

        // Prüfe ob status_geaendert_datum Spalte existiert, falls nicht hinzufügen
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
        $columns = $wpdb->get_col($wpdb->prepare("DESCRIBE %i", $tabellen_name));

        if (!in_array('status_geaendert_datum', $columns, true)) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- Schema change required for plugin update
            $wpdb->query($wpdb->prepare("ALTER TABLE %i ADD status_geaendert_datum datetime NULL AFTER status", $tabellen_name));
        }

        // Aktuelles Datum und Uhrzeit für Statusänderung
        $status_geaendert_datum = current_time('mysql');

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Plugin-specific table
        $wpdb->update($tabellen_name, ['status' => $neuer_status_val, 'status_geaendert_datum' => $status_geaendert_datum], ['id' => $id], ['%s', '%s'], ['%d']);
        if ($alter_status_db_val !== $neuer_status_val && simpbook_get_option('simpbook_email_benachrichtigungen', '1') === '1') {
            $this->simpbook_benachrichtige_gast_ueber_statusaenderung($id, $neuer_status_val);
        }
        // Kein Redirect hier - das wird im aufrufenden Code gemacht
        return true;
    }

    /**
     * Ruft alle Reservierungen ab, optional gefiltert und sortiert.
     */
    public function simpbook_alle_reservierungen_holen($limit = 20, $offset = 0, $order_by = 'datum', $direction = 'ASC', $filter_condition = '1=1') {
        global $wpdb; $table_name = $wpdb->prefix . 'buchungen';
        $valid_cols = ['id', 'name', 'email', 'telefon', 'datum', 'uhrzeit', 'status', 'erstellungsdatum'];
        $order_by_safe = in_array($order_by, $valid_cols) ? $order_by : 'datum';
        $direction_safe = strtoupper($direction) === 'DESC' ? 'DESC' : 'ASC';

        // Prepare SQL query with safe table name and validated filter condition
        // Note: $table_name is safe (from $wpdb->prefix), $filter_condition should be validated by caller
        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        // Table name and filter condition are validated/sanitized before use
        $sql = "SELECT * FROM `{$table_name}` WHERE {$filter_condition} ORDER BY `{$order_by_safe}` {$direction_safe}";
        if ($limit !== PHP_INT_MAX) {
            $sql .= $wpdb->prepare(" LIMIT %d OFFSET %d", $limit, $offset);
        }

        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,PluginCheck.Security.DirectDB.UnescapedDBParameter -- Plugin-specific table with dynamic filter, filter condition is validated
        $results = $wpdb->get_results($sql);

        return $results ?: [];
    }

    /**
     * Sendet eine Stornierungs-E-Mail an den Gast.
     */
    public function simpbook_sende_stornierungs_email($reservierungs_id_val) {
        global $wpdb; $tabellen_name = $wpdb->prefix . 'buchungen';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
        $reservierung = $wpdb->get_row($wpdb->prepare("SELECT * FROM %i WHERE id = %d", $tabellen_name, $reservierungs_id_val));
        if (!$reservierung) return false;

        $default_map = simpbook_get_default_settings_map();
        $firmen_name = simpbook_get_option('simpbook_firmen_name', $default_map['simpbook_firmen_name']);
        $datum_obj = new DateTime($reservierung->datum);

        $current_language_for_email = simpbook_get_current_language();
        $datum_formatted = simpbook_format_date($reservierung->datum, $current_language_for_email);
        $uhrzeit_formatted = simpbook_format_time($reservierung->uhrzeit, $current_language_for_email);

        // Dienstleistung und Mitarbeiter laden
        $dienstleistung = isset($reservierung->dienstleistung_id) && $reservierung->dienstleistung_id > 0
            ? simpbook_get_dienstleistung($reservierung->dienstleistung_id)
            : null;
        $mitarbeiter = isset($reservierung->mitarbeiter_id) && $reservierung->mitarbeiter_id > 0
            ? simpbook_get_mitarbeiter($reservierung->mitarbeiter_id)
            : null;

        $service_name = $dienstleistung ? $dienstleistung->name : '';
        $employee_name = $mitarbeiter ? $mitarbeiter->name : '';
        $employee_name_label = __('Staff', 'simple-appointment-booking');

        // Buchungsoption laden
        $buchungsoption_gast_line = '';
        if (!empty($reservierung->buchungsoption_id) && (int)$reservierung->buchungsoption_id > 0) {
            $bo_table_name = $wpdb->prefix . 'simpbook_buchungsoptionen';
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $bo_row_st = $wpdb->get_row($wpdb->prepare("SELECT name FROM %i WHERE id = %d", $bo_table_name, (int)$reservierung->buchungsoption_id));
            if ($bo_row_st) {
                $buchungsoption_gast_line = __('Booking Option', 'simple-appointment-booking') . ': ' . $bo_row_st->name;
            }
        }

        // Buchungsoption-Preis laden
        $bo_preis_storniert = '';
        if (!empty($reservierung->buchungsoption_id) && (int)$reservierung->buchungsoption_id > 0 && !empty($reservierung->dienstleistung_id)) {
            $dl_bo_table_st = $wpdb->prefix . 'simpbook_dienstleistung_buchungsoptionen';
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $bo_preis_row_st = $wpdb->get_row($wpdb->prepare("SELECT preis FROM %i WHERE dienstleistung_id = %d AND buchungsoption_id = %d LIMIT 1", $dl_bo_table_st, (int)$reservierung->dienstleistung_id, (int)$reservierung->buchungsoption_id));
            if ($bo_preis_row_st && !empty($bo_preis_row_st->preis)) {
                $bo_preis_storniert = $bo_preis_row_st->preis;
            }
        }
        $gast_preis_storniert = !empty($bo_preis_storniert) ? $bo_preis_storniert : (!empty($dienstleistung->preis) ? $dienstleistung->preis : '');

        $daten_fuer_platzhalter = [
            'name' => $reservierung->name,
            'email' => $reservierung->email,
            'date' => $datum_formatted,
            'datum' => $datum_formatted,
            'time' => $uhrzeit_formatted,
            'uhrzeit' => $uhrzeit_formatted,
            'service_name' => $service_name,
            'employee_name' => $employee_name,
            'employee_name_label' => $employee_name_label,
            'booking_option' => $buchungsoption_gast_line,
            'booking_price' => $gast_preis_storniert,
            'company_name' => $firmen_name,
            'firmen_name' => $firmen_name, // Rückwärtskompatibilität
            'restaurant_name' => $firmen_name, // Fallback für Kompatibilität
        ];

        $betreff = $this->simpbook_ersetze_platzhalter(simpbook_get_email_template('simpbook_email_storniert_betreff', '', $current_language_for_email), $daten_fuer_platzhalter);
        $nachricht = $this->simpbook_ersetze_platzhalter(simpbook_get_email_template('simpbook_email_storniert_nachricht', '', $current_language_for_email), $daten_fuer_platzhalter);

        $html_body_storniert    = simpbook_build_guest_html_email($betreff, $nachricht, $firmen_name, 'simpbook_email_storniert_nachricht');
        $html_headers_storniert = array('Content-Type: text/html; charset=UTF-8');
        wp_mail($reservierung->email, $betreff, $html_body_storniert, $html_headers_storniert);
        return true;
    }

    /**
     * Sendet eine Erinnerungs-E-Mail an den Gast X Stunden vor dem Termin.
     */
    public function simpbook_sende_erinnerungs_email($reservierungs_id_val) {
        global $wpdb;
        $tabellen_name = $wpdb->prefix . 'buchungen';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
        $reservierung = $wpdb->get_row($wpdb->prepare("SELECT * FROM %i WHERE id = %d", $tabellen_name, $reservierungs_id_val));
        if (!$reservierung) {
            return false;
        }

        $default_map = simpbook_get_default_settings_map();
        $firmen_name = simpbook_get_option('simpbook_firmen_name', $default_map['simpbook_firmen_name']);

        $current_language_for_email = simpbook_get_current_language();
        $datum_formatted = simpbook_format_date($reservierung->datum, $current_language_for_email);
        $uhrzeit_formatted = simpbook_format_time($reservierung->uhrzeit, $current_language_for_email);

        // Dienstleistung und Mitarbeiter laden
        $dienstleistung = isset($reservierung->dienstleistung_id) && $reservierung->dienstleistung_id > 0
            ? simpbook_get_dienstleistung($reservierung->dienstleistung_id)
            : null;
        $mitarbeiter = isset($reservierung->mitarbeiter_id) && $reservierung->mitarbeiter_id > 0
            ? simpbook_get_mitarbeiter($reservierung->mitarbeiter_id)
            : null;

        $service_name = $dienstleistung ? $dienstleistung->name : '';
        $employee_name = $mitarbeiter ? $mitarbeiter->name : '';
        $employee_name_label = __('Staff', 'simple-appointment-booking');

        // Buchungsoption laden
        $buchungsoption_gast_line = '';
        if (!empty($reservierung->buchungsoption_id) && (int)$reservierung->buchungsoption_id > 0) {
            $bo_table_name = $wpdb->prefix . 'simpbook_buchungsoptionen';
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $bo_row_er = $wpdb->get_row($wpdb->prepare("SELECT name FROM %i WHERE id = %d", $bo_table_name, (int)$reservierung->buchungsoption_id));
            if ($bo_row_er) {
                $buchungsoption_gast_line = __('Booking Option', 'simple-appointment-booking') . ': ' . $bo_row_er->name;
            }
        }

        // Buchungsoption-Preis laden
        $bo_preis_erinnerung = '';
        if (!empty($reservierung->buchungsoption_id) && (int)$reservierung->buchungsoption_id > 0 && !empty($reservierung->dienstleistung_id)) {
            $dl_bo_table_er = $wpdb->prefix . 'simpbook_dienstleistung_buchungsoptionen';
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $bo_preis_row_er = $wpdb->get_row($wpdb->prepare("SELECT preis FROM %i WHERE dienstleistung_id = %d AND buchungsoption_id = %d LIMIT 1", $dl_bo_table_er, (int)$reservierung->dienstleistung_id, (int)$reservierung->buchungsoption_id));
            if ($bo_preis_row_er && !empty($bo_preis_row_er->preis)) {
                $bo_preis_erinnerung = $bo_preis_row_er->preis;
            }
        }
        $gast_preis_erinnerung = !empty($bo_preis_erinnerung) ? $bo_preis_erinnerung : (!empty($dienstleistung->preis) ? $dienstleistung->preis : '');

        // Stornierungs-Link generieren (nur wenn Token vorhanden)
        $cancellation_link = '';
        if (!empty($reservierung->stornierungs_token)) {
            $cancellation_link = home_url('/?simpbook_cancel=' . urlencode($reservierung->stornierungs_token));
        }

        $daten_fuer_platzhalter = [
            'name' => $reservierung->name,
            'email' => $reservierung->email,
            'date' => $datum_formatted,
            'datum' => $datum_formatted,
            'time' => $uhrzeit_formatted,
            'uhrzeit' => $uhrzeit_formatted,
            'service_name' => $service_name,
            'employee_name' => $employee_name,
            'employee_name_label' => $employee_name_label,
            'booking_option' => $buchungsoption_gast_line,
            'booking_price' => $gast_preis_erinnerung,
            'cancellation_link' => $cancellation_link,
            'company_name' => $firmen_name,
            'firmen_name' => $firmen_name, // Rückwärtskompatibilität
            'restaurant_name' => $firmen_name, // Fallback für Kompatibilität
        ];

        $betreff = $this->simpbook_ersetze_platzhalter(simpbook_get_email_template('simpbook_email_erinnerung_betreff', '', $current_language_for_email), $daten_fuer_platzhalter);
        $nachricht = $this->simpbook_ersetze_platzhalter(simpbook_get_email_template('simpbook_email_erinnerung_nachricht', '', $current_language_for_email), $daten_fuer_platzhalter);

        $html_body_erinnerung    = simpbook_build_guest_html_email($betreff, $nachricht, $firmen_name, 'simpbook_email_erinnerung_nachricht');
        $html_headers_erinnerung = array('Content-Type: text/html; charset=UTF-8');
        $success = wp_mail($reservierung->email, $betreff, $html_body_erinnerung, $html_headers_erinnerung);
        return $success;
    }

    /**
     * Benachrichtigt einen Gast über eine Statusänderung seiner Reservierung.
     */
    public function simpbook_benachrichtige_gast_ueber_statusaenderung($reservierungs_id_val, $neuer_status_val) {
        global $wpdb; $tabellen_name = $wpdb->prefix . 'buchungen';
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Plugin-specific table
        $reservierung = $wpdb->get_row($wpdb->prepare("SELECT * FROM %i WHERE id = %d", $tabellen_name, $reservierungs_id_val));
        if (!$reservierung) return false;

        $default_map = simpbook_get_default_settings_map();
        $firmen_name_opt_val = simpbook_get_option('simpbook_firmen_name', $default_map['simpbook_firmen_name']);
        $datum_obj_val = new DateTime($reservierung->datum);

        $current_language_for_email = simpbook_get_current_language();
        $datum_formatted = simpbook_format_date($reservierung->datum, $current_language_for_email);
        $uhrzeit_formatted = simpbook_format_time($reservierung->uhrzeit, $current_language_for_email);
        // Dienstleistung und Mitarbeiter laden
        $dienstleistung = isset($reservierung->dienstleistung_id) && $reservierung->dienstleistung_id > 0
            ? simpbook_get_dienstleistung($reservierung->dienstleistung_id)
            : null;
        $mitarbeiter = isset($reservierung->mitarbeiter_id) && $reservierung->mitarbeiter_id > 0
            ? simpbook_get_mitarbeiter($reservierung->mitarbeiter_id)
            : null;

        $service_name = $dienstleistung ? $dienstleistung->name : '';
        $employee_name = $mitarbeiter ? $mitarbeiter->name : '';
        $employee_name_label = __('Staff', 'simple-appointment-booking');

        // Buchungsoption laden
        $buchungsoption_gast_line = '';
        if (!empty($reservierung->buchungsoption_id) && (int)$reservierung->buchungsoption_id > 0) {
            $bo_table_name = $wpdb->prefix . 'simpbook_buchungsoptionen';
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $bo_row_sa = $wpdb->get_row($wpdb->prepare("SELECT name FROM %i WHERE id = %d", $bo_table_name, (int)$reservierung->buchungsoption_id));
            if ($bo_row_sa) {
                $buchungsoption_gast_line = __('Booking Option', 'simple-appointment-booking') . ': ' . $bo_row_sa->name;
            }
        }

        // Buchungsoption-Preis laden
        $bo_preis_status = '';
        if (!empty($reservierung->buchungsoption_id) && (int)$reservierung->buchungsoption_id > 0 && !empty($reservierung->dienstleistung_id)) {
            $dl_bo_table_sa = $wpdb->prefix . 'simpbook_dienstleistung_buchungsoptionen';
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $bo_preis_row_sa = $wpdb->get_row($wpdb->prepare("SELECT preis FROM %i WHERE dienstleistung_id = %d AND buchungsoption_id = %d LIMIT 1", $dl_bo_table_sa, (int)$reservierung->dienstleistung_id, (int)$reservierung->buchungsoption_id));
            if ($bo_preis_row_sa && !empty($bo_preis_row_sa->preis)) {
                $bo_preis_status = $bo_preis_row_sa->preis;
            }
        }
        $gast_preis_status = !empty($bo_preis_status) ? $bo_preis_status : (!empty($dienstleistung->preis) ? $dienstleistung->preis : '');

        // Stornierungs-Link generieren (nur wenn Token vorhanden)
        $cancellation_link = '';
        if (!empty($reservierung->stornierungs_token)) {
            $cancellation_link = home_url('/?simpbook_cancel=' . urlencode($reservierung->stornierungs_token));
        }

        $daten_fuer_platzhalter_val = [
            'name' => $reservierung->name,
            'email' => $reservierung->email,
            'date' => $datum_formatted, 'datum' => $datum_formatted,
            'time' => $uhrzeit_formatted, 'uhrzeit' => $uhrzeit_formatted,
            'service_name' => $service_name,
            'employee_name' => $employee_name,
            'employee_name_label' => $employee_name_label,
            'booking_option' => $buchungsoption_gast_line,
            'booking_price' => $gast_preis_status,
            'cancellation_link' => $cancellation_link,
            'status' => $neuer_status_val,
            'company_name' => $firmen_name_opt_val,
            'firmen_name' => $firmen_name_opt_val, // Rückwärtskompatibilität
            'restaurant_name' => $firmen_name_opt_val // Fallback für Kompatibilität
        ];

        $betreff_tpl_key = ''; $nachricht_tpl_key = '';
        if ($neuer_status_val === 'BESTÄTIGT') { $betreff_tpl_key = 'simpbook_email_bestaetigt_betreff'; $nachricht_tpl_key = 'simpbook_email_bestaetigt_nachricht'; }
        elseif ($neuer_status_val === 'ABGELEHNT') { $betreff_tpl_key = 'simpbook_email_abgelehnt_betreff'; $nachricht_tpl_key = 'simpbook_email_abgelehnt_nachricht'; }
        else { return false; }

        // Verwende leere Strings als Fallback, da simpbook_get_email_template() automatisch sprachspezifische Standardwerte verwendet
        $betreff_tpl_val = simpbook_get_email_template($betreff_tpl_key, '', $current_language_for_email);
        $nachricht_tpl_val = simpbook_get_email_template($nachricht_tpl_key, '', $current_language_for_email);

        $betreff_final = $this->simpbook_ersetze_platzhalter($betreff_tpl_val, $daten_fuer_platzhalter_val);
        $nachricht_final = $this->simpbook_ersetze_platzhalter($nachricht_tpl_val, $daten_fuer_platzhalter_val);

        $html_body_status    = simpbook_build_guest_html_email($betreff_final, $nachricht_final, $firmen_name_opt_val, $nachricht_tpl_key);
        $html_headers_status = array('Content-Type: text/html; charset=UTF-8');
        return wp_mail($daten_fuer_platzhalter_val['email'], $betreff_final, $html_body_status, $html_headers_status);
    }

    /**
     * Ersetzt Platzhalter in E-Mail-Vorlagen.
     * Unterstützt sowohl deutsche als auch englische Platzhalter für Rückwärtskompatibilität.
     */
    private function simpbook_ersetze_platzhalter($text_val, $daten_val) {
        // Remove entire lines for empty optional placeholders before performing replacements
        if (array_key_exists('employee_name', $daten_val) && $daten_val['employee_name'] === '') {
            $text_val = preg_replace('/[^\n]*\{employee_name\}[^\n]*(\n|$)/', '', $text_val);
        }
        if (array_key_exists('booking_option', $daten_val) && $daten_val['booking_option'] === '') {
            $text_val = preg_replace('/[^\n]*\{booking_option\}[^\n]*(\n|$)/', '', $text_val);
        }
        if (array_key_exists('booking_price', $daten_val) && $daten_val['booking_price'] === '') {
            $text_val = preg_replace('/[^\n]*\{booking_price\}[^\n]*(\n|$)/', '', $text_val);
        }

        // Mapping von deutschen zu englischen Platzhaltern
        $placeholder_mapping = [
            'name' => 'name',
            'email' => 'email',
            'telefon' => 'phone',
            'datum' => 'date',
            'uhrzeit' => 'time',
            'personen' => 'persons',
            'simpbook_nachricht' => 'message',
            'firmen_name' => 'company_name',
            'restaurant_name' => 'company_name',
            'personen_text' => 'persons_text'
        ];

        foreach ($daten_val as $key_val => $value_val) {
            // Englische Platzhalter (neue Standard)
            $english_key = isset($placeholder_mapping[$key_val]) ? $placeholder_mapping[$key_val] : $key_val;
            $text_val = str_replace('{' . $english_key . '}', $value_val, $text_val);

            // Deutsche Platzhalter (für Rückwärtskompatibilität)
            $text_val = str_replace('{' . $key_val . '}', $value_val, $text_val);

            // Spezifische Behandlung für {persons_text} / {personen_text}
            if ($key_val === 'personen' && is_numeric($value_val)) {
                // translators: %d: Number of people
                $personen_text_val = sprintf(_n('%d Person', '%d Personen', $value_val, 'simple-appointment-booking'), $value_val);
                $text_val = str_replace('{persons_text}', $personen_text_val, $text_val);
                $text_val = str_replace('{personen_text}', $personen_text_val, $text_val);
            }
        }
        return $text_val;
    }

    /**
     * Generiert HTML-Buttons für E-Mail-Aktionen mit optimierten VML/Tabellen für Outlook
     */
private function simpbook_generate_email_action_buttons($accept_url, $reject_url, $view_url, $language = 'de_DE') {
        // Sprachspezifische Button-Texte
        $button_labels = array(
            'de_DE' => array(
                'quick_actions' => 'Schnellaktionen:',
                'accept' => 'Annehmen',
                'reject' => 'Ablehnen',
                'details' => 'Details'
            ),
            'en_US' => array(
                'quick_actions' => 'Quick Actions:',
                'accept' => 'Accept',
                'reject' => 'Reject',
                'details' => 'Details'
            ),
            'en_US_AMPM' => array(
                'quick_actions' => 'Quick Actions:',
                'accept' => 'Accept',
                'reject' => 'Reject',
                'details' => 'Details'
            ),
            'it_IT' => array(
                'quick_actions' => 'Azioni Rapide:',
                'accept' => 'Accetta',
                'reject' => 'Rifiuta',
                'details' => 'Dettagli'
            ),
            'es_ES' => array(
                'quick_actions' => 'Acciones Rápidas:',
                'accept' => 'Aceptar',
                'reject' => 'Rechazar',
                'details' => 'Detalles'
            ),
            'fr_FR' => array(
                'quick_actions' => 'Actions Rapides:',
                'accept' => 'Accepter',
                'reject' => 'Refuser',
                'details' => 'Détails'
            ),
            'pl_PL' => array(
                'quick_actions' => 'Szybkie Akcje:',
                'accept' => 'Zaakceptuj',
                'reject' => 'Odrzuć',
                'details' => 'Szczegóły'
            ),
            'en_GB' => array(
                'quick_actions' => 'Quick Actions:',
                'accept' => 'Accept',
                'reject' => 'Reject',
                'details' => 'Details'
            ),
            'ru_RU' => array(
                'quick_actions' => 'Быстрые действия:',
                'accept' => 'Принять',
                'reject' => 'Отклонить',
                'details' => 'Подробности'
            ),
            'sv_SE' => array(
                'quick_actions' => 'Snabbåtgärder:',
                'accept' => 'Acceptera',
                'reject' => 'Avvisa',
                'details' => 'Detaljer'
            )
        );
        
        // Fallback auf Deutsch wenn Sprache nicht gefunden
        $labels = isset($button_labels[$language]) ? $button_labels[$language] : $button_labels['de_DE'];
        
        // Container Styles
        $container_style = 'margin:30px 0;text-align:center;padding:30px 20px;background:#f8f9fa;border-radius:12px;border:1px solid #e9ecef;';
        $header_style = 'font-size:16px;font-weight:600;color:#495057;margin:0 0 20px 0;font-family:Arial,sans-serif;';
        $separator_style = 'font-size:14px;color:#6c757d;margin:0 0 20px 0;letter-spacing:2px;';

        // Button Farben & Größen
        $accept_color = '#10b981';
        $reject_color = '#ef4444';
        $view_color = '#3b82f6';
        $button_width = 140; 
        $button_height = 46; 

        // Helper für Button-Generierung (VML + HTML)
        $generate_button = function($url, $label, $color, $width, $height) {
            $html = '';
            // VML für Outlook (Runde Ecken & Hintergrund)
            $html .= '<!--[if mso]>';
            $html .= '<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="' . esc_url($url) . '" style="height:' . $height . 'px;v-text-anchor:middle;width:' . $width . 'px;" arcsize="18%" stroke="f" fillcolor="' . $color . '">';
            $html .= '<w:anchorlock/>';
            $html .= '<center style="color:#ffffff;font-family:Arial,sans-serif;font-size:16px;font-weight:bold;">' . $label . '</center>';
            $html .= '</v:roundrect>';
            $html .= '<![endif]-->';
            
            // HTML für alle anderen Clients
            // WICHTIG: mso-hide:all verhindert doppelte Anzeige in Outlook
            $html .= '<a href="' . esc_url($url) . '" style="background-color:' . $color . ';border-radius:8px;color:#ffffff;display:inline-block;font-family:Arial,sans-serif;font-size:16px;font-weight:bold;line-height:' . $height . 'px;text-align:center;text-decoration:none;width:' . $width . 'px;-webkit-text-size-adjust:none;mso-hide:all;">' . $label . '</a>';
            
            return $html;
        };

        // Starte HTML Ausgabe
        $html = '<div style="' . $container_style . '">';
        $html .= '<p style="' . $separator_style . '">───────────────────</p>';
        $html .= '<p style="' . $header_style . '">' . $labels['quick_actions'] . '</p>';
        
        // HAUPT-TABELLE ZUR ZENTRIERUNG & LAYOUT (Outlook Fix für Nebeneinander)
        $html .= '<table border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;">';
        $html .= '<tr><td align="center">';
        
        // BUTTON-TABELLE (Damit sie nebeneinander bleiben)
        $html .= '<!--[if mso]><table border="0" cellpadding="0" cellspacing="0"><tr><![endif]-->';
        
        // BUTTON 1: ANNEHMEN
        $html .= '<!--[if mso]><td style="padding:0 5px;"><![endif]-->'; 
        $html .= '<div style="display:inline-block; vertical-align:top; margin:5px;">';
        $html .= $generate_button($accept_url, $labels['accept'], $accept_color, $button_width, $button_height);
        $html .= '</div>';
        $html .= '<!--[if mso]></td><![endif]-->';

        // BUTTON 2: ABLEHNEN
        $html .= '<!--[if mso]><td style="padding:0 5px;"><![endif]-->';
        $html .= '<div style="display:inline-block; vertical-align:top; margin:5px;">';
        $html .= $generate_button($reject_url, $labels['reject'], $reject_color, $button_width, $button_height);
        $html .= '</div>';
        $html .= '<!--[if mso]></td><![endif]-->';

        // BUTTON 3: DETAILS
        $html .= '<!--[if mso]><td style="padding:0 5px;"><![endif]-->';
        $html .= '<div style="display:inline-block; vertical-align:top; margin:5px;">';
        $html .= $generate_button($view_url, $labels['details'], $view_color, $button_width, $button_height);
        $html .= '</div>';
        $html .= '<!--[if mso]></td><![endif]-->';

        $html .= '<!--[if mso]></tr></table><![endif]-->';
        
        $html .= '</td></tr></table>'; // Ende Haupt-Tabelle
        $html .= '</div>'; // Ende Container

        return $html;
    }



    /**
     * Zählt Reservierungen basierend auf einer Filterbedingung.
     */
    public function simpbook_reservierungen_zaehlen($simpbook_filter_condition = '1=1') {
        global $wpdb; $simpbook_table_name = $wpdb->prefix . 'buchungen';
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $simpbook_count = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM %i WHERE $simpbook_filter_condition",
            $simpbook_table_name
        ));
        // phpcs:enable

        return intval($simpbook_count);
    }

    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Plugin-specific table
    public function simpbook_reservierung_holen($id_val) { global $wpdb; return $wpdb->get_row($wpdb->prepare("SELECT * FROM %i WHERE id = %d", $wpdb->prefix . 'buchungen', $id_val)); }

    /**
     * Exportiert Reservierungen als CSV-Datei.
     */
    public function simpbook_export_reservierungen_csv($filter_condition = '1=1', $order_by = 'datum', $direction = 'ASC') {
        $reservierungen = $this->simpbook_alle_reservierungen_holen(PHP_INT_MAX, 0, $order_by, $direction, $filter_condition);
        $filename = "reservierungen_" . gmdate('Y-m-d_H-i-s') . ".csv";

        if (ob_get_level() > 0) {
            ob_end_clean();
        }

        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Pragma: no-cache');
        header('Expires: 0');

        $output = fopen('php://output', 'w');
        if ($output === false) {

            echo esc_html__('Error creating CSV file. Please try again or contact support.', 'simple-appointment-booking');
            exit;
        }

        fprintf($output, chr(0xEF).chr(0xBB).chr(0xBF)); // BOM für UTF-8

        $header_row = array(
            __('ID', 'simple-appointment-booking'),
            __('Creation Date', 'simple-appointment-booking'),
            __('Name', 'simple-appointment-booking'),
            __('Email', 'simple-appointment-booking'),
            __('phone', 'simple-appointment-booking'),
            __('Date', 'simple-appointment-booking'),
            __('Time', 'simple-appointment-booking'),
            __('Service', 'simple-appointment-booking'),
            __('Staff', 'simple-appointment-booking'),
            __('Message', 'simple-appointment-booking'),
            __('Status', 'simple-appointment-booking'),
            __('Cancelled', 'simple-appointment-booking')
        );
        fputcsv($output, $header_row, ';', '"', '\\');

        if (!empty($reservierungen)) {
            foreach ($reservierungen as $reservierung) {
                // Dienstleistung und Mitarbeiter laden
                $dienstleistung = isset($reservierung->dienstleistung_id) && $reservierung->dienstleistung_id > 0
                    ? simpbook_get_dienstleistung($reservierung->dienstleistung_id)
                    : null;
                $mitarbeiter = isset($reservierung->mitarbeiter_id) && $reservierung->mitarbeiter_id > 0
                    ? simpbook_get_mitarbeiter($reservierung->mitarbeiter_id)
                    : null;

                $service_name = $dienstleistung ? $dienstleistung->name : '';
                $employee_name = $mitarbeiter ? $mitarbeiter->name : __('No Specific Staff Member', 'simple-appointment-booking');
                
                $row = array(
                    $reservierung->id,
                    $reservierung->erstellungsdatum,
                    $reservierung->name,
                    $reservierung->email,
                    $reservierung->telefon,
                    date_i18n(get_option('date_format', 'd.m.Y'), strtotime($reservierung->datum)),
                    date_i18n(get_option('time_format', 'H:i'), strtotime($reservierung->uhrzeit)),
                    $service_name,
                    $employee_name,
                    $reservierung->nachricht,
                    $reservierung->status,
                    $reservierung->storniert ? __('Ja', 'simple-appointment-booking') : __('Nein', 'simple-appointment-booking')
                );
                fputcsv($output, $row, ';', '"', '\\');
            }
        }
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- fclose() is required for php://output stream used in CSV export
        fclose($output);
        exit;
    }
}

/**
 * Token-System für E-Mail-Aktionslinks (ersetzt WordPress Nonces mit 7-Tage-Gültigkeit)
 */

/**
 * Erstellt einen sicheren Token für E-Mail-Aktionslinks
 * 
 * @param int $booking_id Die Reservierungs-ID
 * @param string $action Die Aktion (accept, reject)
 * @return string Der generierte Token (64 Zeichen)
 */
function simpbook_create_email_token($booking_id, $action) {
    global $wpdb;
    $tokens_table = $wpdb->prefix . 'simpbook_email_tokens';
    
    // Generiere kryptographisch sicheren Token
    $token = bin2hex(random_bytes(32)); // 64 Zeichen hex
    
    // Token-Gültigkeitsdauer: 14 Tage (berücksichtigt auch Urlaubszeiten)
    $expires_at = gmdate('Y-m-d H:i:s', strtotime('+14 days'));
    
    // Token in Datenbank speichern
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->insert(
        $tokens_table,
        [
            'token' => $token,
            'booking_id' => $booking_id,
            'action' => $action,
            'expires_at' => $expires_at
        ],
        ['%s', '%d', '%s', '%s']
    );
    
    return $token;
}

/**
 * Verifiziert einen Token und gibt die Token-Daten zurück
 * 
 * @param string $token Der zu prüfende Token
 * @param int $booking_id Die erwartete Reservierungs-ID
 * @return object|false Token-Daten bei Erfolg, false bei Fehler
 */
function simpbook_verify_email_token($token, $booking_id) {
    global $wpdb;
    $tokens_table = $wpdb->prefix . 'simpbook_email_tokens';
    
    // Token aus Datenbank abrufen
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $token_data = $wpdb->get_row($wpdb->prepare(
        "SELECT * FROM %i WHERE token = %s AND booking_id = %d",
        $tokens_table,
        $token,
        $booking_id
    ));
    
    if (!$token_data) {
        return false;
    }
    
    // Prüfen ob Token abgelaufen ist
    $now = current_time('mysql');
    if ($token_data->expires_at < $now) {
        // Abgelaufenen Token löschen
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->delete($tokens_table, ['id' => $token_data->id], ['%d']);
        return false;
    }
    
    return $token_data;
}

/**
 * Löscht einen Token nach erfolgreicher Verwendung
 * 
 * @param string $token Der zu löschende Token
 * @return bool True bei Erfolg
 */
function simpbook_delete_email_token($token) {
    global $wpdb;
    $tokens_table = $wpdb->prefix . 'simpbook_email_tokens';
    
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    return $wpdb->delete($tokens_table, ['token' => $token], ['%s']);
}

/**
 * Cron-Job: Löscht abgelaufene Tokens aus der Datenbank
 */
function simpbook_cleanup_expired_tokens() {
    global $wpdb;
    $tokens_table = $wpdb->prefix . 'simpbook_email_tokens';
    $now = current_time('mysql');
    
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->query($wpdb->prepare(
        "DELETE FROM %i WHERE expires_at < %s",
        $tokens_table,
        $now
    ));
}
add_action('simpbook_cleanup_expired_tokens', 'simpbook_cleanup_expired_tokens');

