<?php
/**
 * Helper-Funktionen für PocketBooking Calendar
 * 
 * Enthält: Options-Handler, E-Mail Templates, Sprach-Funktionen
 *
 * @package SimpleBookingCalendar
 * @since 1.1.3
 */

// Sicherheitsmaßnahme: Direkten Zugriff verhindern
if (!defined('ABSPATH')) {
    exit;
}

// === HILFSFUNKTIONEN FÜR OPTIONEN ===

function simpbook_get_option($option_name, $default = false) {
    return get_option($option_name, $default);
}

function simpbook_update_option($option_name, $value) {
    update_option($option_name, $value);
}

function simpbook_delete_option($option_name) {
    delete_option($option_name);
}

// === E-MAIL TEMPLATE FUNKTIONEN ===

/**
 * Generiert einen sprachspezifischen Option-Namen für E-Mail-Templates
 * @param string $base_option_name Basis-Option-Name (z.B. 'simpbook_email_bestaetigungs_betreff')
 * @param string|null $language Sprachcode (z.B. 'de_DE'). Wenn null, wird die aktuelle Plugin-Sprache verwendet
 * @return string Sprachspezifischer Option-Name
 */
function simpbook_get_language_specific_email_option_name($base_option_name, $language = null) {
    if ($language === null) {
        $language = simpbook_get_current_language();
    }
    return $base_option_name . '_' . $language;
}

/**
 * Gibt sprachspezifische Standardwerte für Email-Templates zurück
 * @param string $base_option_name Basis-Option-Name
 * @param string $language Sprachcode (z.B. 'de_DE', 'en_US', etc.)
 * @return string|false Standardwert für die angegebene Sprache, oder false wenn nicht gefunden
 */
function simpbook_get_email_template_defaults($base_option_name, $language) {
    $simpbook_defaults = array(
        'de_DE' => array(
            'simpbook_email_bestaetigungs_betreff' => 'Ihre Buchungsanfrage für {service_name} wurde erhalten',
            'simpbook_email_bestaetigungs_nachricht' => "Sehr geehrte(r) {name},\n\nvielen Dank für Ihre Anfrage bei {company_name}. Wir haben folgende Buchungsanfrage erhalten:\n\nDienstleistung: {service_name}\nDatum: {date}\nUhrzeit: {time}\n{booking_option}\nPreis: {booking_price}\n{employee_name_label}: {employee_name}\n\n{message}\n\nWir prüfen die Verfügbarkeit und werden uns so schnell wie möglich bei Ihnen zurück melden.\n\nMit freundlichen Grüßen\n{company_name}",
            'simpbook_email_bestaetigt_betreff' => 'Ihre Buchung für {service_name} wurde bestätigt',
            'simpbook_email_bestaetigt_nachricht' => "Sehr geehrte(r) {name},\n\nIhre Buchung für {service_name} am {date} um {time} Uhr wurde bestätigt.\n{booking_option}\nPreis: {booking_price}\n{employee_name_label}: {employee_name}\n\nSie können Ihre Buchung jederzeit über folgenden Link stornieren:\n{cancellation_link}\n\nWir freuen uns auf Ihren Besuch!\n\nMit freundlichen Grüßen\n{company_name}",
            'simpbook_email_abgelehnt_betreff' => 'Information zu Ihrer Buchungsanfrage',
            'simpbook_email_abgelehnt_nachricht' => "Sehr geehrte(r) {name},\n\nwir bedauern Ihnen mitteilen zu müssen, dass Ihre Buchungsanfrage für {service_name} am {date} um {time} Uhr leider nicht bestätigt werden kann.\n\nBitte kontaktieren Sie uns für alternative Termine oder bei Fragen.\n\nMit freundlichen Grüßen\n{company_name}",
            'simpbook_email_erinnerung_betreff' => 'Erinnerung: Ihr Termin für {service_name}',
            'simpbook_email_erinnerung_nachricht' => "Sehr geehrte(r) {name},\n\nwir möchten Sie daran erinnern, dass Sie einen Termin bei {company_name} haben:\n\nDienstleistung: {service_name}\nDatum: {date}\nUhrzeit: {time}\n{booking_option}\nPreis: {booking_price}\n{employee_name_label}: {employee_name}\n\nFalls Sie den Termin nicht wahrnehmen können, können Sie ihn hier stornieren:\n{cancellation_link}\n\nWir freuen uns auf Ihren Besuch!\n\nMit freundlichen Grüßen\n{company_name}",
            'simpbook_email_storniert_betreff' => 'Stornierung erfolgreich: {service_name} am {date}',
            'simpbook_email_storniert_nachricht' => "Sehr geehrte(r) {name},\n\nwir bestätigen den Erhalt Ihrer Stornierung.\n\nDer folgende Termin wurde erfolgreich aus unserem System entfernt:\n\nDienstleistung: {service_name}\nDatum: {date}\nUhrzeit: {time}\n\nSie können gerne jederzeit einen neuen Termin über unsere Website buchen, wenn Sie bereit sind.\n\nMit freundlichen Grüßen,\n{company_name}"
        ),
        'en_US' => array(
            'simpbook_email_bestaetigungs_betreff' => 'Your booking request for {service_name} has been received',
            'simpbook_email_bestaetigungs_nachricht' => "Dear {name},\n\nThank you for your booking request at {company_name}. We have received the following booking:\n\nService: {service_name}\nDate: {date}\nTime: {time}\n{booking_option}\nPrice: {booking_price}\n{employee_name_label}: {employee_name}\n\n{message}\n\nWe will check availability and get back to you as soon as possible.\n\nBest regards\n{company_name}",
            'simpbook_email_bestaetigt_betreff' => 'Your booking for {service_name} has been confirmed',
            'simpbook_email_bestaetigt_nachricht' => "Dear {name},\n\nYour booking for {service_name} on {date} at {time} has been confirmed.\n{booking_option}\nPrice: {booking_price}\n{employee_name_label}: {employee_name}\n\nYou can cancel your booking at any time using this link:\n{cancellation_link}\n\nWe look forward to your visit!\n\nBest regards\n{company_name}",
            'simpbook_email_abgelehnt_betreff' => 'Information regarding your booking request',
            'simpbook_email_abgelehnt_nachricht' => "Dear {name},\n\nWe regret to inform you that your booking request for {service_name} on {date} at {time} cannot be confirmed.\n\nPlease contact us for alternative dates or if you have any questions.\n\nBest regards\n{company_name}",
            'simpbook_email_erinnerung_betreff' => 'Reminder: Your booking for {service_name}',
            'simpbook_email_erinnerung_nachricht' => "Dear {name},\n\nWe would like to remind you of your appointment at {company_name}:\n\nService: {service_name}\nDate: {date}\nTime: {time}\n{booking_option}\nPrice: {booking_price}\n{employee_name_label}: {employee_name}\n\nIf you cannot make it, you can cancel here:\n{cancellation_link}\n\nWe look forward to your visit!\n\nBest regards\n{company_name}",
            'simpbook_email_storniert_betreff' => 'Cancellation successful: {service_name} on {date}',
            'simpbook_email_storniert_nachricht' => "Hello {name},\n\nWe confirm the receipt of your cancellation.\n\nThe following appointment has been successfully removed from our system:\n\nService: {service_name}\nDate: {date}\nTime: {time}\n\nFeel free to book a new slot via our website whenever you are ready.\n\nBest regards,\n{company_name}"
        ),
        'en_US_AMPM' => array(
            'simpbook_email_bestaetigungs_betreff' => 'Your booking request for {service_name} has been received',
            'simpbook_email_bestaetigungs_nachricht' => "Dear {name},\n\nThank you for your booking request at {company_name}. We have received the following booking:\n\nService: {service_name}\nDate: {date}\nTime: {time}\n{booking_option}\nPrice: {booking_price}\n{employee_name_label}: {employee_name}\n\n{message}\n\nWe will check availability and get back to you as soon as possible.\n\nBest regards\n{company_name}",
            'simpbook_email_bestaetigt_betreff' => 'Your booking for {service_name} has been confirmed',
            'simpbook_email_bestaetigt_nachricht' => "Dear {name},\n\nYour booking for {service_name} on {date} at {time} has been confirmed.\n{booking_option}\nPrice: {booking_price}\n{employee_name_label}: {employee_name}\n\nYou can cancel your booking at any time using this link:\n{cancellation_link}\n\nWe look forward to your visit!\n\nBest regards\n{company_name}",
            'simpbook_email_abgelehnt_betreff' => 'Information regarding your booking request',
            'simpbook_email_abgelehnt_nachricht' => "Dear {name},\n\nWe regret to inform you that your booking request for {service_name} on {date} at {time} cannot be confirmed.\n\nPlease contact us for alternative dates or if you have any questions.\n\nBest regards\n{company_name}",
            'simpbook_email_erinnerung_betreff' => 'Reminder: Your booking for {service_name}',
            'simpbook_email_erinnerung_nachricht' => "Dear {name},\n\nWe would like to remind you of your appointment at {company_name}:\n\nService: {service_name}\nDate: {date}\nTime: {time}\n{booking_option}\nPrice: {booking_price}\n{employee_name_label}: {employee_name}\n\nIf you cannot make it, you can cancel here:\n{cancellation_link}\n\nWe look forward to your visit!\n\nBest regards\n{company_name}",
            'simpbook_email_storniert_betreff' => 'Cancellation successful: {service_name} on {date}',
            'simpbook_email_storniert_nachricht' => "Hello {name},\n\nWe confirm the receipt of your cancellation.\n\nThe following appointment has been successfully removed from our system:\n\nService: {service_name}\nDate: {date}\nTime: {time}\n\nFeel free to book a new slot via our website whenever you are ready.\n\nBest regards,\n{company_name}"
        ),
        'it_IT' => array(
            'simpbook_email_bestaetigungs_betreff' => 'La tua richiesta per {service_name} è stata ricevuta',
            'simpbook_email_bestaetigungs_nachricht' => "Gentile {name},\n\nGrazie per la tua richiesta di prenotazione presso {company_name}. Abbiamo ricevuto la seguente prenotazione:\n\nServizio: {service_name}\nData: {date}\nOra: {time}\n{booking_option}\nPrezzo: {booking_price}\n{employee_name_label}: {employee_name}\n\n{message}\n\nControlleremo la disponibilità e ti risponderemo il prima possibile.\n\nCordiali saluti\n{company_name}",
            'simpbook_email_bestaetigt_betreff' => 'La tua prenotazione per {service_name} è stata confermata',
            'simpbook_email_bestaetigt_nachricht' => "Gentile {name},\n\nLa tua prenotazione per {service_name} il {date} alle {time} è stata confermata.\n{booking_option}\nPrezzo: {booking_price}\n{employee_name_label}: {employee_name}\n\nPuoi cancellare la tua prenotazione in qualsiasi momento utilizzando questo link:\n{cancellation_link}\n\nNon vediamo l'ora di vederti!\n\nCordiali saluti\n{company_name}",
            'simpbook_email_abgelehnt_betreff' => 'Informazioni sulla tua richiesta di prenotazione',
            'simpbook_email_abgelehnt_nachricht' => "Gentile {name},\n\nCi dispiace informarti che la tua richiesta di prenotazione per {service_name} il {date} alle {time} non può essere confermata.\n\nTi preghiamo di contattarci per date alternative o se hai domande.\n\nCordiali saluti\n{company_name}",
            'simpbook_email_erinnerung_betreff' => 'Promemoria: La tua prenotazione per {service_name}',
            'simpbook_email_erinnerung_nachricht' => "Gentile {name},\n\nVolevamo ricordarti il tuo appuntamento presso {company_name}:\n\nServizio: {service_name}\nData: {date}\nOra: {time}\n{booking_option}\nPrezzo: {booking_price}\n{employee_name_label}: {employee_name}\n\nSe non puoi presentarti, puoi cancellare qui:\n{cancellation_link}\n\nNon vediamo l'ora di vederti!\n\nCordiali saluti\n{company_name}",
            'simpbook_email_storniert_betreff' => 'Cancellazione riuscita: {service_name} il {date}',
            'simpbook_email_storniert_nachricht' => "Gentile {name},\n\nconfermiamo la ricezione della tua cancellazione.\n\nIl seguente appuntamento è stato rimosso con successo dal nostro sistema:\n\nServizio: {service_name}\nData: {date}\nOra: {time}\n\nSentiti libero di prenotare un nuovo appuntamento tramite il nostro sito web quando sarai pronto.\n\nCordiali saluti,\n{company_name}"
        ),
        'es_ES' => array(
            'simpbook_email_bestaetigungs_betreff' => 'Su solicitud para {service_name} ha sido recibida',
            'simpbook_email_bestaetigungs_nachricht' => "Estimado/a {name},\n\nGracias por su solicitud de reserva en {company_name}. Hemos recibido la siguiente reserva:\n\nServicio: {service_name}\nFecha: {date}\nHora: {time}\n{booking_option}\nPrecio: {booking_price}\n{employee_name_label}: {employee_name}\n\n{message}\n\nVerificaremos la disponibilidad y le responderemos lo antes posible.\n\nSaludos cordiales\n{company_name}",
            'simpbook_email_bestaetigt_betreff' => 'Su reserva para {service_name} ha sido confirmada',
            'simpbook_email_bestaetigt_nachricht' => "Estimado/a {name},\n\nSu reserva para {service_name} el {date} a las {time} ha sido confirmada.\n{booking_option}\nPrecio: {booking_price}\n{employee_name_label}: {employee_name}\n\nPuede cancelar su reserva en cualquier momento usando este enlace:\n{cancellation_link}\n\n¡Esperamos su visita!\n\nSaludos cordiales\n{company_name}",
            'simpbook_email_abgelehnt_betreff' => 'Información sobre su solicitud de reserva',
            'simpbook_email_abgelehnt_nachricht' => "Estimado/a {name},\n\nLamentamos informarle que su solicitud de reserva para {service_name} el {date} a las {time} no puede ser confirmada.\n\nPor favor, contáctenos para fechas alternativas o si tiene alguna pregunta.\n\nSaludos cordiales\n{company_name}",
            'simpbook_email_erinnerung_betreff' => 'Recordatorio: Su reserva para {service_name}',
            'simpbook_email_erinnerung_nachricht' => "Estimado/a {name},\n\nQueríamos recordarle su cita en {company_name}:\n\nServicio: {service_name}\nFecha: {date}\nHora: {time}\n{booking_option}\nPrecio: {booking_price}\n{employee_name_label}: {employee_name}\n\nSi no puede asistir, puede cancelar aquí:\n{cancellation_link}\n\n¡Esperamos verle!\n\nSaludos cordiales\n{company_name}",
            'simpbook_email_storniert_betreff' => 'Cancelación exitosa: {service_name} el {date}',
            'simpbook_email_storniert_nachricht' => "Estimado/a {name},\n\nconfirmamos la recepción de su cancelación.\n\nLa siguiente cita ha sido eliminada con éxito de nuestro sistema:\n\nServicio: {service_name}\nFecha: {date}\nHora: {time}\n\nNo dude en reservar un nuevo espacio a través de nuestro sitio web cuando esté listo.\n\nSaludos cordiales,\n{company_name}"
        ),
        'fr_FR' => array(
            'simpbook_email_bestaetigungs_betreff' => 'Votre demande pour {service_name} a été reçue',
            'simpbook_email_bestaetigungs_nachricht' => "Cher/Chère {name},\n\nMerci pour votre demande de réservation chez {company_name}. Nous avons reçu la réservation suivante:\n\nService: {service_name}\nDate: {date}\nHeure: {time}\n{booking_option}\nPrix : {booking_price}\n{employee_name_label}: {employee_name}\n\n{message}\n\nNous vérifierons la disponibilité et vous répondrons dans les plus brefs délais.\n\nCordialement\n{company_name}",
            'simpbook_email_bestaetigt_betreff' => 'Votre réservation pour {service_name} a été confirmée',
            'simpbook_email_bestaetigt_nachricht' => "Cher/Chère {name},\n\nVotre réservation pour {service_name} le {date} à {time} a été confirmée.\n{booking_option}\nPrix : {booking_price}\n{employee_name_label}: {employee_name}\n\nVous pouvez annuler votre réservation à tout moment en utilisant ce lien:\n{cancellation_link}\n\nNous avons hâte de vous voir!\n\nCordialement\n{company_name}",
            'simpbook_email_abgelehnt_betreff' => 'Information concernant votre demande de réservation',
            'simpbook_email_abgelehnt_nachricht' => "Cher/Chère {name},\n\nNous regrettons de vous informer que votre demande de réservation pour {service_name} le {date} à {time} ne peut pas être confirmée.\n\nVeuillez nous contacter pour des dates alternatives ou si vous avez des questions.\n\nCordialement\n{company_name}",
            'simpbook_email_erinnerung_betreff' => 'Rappel: Votre réservation pour {service_name}',
            'simpbook_email_erinnerung_nachricht' => "Cher/Chère {name},\n\nNous voulions vous rappeler votre rendez-vous chez {company_name}:\n\nService: {service_name}\nDate: {date}\nHeure: {time}\n{booking_option}\nPrix : {booking_price}\n{employee_name_label}: {employee_name}\n\nSi vous ne pouvez pas venir, vous pouvez annuler ici:\n{cancellation_link}\n\nNous avons hâte de vous voir!\n\nCordialement\n{company_name}",
            'simpbook_email_storniert_betreff' => 'Annulation réussie : {service_name} le {date}',
            'simpbook_email_storniert_nachricht' => "Bonjour {name},\n\nnous confirmons la réception de votre annulation.\n\nLe rendez-vous suivant a été supprimé avec succès de notre système :\n\nService : {service_name}\nDate : {date}\nHeure : {time}\n\nN'hésitez pas à réserver un nouveau rendez-vous via notre site web dès que vous serez prêt.\n\nCordialement,\n{company_name}"
        ),
        'pl_PL' => array(
            'simpbook_email_bestaetigungs_betreff' => 'Twoja prośba o {service_name} została otrzymana',
            'simpbook_email_bestaetigungs_nachricht' => "Szanowny/a {name},\n\nDziękujemy za Twoją prośbę o rezerwację w {company_name}. Otrzymaliśmy następującą rezerwację:\n\nUsługa: {service_name}\nData: {date}\nGodzina: {time}\n{booking_option}\nCena: {booking_price}\n{employee_name_label}: {employee_name}\n\n{message}\n\nSprawdzimy dostępność i skontaktujemy się z Tobą jak najszybciej.\n\nPozdrawiamy\n{company_name}",
            'simpbook_email_bestaetigt_betreff' => 'Twoja rezerwacja dla {service_name} została potwierdzona',
            'simpbook_email_bestaetigt_nachricht' => "Szanowny/a {name},\n\nTwoja rezerwacja dla {service_name} w dniu {date} o {time} została potwierdzona.\n{booking_option}\nCena: {booking_price}\n{employee_name_label}: {employee_name}\n\nMożesz anulować swoją rezerwację w dowolnym momencie, korzystając z tego linku:\n{cancellation_link}\n\nCzekamy na Twoją wizytę!\n\nPozdrawiamy\n{company_name}",
            'simpbook_email_abgelehnt_betreff' => 'Informacja dotycząca Twojej prośby o rezerwację',
            'simpbook_email_abgelehnt_nachricht' => "Szanowny/a {name},\n\nZ przykrością informujemy, że Twoja prośba o rezerwację dla {service_name} w dniu {date} o {time} nie może zostać potwierdzona.\n\nProsimy o kontakt w sprawie alternatywnych terminów lub w razie pytań.\n\nPozdrawiamy\n{company_name}",
            'simpbook_email_erinnerung_betreff' => 'Przypomnienie: Twoja rezerwacja dla {service_name}',
            'simpbook_email_erinnerung_nachricht' => "Szanowny/a {name},\n\nChcieliśmy Ci przypomnieć o Twojej wizycie w {company_name}:\n\nUsługa: {service_name}\nData: {date}\nGodzina: {time}\n{booking_option}\nCena: {booking_price}\n{employee_name_label}: {employee_name}\n\nJeśli nie możesz się pojawić, możesz anulować tutaj:\n{cancellation_link}\n\nCzekamy na Twoją wizytę!\n\nPozdrawiamy\n{company_name}",
            'simpbook_email_storniert_betreff' => 'Anulowanie zakończone sukcesem: {service_name} w dniu {date}',
            'simpbook_email_storniert_nachricht' => "Witaj {name},\n\npotwierdzamy otrzymanie Twojej rezygnacji.\n\nNastępująca wizyta została pomyślnie usunięta z naszego systemu:\n\nUsługa: {service_name}\nData: {date}\nGodzina: {time}\n\nZapraszamy do rezerwacji nowego terminu za pośrednictwem naszej strony internetowej, gdy tylko będziesz gotowy.\n\nPozdrawiamy,\n{company_name}"
        ),
        'en_GB' => array(
            'simpbook_email_bestaetigungs_betreff' => 'Your booking request for {service_name} has been received',
            'simpbook_email_bestaetigungs_nachricht' => "Dear {name},\n\nThank you for your booking request at {company_name}. We have received the following booking:\n\nService: {service_name}\nDate: {date}\nTime: {time}\n{booking_option}\nPrice: {booking_price}\n{employee_name_label}: {employee_name}\n\n{message}\n\nWe will check availability and get back to you as soon as possible.\n\nKind regards\n{company_name}",
            'simpbook_email_bestaetigt_betreff' => 'Your booking for {service_name} has been confirmed',
            'simpbook_email_bestaetigt_nachricht' => "Dear {name},\n\nYour booking for {service_name} on {date} at {time} has been confirmed.\n{booking_option}\nPrice: {booking_price}\n{employee_name_label}: {employee_name}\n\nYou can cancel your booking at any time using this link:\n{cancellation_link}\n\nWe look forward to seeing you!\n\nKind regards\n{company_name}",
            'simpbook_email_abgelehnt_betreff' => 'Information regarding your booking request',
            'simpbook_email_abgelehnt_nachricht' => "Dear {name},\n\nWe regret to inform you that your booking request for {service_name} on {date} at {time} cannot be confirmed.\n\nPlease contact us for alternative dates or if you have any questions.\n\nKind regards\n{company_name}",
            'simpbook_email_erinnerung_betreff' => 'Reminder: Your booking for {service_name}',
            'simpbook_email_erinnerung_nachricht' => "Dear {name},\n\nWe would like to remind you of your appointment at {company_name}:\n\nService: {service_name}\nDate: {date}\nTime: {time}\n{booking_option}\nPrice: {booking_price}\n{employee_name_label}: {employee_name}\n\nIf you are unable to attend, you can cancel here:\n{cancellation_link}\n\nWe look forward to seeing you!\n\nKind regards\n{company_name}",
            'simpbook_email_storniert_betreff' => 'Cancellation confirmed: {service_name} on {date}',
            'simpbook_email_storniert_nachricht' => "Dear {name},\n\nWe confirm the receipt of your cancellation.\n\nThe following appointment has been successfully removed from our system:\n\nService: {service_name}\nDate: {date}\nTime: {time}\n\nFeel free to book a new appointment via our website whenever you are ready.\n\nKind regards,\n{company_name}"
        ),
        'ru_RU' => array(
            'simpbook_email_bestaetigungs_betreff' => 'Ваш запрос на {service_name} получен',
            'simpbook_email_bestaetigungs_nachricht' => "Уважаемый/ая {name},\n\nСпасибо за Вашу заявку на бронирование в {company_name}. Мы получили следующий запрос:\n\nУслуга: {service_name}\nДата: {date}\nВремя: {time}\n{booking_option}\nЦена: {booking_price}\n{employee_name_label}: {employee_name}\n\n{message}\n\nМы проверим наличие свободных мест и свяжемся с Вами как можно скорее.\n\nС уважением\n{company_name}",
            'simpbook_email_bestaetigt_betreff' => 'Ваше бронирование {service_name} подтверждено',
            'simpbook_email_bestaetigt_nachricht' => "Уважаемый/ая {name},\n\nВаше бронирование {service_name} на {date} в {time} подтверждено.\n{booking_option}\nЦена: {booking_price}\n{employee_name_label}: {employee_name}\n\nВы можете отменить бронирование в любое время по следующей ссылке:\n{cancellation_link}\n\nБудем рады Вас видеть!\n\nС уважением\n{company_name}",
            'simpbook_email_abgelehnt_betreff' => 'Информация о Вашем запросе на бронирование',
            'simpbook_email_abgelehnt_nachricht' => "Уважаемый/ая {name},\n\nС сожалением сообщаем, что Ваш запрос на бронирование {service_name} на {date} в {time} не может быть подтверждён.\n\nПожалуйста, свяжитесь с нами для выбора другого времени или при наличии вопросов.\n\nС уважением\n{company_name}",
            'simpbook_email_erinnerung_betreff' => 'Напоминание: Ваше бронирование {service_name}',
            'simpbook_email_erinnerung_nachricht' => "Уважаемый/ая {name},\n\nНапоминаем, что у Вас запланирован визит в {company_name}:\n\nУслуга: {service_name}\nДата: {date}\nВремя: {time}\n{booking_option}\nЦена: {booking_price}\n{employee_name_label}: {employee_name}\n\nЕсли Вы не сможете прийти, отменить запись можно здесь:\n{cancellation_link}\n\nБудем рады Вас видеть!\n\nС уважением\n{company_name}",
            'simpbook_email_storniert_betreff' => 'Отмена выполнена: {service_name} на {date}',
            'simpbook_email_storniert_nachricht' => "Уважаемый/ая {name},\n\nПодтверждаем получение Вашей отмены.\n\nСледующая запись была успешно удалена из нашей системы:\n\nУслуга: {service_name}\nДата: {date}\nВремя: {time}\n\nВы можете записаться на новое время через наш сайт, когда будете готовы.\n\nС уважением,\n{company_name}"
        ),
        'sv_SE' => array(
            'simpbook_email_bestaetigungs_betreff' => 'Din bokningsbegäran för {service_name} har mottagits',
            'simpbook_email_bestaetigungs_nachricht' => "Kära {name},\n\nTack för din bokningsbegäran hos {company_name}. Vi har tagit emot följande bokning:\n\nTjänst: {service_name}\nDatum: {date}\nTid: {time}\n{booking_option}\nPris: {booking_price}\n{employee_name_label}: {employee_name}\n\n{message}\n\nVi kontrollerar tillgängligheten och återkommer till dig så snart som möjligt.\n\nMed vänliga hälsningar\n{company_name}",
            'simpbook_email_bestaetigt_betreff' => 'Din bokning av {service_name} har bekräftats',
            'simpbook_email_bestaetigt_nachricht' => "Kära {name},\n\nDin bokning av {service_name} den {date} kl. {time} har bekräftats.\n{booking_option}\nPris: {booking_price}\n{employee_name_label}: {employee_name}\n\nDu kan avboka när som helst via följande länk:\n{cancellation_link}\n\nVi ser fram emot ditt besök!\n\nMed vänliga hälsningar\n{company_name}",
            'simpbook_email_abgelehnt_betreff' => 'Information om din bokningsbegäran',
            'simpbook_email_abgelehnt_nachricht' => "Kära {name},\n\nVi beklagar att meddela att din bokningsbegäran för {service_name} den {date} kl. {time} tyvärr inte kan bekräftas.\n\nKontakta oss gärna för alternativa tider eller om du har frågor.\n\nMed vänliga hälsningar\n{company_name}",
            'simpbook_email_erinnerung_betreff' => 'Påminnelse: Din bokning av {service_name}',
            'simpbook_email_erinnerung_nachricht' => "Kära {name},\n\nVi vill påminna dig om din tid hos {company_name}:\n\nTjänst: {service_name}\nDatum: {date}\nTid: {time}\n{booking_option}\nPris: {booking_price}\n{employee_name_label}: {employee_name}\n\nOm du inte kan komma kan du avboka här:\n{cancellation_link}\n\nVi ser fram emot ditt besök!\n\nMed vänliga hälsningar\n{company_name}",
            'simpbook_email_storniert_betreff' => 'Avbokning genomförd: {service_name} den {date}',
            'simpbook_email_storniert_nachricht' => "Kära {name},\n\nVi bekräftar mottagandet av din avbokning.\n\nFöljande tid har tagits bort från vårt system:\n\nTjänst: {service_name}\nDatum: {date}\nTid: {time}\n\nDu är välkommen att boka en ny tid via vår webbplats när du är redo.\n\nMed vänliga hälsningar,\n{company_name}"
        )
    );

    // Validiere Sprache
    $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'; // Fallback auf Englisch
    }

    // Prüfe ob Standardwert für diese Sprache und Option existiert
    if (isset($simpbook_defaults[$language][$base_option_name])) {
        $simpbook_result = $simpbook_defaults[$language][$base_option_name];
        return $simpbook_result;
    }

    // Fallback auf Deutsch wenn nicht gefunden
    if (isset($simpbook_defaults['de_DE'][$base_option_name])) {
        $simpbook_result = $simpbook_defaults['de_DE'][$base_option_name];
        return $simpbook_result;
    }

    return false;
}

/**
 * Gibt die Standardwerte für Formular-Überschriften in verschiedenen Sprachen zurück
 * @param string $header_key Schlüssel der Überschrift (date, service, employee, time, contact)
 * @param string $language Sprachcode
 * @return string|false Standardwert oder false wenn nicht gefunden
 */
function simpbook_get_form_header_defaults($header_key, $language) {
    $simpbook_form_headers = array(
        'de_DE' => array(
            'date' => 'Wann möchten Sie reservieren? *',
            'service' => 'Welche Dienstleistung? *',
            'employee' => 'Welcher Mitarbeiter?',
            'time' => 'Zu welcher Uhrzeit? *',
            'contact' => 'Ihre Kontaktdaten',
            'ungrouped_services' => 'Weitere Dienstleistungen:',
            'booking_option' => 'Buchungsoption wählen',
            'confirmation' => 'Buchung bestätigen'
        ),
        'en_US' => array(
            'date' => 'When would you like to book? *',
            'service' => 'Which service? *',
            'employee' => 'Which employee?',
            'time' => 'What time? *',
            'contact' => 'Your contact details',
            'ungrouped_services' => 'Other Services:',
            'booking_option' => 'Choose Booking Option',
            'confirmation' => 'Confirm Your Reservation'
        ),
        'en_US_AMPM' => array(
            'date' => 'When would you like to book? *',
            'service' => 'Which service? *',
            'employee' => 'Which employee?',
            'time' => 'What time? *',
            'contact' => 'Your contact details',
            'ungrouped_services' => 'Other Services:',
            'booking_option' => 'Choose Booking Option',
            'confirmation' => 'Confirm Your Reservation'
        ),
        'en_GB' => array(
            'date' => 'When would you like to book? *',
            'service' => 'Which service? *',
            'employee' => 'Which employee?',
            'time' => 'What time? *',
            'contact' => 'Your contact details',
            'ungrouped_services' => 'Other Services:',
            'booking_option' => 'Choose Booking Option',
            'confirmation' => 'Confirm Your Reservation'
        ),
        'fr_FR' => array(
            'date' => 'Quand souhaitez-vous réserver ? *',
            'service' => 'Quel service ? *',
            'employee' => 'Quel employé ?',
            'time' => 'À quelle heure ? *',
            'contact' => 'Vos coordonnées',
            'ungrouped_services' => 'Autres services :',
            'booking_option' => 'Choisir une option de réservation',
            'confirmation' => 'Confirmer votre réservation'
        ),
        'es_ES' => array(
            'date' => '¿Cuándo desea reservar? *',
            'service' => '¿Qué servicio? *',
            'employee' => '¿Qué empleado?',
            'time' => '¿A qué hora? *',
            'contact' => 'Sus datos de contacto',
            'ungrouped_services' => 'Otros servicios:',
            'booking_option' => 'Elegir opción de reserva',
            'confirmation' => 'Confirmar su reserva'
        ),
        'it_IT' => array(
            'date' => 'Per quando desidera prenotare? *',
            'service' => 'Quale servizio? *',
            'employee' => 'Quale dipendente?',
            'time' => 'A che ora? *',
            'contact' => 'I tuoi dati di contatto',
            'ungrouped_services' => 'Altri servizi:',
            'booking_option' => 'Scegli un\'opzione di prenotazione',
            'confirmation' => 'Conferma la tua prenotazione'
        ),
        'pl_PL' => array(
            'date' => 'Na kiedy chcesz zarezerwować? *',
            'service' => 'Jaka usługa? *',
            'employee' => 'Który pracownik?',
            'time' => 'O której godzinie? *',
            'contact' => 'Twoje dane kontaktowe',
            'ungrouped_services' => 'Inne usługi:',
            'booking_option' => 'Wybierz opcję rezerwacji',
            'confirmation' => 'Potwierdź swoją rezerwację'
        ),
        'ru_RU' => array(
            'date' => 'На какое время вы хотите забронировать? *',
            'service' => 'Какая услуга? *',
            'employee' => 'Какой сотрудник?',
            'time' => 'В какое время? *',
            'contact' => 'Ваши контактные данные',
            'ungrouped_services' => 'Другие услуги:',
            'booking_option' => 'Выберите вариант бронирования',
            'confirmation' => 'Подтвердите вашу бронь'
        ),
        'sv_SE' => array(
            'date' => 'När vill du boka? *',
            'service' => 'Vilken tjänst? *',
            'employee' => 'Vilken anställd?',
            'time' => 'Vilken tid? *',
            'contact' => 'Dina kontaktuppgifter',
            'ungrouped_services' => 'Övriga tjänster:',
            'booking_option' => 'Välj bokningsalternativ',
            'confirmation' => 'Bekräfta din bokning'
        )
    );

    // Validiere Sprache
    $valid_languages = simpbook_get_supported_languages();
    if (!in_array($language, $valid_languages, true)) {
        $language = 'en_US'; // Fallback auf Englisch
    }

    // Prüfe ob Standardwert für diese Sprache und diesen Header existiert
    if (isset($simpbook_form_headers[$language][$header_key])) {
        return $simpbook_form_headers[$language][$header_key];
    }

    // Fallback auf Deutsch wenn nicht gefunden
    if (isset($simpbook_form_headers['de_DE'][$header_key])) {
        return $simpbook_form_headers['de_DE'][$header_key];
    }

    return false;
}

/**
 * Holt ein E-Mail-Template mit Sprachunterstützung
 * @param string $base_option_name Basis-Option-Name
 * @param string $default_value Standardwert (wird als Fallback verwendet, wenn keine sprachspezifischen Standardwerte gefunden werden)
 * @param string|null $language Sprachcode. Wenn null, wird die aktuelle Plugin-Sprache verwendet
 * @return string Template-Wert
 */
function simpbook_get_email_template($base_option_name, $default_value, $language = null) {
    // Bestimme die zu verwendende Sprache
    if ($language === null) {
        $language = simpbook_get_current_language();
    }

    $lang_specific_name = simpbook_get_language_specific_email_option_name($base_option_name, $language);
    $value = simpbook_get_option($lang_specific_name, '');

    // Prüfe explizit auf leeren String (nicht nur empty(), da '0' auch als empty gilt)
    if ($value === '' || trim($value) === '') {
        // WICHTIG: Überspringe globale Werte und verwende direkt sprachspezifische Standardwerte
        // Globale Werte werden ignoriert, um sicherzustellen, dass die richtige Sprache verwendet wird
        $language_default = simpbook_get_email_template_defaults($base_option_name, $language);
        if ($language_default !== false) {
            $value = $language_default;
        } else {
            // Letzter Fallback: übergebener Standardwert
            $value = $default_value;
        }
    }

    return $value;
}

/**
 * Speichert ein E-Mail-Template sprachspezifisch
 * @param string $base_option_name Basis-Option-Name
 * @param string $value Template-Wert
 * @param string|null $language Sprachcode. Wenn null, wird die aktuelle Plugin-Sprache verwendet
 */
function simpbook_save_email_template($base_option_name, $value, $language = null) {
    if ($language === null) {
        $language = simpbook_get_current_language();
    }
    $lang_specific_name = simpbook_get_language_specific_email_option_name($base_option_name, $language);

    // Wenn der Wert leer ist, lösche die Option, damit der Standardwert verwendet wird
    if (empty(trim($value))) {
        simpbook_delete_option($lang_specific_name);
    } else {
        simpbook_update_option($lang_specific_name, $value);
    }
}

/**
 * Holt eine Formular-Überschrift mit Sprachunterstützung
 * @param string $header_key Schlüssel der Überschrift (date, service, employee, time, contact)
 * @param string|null $language Sprachcode. Wenn null, wird die aktuelle Plugin-Sprache verwendet
 * @return string Überschrift
 */
function simpbook_get_form_header($header_key, $language = null) {
    // Prüfe auf Live-Vorschau-Überschreibung (wird gesetzt in simpbook_get_form_preview_ajax())
    global $simpbook_preview_headers;
    if (!empty($simpbook_preview_headers) && isset($simpbook_preview_headers[$header_key])) {
        return $simpbook_preview_headers[$header_key];
    }

    // Bestimme die zu verwendende Sprache
    if ($language === null) {
        $language = simpbook_get_current_language();
    }

    // Erstelle sprachspezifischen Option-Namen (z.B. simpbook_form_header_date_de_DE)
    $base_option_name = 'simpbook_form_header_' . $header_key;
    $lang_specific_name = $base_option_name . '_' . $language;
    $value = simpbook_get_option($lang_specific_name, '');

    // Prüfe explizit auf leeren String
    if ($value === '' || trim($value) === '') {
        // Hole sprachspezifischen Standardwert
        $language_default = simpbook_get_form_header_defaults($header_key, $language);
        if ($language_default !== false) {
            $value = $language_default;
        } else {
            // Letzter Fallback: leerer String
            $value = '';
        }
    }

    return $value;
}

/**
 * Speichert eine Formular-Überschrift sprachspezifisch
 * @param string $header_key Schlüssel der Überschrift (date, service, employee, time, contact)
 * @param string $value Überschrift-Text
 * @param string|null $language Sprachcode. Wenn null, wird die aktuelle Plugin-Sprache verwendet
 */
function simpbook_save_form_header($header_key, $value, $language = null) {
    if ($language === null) {
        $language = simpbook_get_current_language();
    }
    $base_option_name = 'simpbook_form_header_' . $header_key;
    $lang_specific_name = $base_option_name . '_' . $language;

    // Hole den sprachspezifischen Standardwert
    $default_value = simpbook_get_form_header_defaults($header_key, $language);

    // Wenn der Wert leer ist ODER dem Standardwert entspricht, lösche die Option
    // Dadurch wird immer der aktuelle Standardwert aus dem Code verwendet
    if (empty(trim($value)) || trim($value) === trim($default_value)) {
        simpbook_delete_option($lang_specific_name);
    } else {
        simpbook_update_option($lang_specific_name, $value);
    }
}

// === SPRACH-FUNKTIONEN ===

/**
 * Gibt die unterstützten Sprachen zurück
 * @return array
 */
function simpbook_get_supported_languages() {
    return array('de_DE', 'en_US', 'en_US_AMPM', 'en_GB', 'it_IT', 'es_ES', 'fr_FR', 'pl_PL', 'ru_RU', 'sv_SE');
}

/**
 * Gibt die WordPress-Sprache zurück und prüft ob sie unterstützt wird
 * @return string Die WordPress-Sprache oder 'en_US' als Fallback
 */
function simpbook_get_wordpress_language() {
    $wp_locale = get_locale();
    $supported = simpbook_get_supported_languages();

    // Direkte Übereinstimmung prüfen
    if (in_array($wp_locale, $supported, true)) {
        return $wp_locale;
    }

    // Spezialfall: de_DE_formal -> de_DE
    if (strpos($wp_locale, 'de_') === 0) {
        return 'de_DE';
    }

    // Spezialfall: en_GB bleibt en_GB (nicht mehr zu en_US mappen!)
    if ($wp_locale === 'en_GB') {
        return 'en_GB';
    }

    // Spezialfall: andere en_* Varianten -> en_US
    if (strpos($wp_locale, 'en_') === 0) {
        return 'en_US';
    }

    // Spezialfall: ru_* -> ru_RU
    if (strpos($wp_locale, 'ru_') === 0) {
        return 'ru_RU';
    }

    // Spezialfall: it_* -> it_IT
    if (strpos($wp_locale, 'it_') === 0) {
        return 'it_IT';
    }

    // Spezialfall: es_* -> es_ES
    if (strpos($wp_locale, 'es_') === 0) {
        return 'es_ES';
    }

    // Spezialfall: fr_* -> fr_FR
    if (strpos($wp_locale, 'fr_') === 0) {
        return 'fr_FR';
    }

    // Spezialfall: pl_* -> pl_PL
    if (strpos($wp_locale, 'pl_') === 0) {
        return 'pl_PL';
    }

    // Fallback auf Englisch
    return 'en_US';
}

/**
 * Hilfsfunktion: Gibt die aktuelle Plugin-Sprache zurück
 * Berücksichtigt automatische WordPress-Spracherkennung und manuelle Überschreibung
 */
function simpbook_get_current_language() {
    // Prüfe ob eine manuelle Überschreibung gesetzt ist
    $override = simpbook_get_option('simpbook_language_override', '');

    if (!empty($override) && $override !== 'auto') {
        // Manuelle Überschreibung aktiv
        $supported = simpbook_get_supported_languages();
        if (in_array($override, $supported, true)) {
            return $override;
        }
    }

    // Automatische Erkennung: WordPress-Sprache verwenden
    return simpbook_get_wordpress_language();
}

/**
 * Gibt den lesbaren Namen einer Sprache zurück
 */
function simpbook_get_language_name($locale) {
    $names = array(
        'de_DE' => 'German',
        'en_US' => 'English (US)',
        'en_US_AMPM' => 'English (US) - AM/PM',
        'en_GB' => 'English (UK)',
        'it_IT' => 'Italian',
        'es_ES' => 'Spanish',
        'fr_FR' => 'French',
        'pl_PL' => 'Polish',
        'ru_RU' => 'Русский',
    );
    return isset($names[$locale]) ? $names[$locale] : $locale;
}

/**
 * Gibt den nativen Namen einer Sprache zurück (wie er in der Sprache selbst geschrieben wird)
 * Wird für Dropdown-Optionen verwendet, damit jede Sprache in ihrer eigenen Schrift angezeigt wird
 */
function simpbook_get_language_native_name($locale) {
    $names = array(
        'de_DE' => 'German',
        'en_US' => 'English (US)',
        'en_US_AMPM' => 'English (US) - AM/PM',
        'en_GB' => 'English (UK)',
        'it_IT' => 'Italian',
        'es_ES' => 'Spanish',
        'fr_FR' => 'French',
        'pl_PL' => 'Polish',
        'ru_RU' => 'Русский',
        'sv_SE' => 'Svenska',
    );
    return isset($names[$locale]) ? $names[$locale] : $locale;
}

/**
 * Sanitize-Funktion für Sprache
 */
function simpbook_sanitize_language($input) {
    $valid_languages = simpbook_get_supported_languages();
    if (in_array($input, $valid_languages, true)) {
        return $input;
    }
    return 'en_US'; // Default
}

// === PUSH NOTIFICATION TRANSLATION SYSTEM ===

/**
 * Hart kodierte Übersetzungen für Push-Benachrichtigungen
 * 
 * Diese Funktion liefert Übersetzungen für Push-Notifications, da diese
 * serverseitig generiert werden müssen (der Service Worker kann nicht auf
 * WordPress-Übersetzungen zugreifen).
 * 
 * @param string $key Der Übersetzungsschlüssel
 * @param string|null $language Optional: Spezifische Sprache (falls null, wird aktuelle Plugin-Sprache verwendet)
 * @return string Der übersetzte Text
 */
function simpbook_get_push_translation($key, $language = null) {
    if ($language === null) {
        $language = simpbook_get_current_language();
    }
    
    // Normalisiere Sprache für Push (en_US_AMPM und en_GB -> en_US für einheitliche Texte)
    $lang_short = $language;
    if ($language === 'en_US_AMPM') {
        $lang_short = 'en_US';
    }
    // en_GB bleibt en_GB (separate Übersetzungen)
    
    // Translation Keys für Push-Benachrichtigungen
    $translations = array(
        // Neue Buchungsanfrage - Titel
        'push_new_booking_title' => array(
            'de_DE' => 'Neue Buchungsanfrage',
            'en_US' => 'New Booking Request',
            'en_GB' => 'New Booking Enquiry',
            'it_IT' => 'Nuova Richiesta di Prenotazione',
            'es_ES' => 'Nueva Solicitud de Reserva',
            'fr_FR' => 'Nouvelle Demande de Réservation',
            'pl_PL' => 'Nowe Zapytanie o Rezerwację',
            'ru_RU' => 'Новый запрос на бронирование',
        ),
        
        // Neue Buchungsanfrage - Body (mit Platzhaltern: %s = Name)
        'push_new_booking_body' => array(
            'de_DE' => 'Von %s',
            'en_US' => 'From %s',
            'en_GB' => 'From %s',
            'it_IT' => 'Da %s',
            'es_ES' => 'De %s',
            'fr_FR' => 'De %s',
            'pl_PL' => 'Od %s',
            'ru_RU' => 'От %s',
        ),
        
        // Neue Buchungsanfrage - Details (mit Platzhaltern: %s = Service, %s = Datum, %s = Uhrzeit)
        'push_booking_details' => array(
            'de_DE' => '%s am %s um %s',
            'en_US' => '%s on %s at %s',
            'en_GB' => '%s on %s at %s',
            'it_IT' => '%s il %s alle %s',
            'es_ES' => '%s el %s a las %s',
            'fr_FR' => '%s le %s à %s',
            'pl_PL' => '%s w dniu %s o %s',
            'ru_RU' => '%s на %s в %s',
        ),
        
        // Test-Benachrichtigung - Titel
        'push_test_title' => array(
            'de_DE' => 'Test Benachrichtigung',
            'en_US' => 'Test Notification',
            'en_GB' => 'Test Notification',
            'it_IT' => 'Notifica di Test',
            'es_ES' => 'Notificación de Prueba',
            'fr_FR' => 'Notification de Test',
            'pl_PL' => 'Powiadomienie Testowe',
            'ru_RU' => 'Тестовое уведомление',
        ),
        
        // Test-Benachrichtigung - Body
        'push_test_body' => array(
            'de_DE' => 'Dies ist eine Test-Nachricht vom PocketBooking PWA System. Funktioniert! ✓',
            'en_US' => 'This is a test message from the PocketBooking PWA system. Working! ✓',
            'en_GB' => 'This is a test message from the PocketBooking PWA system. Working! ✓',
            'it_IT' => 'Questo è un messaggio di test dal sistema PocketBooking PWA. Funziona! ✓',
            'es_ES' => 'Este es un mensaje de prueba del sistema PocketBooking PWA. ¡Funciona! ✓',
            'fr_FR' => 'Ceci est un message de test du système PocketBooking PWA. Fonctionne! ✓',
            'pl_PL' => 'To jest wiadomość testowa z systemu PocketBooking PWA. Działa! ✓',
            'ru_RU' => 'Это тестовое сообщение от системы PocketBooking PWA. Работает! ✓',
        ),
    );
    
    // Prüfe ob der Key existiert
    if (!isset($translations[$key])) {
        return $key; // Fallback: Key selbst zurückgeben
    }
    
    // Prüfe ob die Sprache existiert
    if (!isset($translations[$key][$lang_short])) {
        // Fallback-Logik: Englisch -> Deutsch -> Key
        if (isset($translations[$key]['en_US'])) {
            return $translations[$key]['en_US'];
        }
        if (isset($translations[$key]['de_DE'])) {
            return $translations[$key]['de_DE'];
        }
        return $key;
    }
    
    return $translations[$key][$lang_short];
}

// === GLOBALE GETTER FÜR DIENSTLEISTUNGEN & MITARBEITER ===

/**
 * Gibt alle Dienstleistungen zurück
 * @param bool $only_active Nur aktive Dienstleistungen
 * @return array
 */
function simpbook_get_all_dienstleistungen($only_active = true) {
    global $wpdb;
    $simpbook_table_name = $wpdb->prefix . 'dienstleistungen';
    $simpbook_where = $only_active ? "WHERE aktiv = 1" : "";
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
    $simpbook_results = $wpdb->get_results($wpdb->prepare("SELECT * FROM %i $simpbook_where ORDER BY sortierung ASC, name ASC", $simpbook_table_name));
    return $simpbook_results ?: [];
}

/**
 * Holt alle Dienstleistungen gruppiert nach Kategorie für das Frontend
 * 
 * @param bool $only_active Nur aktive Dienstleistungen
 * @return array Array mit Gruppen: [['kategorie' => object|null, 'dienstleistungen' => array], ...]
 */
function simpbook_get_dienstleistungen_grouped_for_frontend($only_active = true) {
    global $wpdb;
    $dienstleistungen_table = $wpdb->prefix . 'dienstleistungen';
    $kategorien_table = $wpdb->prefix . 'simpbook_dienstleistung_kategorien';
    
    $where = $only_active ? "WHERE d.aktiv = 1" : "";
    
    // Alle Kategorien abrufen (sortiert)
    $kategorien = simpbook_get_all_kategorien();
    
    $result = array();
    
    // Für jede Kategorie die Dienstleistungen laden
    foreach ($kategorien as $kategorie) {
        $where_kat = $only_active ? "WHERE aktiv = 1 AND kategorie_id = %d" : "WHERE kategorie_id = %d";
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $dienstleistungen = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$dienstleistungen_table} {$where_kat} ORDER BY sortierung ASC, name ASC",
            $kategorie->id
        ));
        // phpcs:enable
        
        if (!empty($dienstleistungen)) {
            $result[] = array(
                'kategorie' => $kategorie,
                'dienstleistungen' => $dienstleistungen
            );
        }
    }
    
    // Dienstleistungen ohne Kategorie
    $where_null = $only_active ? "WHERE aktiv = 1 AND (kategorie_id IS NULL OR kategorie_id = 0)" : "WHERE kategorie_id IS NULL OR kategorie_id = 0";
    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
    $ohne_kategorie = $wpdb->get_results(
        "SELECT * FROM {$dienstleistungen_table} {$where_null} ORDER BY sortierung ASC, name ASC"
    );
    // phpcs:enable
    
    if (!empty($ohne_kategorie)) {
        $result[] = array(
            'kategorie' => null,
            'dienstleistungen' => $ohne_kategorie
        );
    }
    
    return $result;
}

/**
 * Holt Dienstleistungen gefiltert nach einer bestimmten Kategorie (für Shortcode-Kategorie-Filter)
 *
 * @param string|int $kategorie_filter Kategorie-ID oder Name
 * @param bool       $only_active      Nur aktive Dienstleistungen
 * @return array Gleiches Format wie simpbook_get_dienstleistungen_grouped_for_frontend
 */
function simpbook_get_dienstleistungen_grouped_by_kategorie_filter($kategorie_filter, $only_active = true) {
    $kategorien = simpbook_get_all_kategorien();
    $matched_kategorie = null;
    foreach ($kategorien as $k) {
        if ((string)$k->id === (string)$kategorie_filter || mb_strtolower($k->name) === mb_strtolower((string)$kategorie_filter)) {
            $matched_kategorie = $k;
            break;
        }
    }
    if (!$matched_kategorie) {
        return [];
    }
    global $wpdb;
    $dienstleistungen_table = $wpdb->prefix . 'dienstleistungen';
    $where_kat = $only_active ? 'WHERE aktiv = 1 AND kategorie_id = %d' : 'WHERE kategorie_id = %d';
    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
    $dienstleistungen = $wpdb->get_results($wpdb->prepare(
        "SELECT * FROM {$dienstleistungen_table} {$where_kat} ORDER BY sortierung ASC, name ASC",
        $matched_kategorie->id
    ));
    // phpcs:enable
    if (empty($dienstleistungen)) {
        return [];
    }
    return array(array(
        'kategorie'        => $matched_kategorie,
        'dienstleistungen' => $dienstleistungen,
    ));
}

/**
 * Gibt eine einzelne Dienstleistung zurück
 * @param int $id Dienstleistungs-ID
 * @return object|null
 */
function simpbook_get_dienstleistung($simpbook_id) {
    global $wpdb;
    $simpbook_table_name = $wpdb->prefix . 'dienstleistungen';
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
    return $wpdb->get_row($wpdb->prepare("SELECT * FROM %i WHERE id = %d", $simpbook_table_name, $simpbook_id));
}

/**
 * Formatiert einen Dienstleistungsname mit Kategorie-Information (ohne Dauer)
 * @param object $dienstleistung Dienstleistungs-Objekt
 * @return string Formatierter Name im Format "Name - Kategorie"
 */
function simpbook_format_dienstleistung_name_with_kategorie($dienstleistung) {
    if (!$dienstleistung) {
        return '';
    }
    
    $name = $dienstleistung->name;
    
    // Kategorie-Name hinzufügen - zuerst prüfen ob bereits im Objekt vorhanden (durch JOIN)
    if (!empty($dienstleistung->kategorie_name)) {
        $name .= ' - ' . $dienstleistung->kategorie_name;
    } elseif (!empty($dienstleistung->kategorie_id)) {
        $kategorie = simpbook_get_kategorie($dienstleistung->kategorie_id);
        if ($kategorie && !empty($kategorie->name)) {
            $name .= ' - ' . $kategorie->name;
        }
    }
    
    return $name;
}

/**
 * Formatiert einen Dienstleistungsname mit Kategorie-Information
 * @param object $dienstleistung Dienstleistungs-Objekt
 * @return string Formatierter Name im Format "Name (Dauer Min.) - Kategorie"
 */
function simpbook_format_dienstleistung_with_kategorie($dienstleistung) {
    if (!$dienstleistung) {
        return '';
    }
    
    $name = $dienstleistung->name;
    
    // Dauer hinzufügen
    if (!empty($dienstleistung->dauer_minuten)) {
        $name .= ' (' . $dienstleistung->dauer_minuten . ' Min.)';
    }
    
    // Kategorie-Name hinzufügen - zuerst prüfen ob bereits im Objekt vorhanden (durch JOIN)
    if (!empty($dienstleistung->kategorie_name)) {
        $name .= ' - ' . $dienstleistung->kategorie_name;
    } elseif (!empty($dienstleistung->kategorie_id)) {
        $kategorie = simpbook_get_kategorie($dienstleistung->kategorie_id);
        if ($kategorie && !empty($kategorie->name)) {
            $name .= ' - ' . $kategorie->name;
        }
    }
    
    return $name;
}

/**
 * Gibt alle Dienstleistungen sortiert nach Kategorie-Sortierung zurück
 * @param bool $only_active Nur aktive Dienstleistungen
 * @return array Array von Dienstleistungs-Objekten sortiert nach Kategorien
 */
function simpbook_get_all_dienstleistungen_sorted_by_kategorie($only_active = true) {
    global $wpdb;
    $dienstleistungen_table = $wpdb->prefix . 'dienstleistungen';
    $kategorien_table = $wpdb->prefix . 'simpbook_dienstleistung_kategorien';
    
    $where = $only_active ? "WHERE d.aktiv = 1" : "";
    
    // Dienstleistungen mit JOINed Kategorie-Sortierung
    $sql = "SELECT d.*, 
                   k.sortierung as kategorie_sortierung, 
                   k.name as kategorie_name
            FROM {$dienstleistungen_table} d
            LEFT JOIN {$kategorien_table} k ON d.kategorie_id = k.id
            {$where}
            ORDER BY 
                CASE WHEN k.sortierung IS NULL THEN 1 ELSE 0 END,
                k.sortierung ASC, 
                d.sortierung ASC, 
                d.name ASC";
                
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
    $results = $wpdb->get_results($sql);
    
    return $results ?: [];
}

/**
 * Gibt alle Dienstleistungen mit formatiertem Namen (inkl. Kategorie) zurück
 * @param bool $only_active Nur aktive Dienstleistungen
 * @return array Array von Dienstleistungs-Objekten mit formatiertem display_name
 */
function simpbook_get_all_dienstleistungen_with_kategorie($only_active = true) {
    $dienstleistungen = simpbook_get_all_dienstleistungen($only_active);
    
    foreach ($dienstleistungen as $dienstleistung) {
        $dienstleistung->display_name = simpbook_format_dienstleistung_with_kategorie($dienstleistung);
    }
    
    return $dienstleistungen;
}

/**
 * Gibt alle Mitarbeiter zurück
 * @param bool $only_active Nur aktive Mitarbeiter
 * @param bool $only_frontend Nur Mitarbeiter die im Frontend angezeigt werden sollen
 * @return array
 */
function simpbook_get_all_mitarbeiter($only_active = true, $only_frontend = false) {
    global $wpdb;
    $simpbook_table_name = $wpdb->prefix . 'mitarbeiter';
    $simpbook_where_parts = [];
    if ($only_active) {
        $simpbook_where_parts[] = "aktiv = 1";
    }
    if ($only_frontend) {
        $simpbook_where_parts[] = "im_frontend_anzeigen = 1";
    }
    $simpbook_where = !empty($simpbook_where_parts) ? "WHERE " . implode(" AND ", $simpbook_where_parts) : "";
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
    $simpbook_results = $wpdb->get_results($wpdb->prepare("SELECT * FROM %i $simpbook_where ORDER BY sortierung ASC, name ASC", $simpbook_table_name));
    return $simpbook_results ?: [];
}

/**
 * Gibt einen einzelnen Mitarbeiter zurück
 * @param int $id Mitarbeiter-ID
 * @return object|null
 */
function simpbook_get_mitarbeiter($simpbook_id) {
    global $wpdb;
    $simpbook_table_name = $wpdb->prefix . 'mitarbeiter';
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
    return $wpdb->get_row($wpdb->prepare("SELECT * FROM %i WHERE id = %d", $simpbook_table_name, $simpbook_id));
}

/**
 * Gibt alle Mitarbeiter zurück, die eine bestimmte Dienstleistung anbieten
 * @param int $dienstleistung_id
 * @param bool $only_active
 * @param bool $only_frontend
 * @return array
 */
function simpbook_get_mitarbeiter_fuer_dienstleistung($simpbook_dienstleistung_id, $only_active = true, $only_frontend = false) {
    global $wpdb;
    $simpbook_mitarbeiter_table = $wpdb->prefix . 'mitarbeiter';
    $simpbook_relation_table = $wpdb->prefix . 'mitarbeiter_dienstleistungen';

    // Prüfen, ob für diese spezifische Dienstleistung Verknüpfungen existieren
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
    $relations_for_service = $wpdb->get_var($wpdb->prepare(
        "SELECT COUNT(*) FROM %i WHERE dienstleistung_id = %d",
        $simpbook_relation_table,
        $simpbook_dienstleistung_id
    ));

    // Wenn für diese Dienstleistung keine Verknüpfungen existieren, leeres Array zurückgeben
    if ($relations_for_service == 0) {
        return [];
    }

    $simpbook_query_where = "";
    if ($only_active) {
        $simpbook_query_where .= " AND m.aktiv = 1";
    }
    if ($only_frontend) {
        $simpbook_query_where .= " AND m.im_frontend_anzeigen = 1";
    }

    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
    $simpbook_results = $wpdb->get_results($wpdb->prepare(
        "SELECT m.* FROM %i m INNER JOIN %i md ON m.id = md.mitarbeiter_id WHERE md.dienstleistung_id = %d $simpbook_query_where ORDER BY m.sortierung ASC, m.name ASC",
        $simpbook_mitarbeiter_table,
        $simpbook_relation_table,
        $simpbook_dienstleistung_id
    ));
    // phpcs:enable

    // Fallback: Wenn immer noch keine Zuordnungen gefunden wurden, alle aktiven Mitarbeiter zurückgeben
    // Dies behebt das Problem nach Updates, wenn die Beziehungstabelle leer ist
    if (empty($simpbook_results)) {
        $simpbook_where_parts_fallback = [];
        if ($only_active) {
            $simpbook_where_parts_fallback[] = "aktiv = 1";
        }
        if ($only_frontend) {
            $simpbook_where_parts_fallback[] = "im_frontend_anzeigen = 1";
        }
        $simpbook_where_fallback = !empty($simpbook_where_parts_fallback) ? "WHERE " . implode(" AND ", $simpbook_where_parts_fallback) : "";
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $simpbook_results = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT * FROM %i $simpbook_where_fallback ORDER BY sortierung ASC, name ASC",
                $simpbook_mitarbeiter_table
            )
        );
        // phpcs:enable
    }

    return $simpbook_results ?: [];
}

/**
 * Gibt alle Dienstleistungen zurück, die ein Mitarbeiter anbietet
 * @param int $mitarbeiter_id
 * @param bool $only_active
 * @return array
 */
function simpbook_get_dienstleistungen_fuer_mitarbeiter($simpbook_mitarbeiter_id, $only_active = true) {
    global $wpdb;
    $simpbook_dienstleistungen_table = $wpdb->prefix . 'dienstleistungen';
    $simpbook_relation_table = $wpdb->prefix . 'mitarbeiter_dienstleistungen';

    $simpbook_query_where = "";
    if ($only_active) {
        $simpbook_query_where .= " AND d.aktiv = 1";
    }
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
$simpbook_results = $wpdb->get_results($wpdb->prepare(
    "SELECT d.* FROM %i d INNER JOIN %i md ON d.id = md.dienstleistung_id WHERE md.mitarbeiter_id = %d $simpbook_query_where ORDER BY d.sortierung ASC, d.name ASC",
    $simpbook_dienstleistungen_table,
    $simpbook_relation_table,
    $simpbook_mitarbeiter_id
));
// phpcs:enable

return $simpbook_results ?: [];
}

/**
 * Gibt die Gesamtdauer (Dauer + Pufferzeit) einer Dienstleistung zurück
 * @param int $dienstleistung_id
 * @return int Dauer in Minuten
 */
function simpbook_get_dienstleistungs_dauer($dienstleistung_id) {
    $dienstleistung = simpbook_get_dienstleistung($dienstleistung_id);
    if (!$dienstleistung) {
        return 0;
    }
    return intval($dienstleistung->dauer_minuten) + intval($dienstleistung->pufferzeit_minuten);
}

/**
 * Gibt die Arbeitszeiten eines Mitarbeiters zurück (als Array)
 * @param int $mitarbeiter_id
 * @return array|null
 */
function simpbook_get_mitarbeiter_arbeitszeiten($mitarbeiter_id) {
    $mitarbeiter = simpbook_get_mitarbeiter($mitarbeiter_id);
    if (!$mitarbeiter || empty($mitarbeiter->arbeitszeiten)) {
        return null;
    }
    $arbeitszeiten = json_decode($mitarbeiter->arbeitszeiten, true);
    return is_array($arbeitszeiten) ? $arbeitszeiten : null;
}

// === DATUM/ZEIT HELPER-FUNKTIONEN ===

/**
 * Prüft ob Mindestvorlaufzeit eingehalten wird
 * @param string $datum MySQL-Datum (YYYY-MM-DD)
 * @param string $uhrzeit MySQL-Zeit (HH:MM:SS)
 * @return bool
 */
function simpbook_pruefe_mindestvorlauf($datum, $uhrzeit) {
    $mindestvorlauf = intval(simpbook_get_option('simpbook_mindestvorlauf_stunden', 2));
    if ($mindestvorlauf <= 0) {
        return true; // Keine Mindestvorlaufzeit
    }

    $termin_timestamp = strtotime($datum . ' ' . $uhrzeit);
    $jetzt_timestamp = current_time('timestamp');
    $stunden_bis_termin = ($termin_timestamp - $jetzt_timestamp) / 3600;

    return $stunden_bis_termin >= $mindestvorlauf;
}

/**
 * Prüft ob Maximale Vorlaufzeit eingehalten wird
 * @param string $datum MySQL-Datum (YYYY-MM-DD)
 * @return bool
 */
function simpbook_pruefe_maximale_vorlauf($datum) {
    $maximale_vorlauf = intval(simpbook_get_option('simpbook_maximale_vorlauf_tage', 30));
    if ($maximale_vorlauf <= 0) {
        return true; // Keine Maximale Vorlaufzeit
    }

    $termin_timestamp = strtotime($datum);
    $jetzt_timestamp = current_time('timestamp');
    $tage_bis_termin = ($termin_timestamp - $jetzt_timestamp) / 86400;

    return $tage_bis_termin <= $maximale_vorlauf;
}

/**
 * Expandiert Urlaubs-Zeiträume in einzelne Datumsangaben.
 * @return string[] Array of YYYY-MM-DD strings
 */
function simpbook_expand_urlaub_dates() {
    $urlaub_konfiguration = get_option('simpbook_urlaub_konfiguration', array());
    if (empty($urlaub_konfiguration) || !is_array($urlaub_konfiguration)) {
        return array();
    }
    $dates = array();
    foreach ($urlaub_konfiguration as $zeitraum) {
        $von = isset($zeitraum['of']) ? $zeitraum['of'] : '';
        $bis = isset($zeitraum['bis']) ? $zeitraum['bis'] : '';
        if (!$von || !$bis || $bis < $von) {
            continue;
        }
        $start = new DateTime($von);
        $end   = new DateTime($bis);
        $end->modify('+1 day');
        $interval = new DateInterval('P1D');
        $period   = new DatePeriod($start, $interval, $end);
        foreach ($period as $date) {
            $dates[] = $date->format('Y-m-d');
        }
    }
    return array_values(array_unique($dates));
}

/**
 * Generiert einen eindeutigen Stornierungs-Token
 * @return string
 */
function simpbook_generiere_stornierungs_token() {
    return bin2hex(random_bytes(32));
}

/**
 * Gibt die übersetzten Monatsnamen für den Datepicker zurück.
 */
function simpbook_get_datepicker_month_names($language = null) {
    if ($language === null) {
        $language = simpbook_get_current_language();
    }

    $months = array(
        'de_DE' => array(
            'full' => array('Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'),
            'short' => array('Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez')
        ),
        'en_US' => array(
            'full' => array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'),
            'short' => array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
        ),
        'en_US_AMPM' => array(
            'full' => array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'),
            'short' => array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
        ),
        'it_IT' => array(
            'full' => array('Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre'),
            'short' => array('Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic')
        ),
        'es_ES' => array(
            'full' => array('Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'),
            'short' => array('Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic')
        ),
        'fr_FR' => array(
            'full' => array('Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'),
            'short' => array('Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Déc')
        ),
        'pl_PL' => array(
            'full' => array('Styczeń', 'Luty', 'Marzec', 'Kwiecień', 'Maj', 'Czerwiec', 'Lipiec', 'Sierpień', 'Wrzesień', 'Październik', 'Listopad', 'Grudzień'),
            'short' => array('Sty', 'Lut', 'Mar', 'Kwi', 'Maj', 'Cze', 'Lip', 'Sie', 'Wrz', 'Paź', 'Lis', 'Gru')
        )
    );

    if (isset($months[$language])) {
        return $months[$language];
    }

    // Fallback zu Englisch
    return $months['en_US'];
}

/**
 * Gibt die übersetzten Wochentagsnamen für den Datepicker zurück.
 */
function simpbook_get_datepicker_day_names($language = null) {
    if ($language === null) {
        $language = simpbook_get_current_language();
    }

    $days = array(
        'de_DE' => array(
            'full' => array('Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'),
            'short' => array('So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'),
            'min' => array('So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa')
        ),
        'en_US' => array(
            'full' => array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'),
            'short' => array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'),
            'min' => array('Su', 'Mon', 'Tu', 'We', 'Th', 'Fri', 'Sat')
        ),
        'en_US_AMPM' => array(
            'full' => array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'),
            'short' => array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'),
            'min' => array('Su', 'Mon', 'Tu', 'We', 'Th', 'Fri', 'Sat')
        ),
        'it_IT' => array(
            'full' => array('Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'),
            'short' => array('Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab'),
            'min' => array('Th', 'Lu', 'Ma', 'Me', 'Gi', 'Ve', 'Sat')
        ),
        'es_ES' => array(
            'full' => array('Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'),
            'short' => array('Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'),
            'min' => array('Th', 'Lu', 'Ma', 'We', 'Ju', 'Vi', 'Sá')
        ),
        'fr_FR' => array(
            'full' => array('Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'),
            'short' => array('Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'),
            'min' => array('Tu', 'Lu', 'Ma', 'Me', 'Je', 'Ve', 'Sat')
        ),
        'pl_PL' => array(
            'full' => array('Niedziela', 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota'),
            'short' => array('Nie', 'Pon', 'Wto', 'Śro', 'Czw', 'Pią', 'Sob'),
            'min' => array('Ni', 'Po', 'Wt', 'Śr', 'Cz', 'Pt', 'Su')
        )
    );

    if (isset($days[$language])) {
        return $days[$language];
    }

    // Fallback zu Englisch
    return $days['en_US'];
}

/**
 * Passt die Helligkeit einer Hex-Farbe an.
 */
function simpbook_adjust_brightness($hex_val, $steps_val) {
    $hex_val = str_replace('#', '', $hex_val);
    if (strlen($hex_val) == 3) $hex_val = str_repeat(substr($hex_val,0,1),2).str_repeat(substr($hex_val,1,1),2).str_repeat(substr($hex_val,2,1),2);
    $r_val = max(0,min(255,hexdec(substr($hex_val,0,2)) + $steps_val));
    $g_val = max(0,min(255,hexdec(substr($hex_val,2,2)) + $steps_val));
    $b_val = max(0,min(255,hexdec(substr($hex_val,4,2)) + $steps_val));
    return '#'.str_pad(dechex($r_val),2,'0',STR_PAD_LEFT).str_pad(dechex($g_val),2,'0',STR_PAD_LEFT).str_pad(dechex($b_val),2,'0',STR_PAD_LEFT);
}

/**
 * Formatiert ein Datum basierend auf der Plugin-Sprache.
 *
 * @param string $date_string Datum im Format YYYY-MM-DD
 * @param string|null $language Sprache (z.B. 'de_DE', 'en_US'). Wenn null, wird die aktuelle Plugin-Sprache verwendet.
 * @return string Formatiertes Datum (z.B. "24. Januar 2026" für Deutsch, "January 24, 2026" für Englisch)
 */
function simpbook_format_date($date_string, $language = null) {
    if (empty($date_string)) {
        return '';
    }

    if ($language === null) {
        $language = simpbook_get_current_language();
    }

    // Parse das Datum
    $date_obj = DateTime::createFromFormat('Y-m-d', $date_string);
    if ($date_obj === false) {
        // Fallback: Versuche strtotime
        $timestamp = strtotime($date_string);
        if ($timestamp === false) {
            return $date_string; // Fallback: Original zurückgeben
        }
        $date_obj = new DateTime();
        $date_obj->setTimestamp($timestamp);
    }

    // Hole Monatsnamen basierend auf der Sprache
    $month_names = simpbook_get_datepicker_month_names($language);
    $day = (int) $date_obj->format('d');
    $month_index = (int) $date_obj->format('n') - 1; // 0-basiert
    $year = (int) $date_obj->format('Y');

    // Formatiere basierend auf der Sprache
    switch ($language) {
        case 'de_DE':
            // Deutsch: "24. Januar 2026"
            return $day . '. ' . $month_names['full'][$month_index] . ' ' . $year;
        case 'en_US':
            // Englisch: "January 24, 2026"
            return $month_names['full'][$month_index] . ' ' . $day . ', ' . $year;
        case 'en_US_AMPM':
            // US-Englisch: "January 24, 2026"
            return $month_names['full'][$month_index] . ' ' . $day . ', ' . $year;
        case 'fr_FR':
            // Französisch: "24 janvier 2026"
            return $day . ' ' . strtolower($month_names['full'][$month_index]) . ' ' . $year;
        case 'it_IT':
            // Italienisch: "24 gennaio 2026"
            return $day . ' ' . strtolower($month_names['full'][$month_index]) . ' ' . $year;
        case 'es_ES':
            // Spanisch: "24 de enero de 2026"
            return $day . ' de ' . strtolower($month_names['full'][$month_index]) . ' de ' . $year;
        case 'pl_PL':
            // Polnisch: "24 stycznia 2026"
            return $day . ' ' . strtolower($month_names['full'][$month_index]) . ' ' . $year;
        default:
            // Fallback: Verwende WordPress date_i18n
            return date_i18n(get_option('date_format', 'd.m.Y'), $date_obj->getTimestamp());
    }
}

/**
 * Gibt das Zeitformat für eine Sprache zurück.
 *
 * @param string|null $language Sprache (z.B. 'de_DE', 'en_US_AMPM'). Wenn null, wird die aktuelle Plugin-Sprache verwendet.
 * @return string Zeitformat ('H:i' für 24h oder 'h:i A' für 12h mit AM/PM)
 */
function simpbook_get_time_format($language = null) {
    if ($language === null) {
        $language = simpbook_get_current_language();
    }

    // US-Sprache mit AM/PM verwendet 12-Stunden-Format
    if ($language === 'en_US_AMPM') {
        return 'h:i A';
    }

    // Alle anderen Sprachen verwenden 24-Stunden-Format
    return 'H:i';
}

/**
 * Formatiert eine Zeit basierend auf der Plugin-Sprache.
 *
 * @param string $time_string Zeit im Format H:i (24h)
 * @param string|null $language Sprache (z.B. 'de_DE', 'en_US_AMPM'). Wenn null, wird die aktuelle Plugin-Sprache verwendet.
 * @return string Formatierte Zeit (z.B. "14:30" oder "02:30 PM")
 */
function simpbook_format_time($time_string, $language = null) {
    if (empty($time_string)) {
        return '';
    }

    if ($language === null) {
        $language = simpbook_get_current_language();
    }

    // Parse die Zeit
    $time_obj = DateTime::createFromFormat('H:i', $time_string);
    if ($time_obj === false) {
        // Fallback: Versuche auch mit Sekunden
        $time_obj = DateTime::createFromFormat('H:i:s', $time_string);
        if ($time_obj === false) {
            return $time_string; // Fallback: Original zurückgeben
        }
    }

    // Wenn US-Sprache mit AM/PM, konvertiere zu 12h-Format
    if ($language === 'en_US_AMPM') {
        return $time_obj->format('h:i A');
    }

    // Alle anderen Sprachen: 24h-Format
    return $time_obj->format('H:i');
}

/**
 * Konvertiert eine Zeit vom 12h-Format (mit AM/PM) zurück zu 24h-Format.
 *
 * @param string $time_string Zeit im Format h:i A (z.B. "02:30 PM")
 * @return string Zeit im Format H:i (z.B. "14:30") oder Original-String bei Fehler
 */
function simpbook_parse_time_12h($time_string) {
    if (empty($time_string)) {
        return '';
    }

    // Versuche 12h-Format zu parsen
    $time_obj = DateTime::createFromFormat('h:i A', $time_string);
    if ($time_obj === false) {
        // Fallback: Versuche auch ohne führende Null
        $time_obj = DateTime::createFromFormat('g:i A', $time_string);
        if ($time_obj === false) {
            // Falls bereits im 24h-Format, direkt zurückgeben
            $time_obj_24h = DateTime::createFromFormat('H:i', $time_string);
            if ($time_obj_24h !== false) {
                return $time_obj_24h->format('H:i');
            }
            return $time_string; // Fallback: Original zurückgeben
        }
    }

    // Konvertiere zu 24h-Format
    return $time_obj->format('H:i');
}

// === USER MANAGEMENT HELPER ===

/**
 * DEMO-BENUTZER DASHBOARD CLEANUP
 * Entfernt alle nicht-benötigten Menüpunkte für Subscriber (Demo-Benutzer)
 */
function simpbook_clean_dashboard_for_demo_user() {
    $user = wp_get_current_user();
    
    // Nur für Abonnenten (Subscriber) ausführen
    if ( ! in_array( 'administrator', (array) $user->roles ) && in_array( 'subscriber', (array) $user->roles ) ) {
        global $menu;
        
        // Diese Slugs sind ERLAUBT (alles andere wird entfernt)
        $allowed_slugs = array( 
            'simpbook-dashboard', 
            'simpbook-reservierungen', 
            'simpbook-reservierungen-neu',
            'simpbook-dienstleistungen',
            'simpbook-mitarbeiter',
            'simpbook-kalender',
            'simpbook-statistiken',
            'simpbook-reservierungen-einstellungen'
        );
        
        // Wir loopen durch das globale Menü
        if ( ! empty( $menu ) ) {
            foreach ( $menu as $key => $item ) {
                $slug = $item[2]; // Der Slug steht an 3. Stelle (Index 2)
                
                // Wir entfernen alles, was nicht in der erlaubten Liste steht
                if ( ! in_array( $slug, $allowed_slugs ) ) {
                    remove_menu_page( $slug );
                }
            }
        }
        
        // Explizit das Profil entfernen (oft hartnäckig)
        remove_menu_page( 'profile.php' );
        
        // Zusätzlich: Entferne die Admin-Bar im Frontend für Abonnenten
        show_admin_bar( false );
    }
}
// Hohe Priorität (999), damit es NACH allen anderen Plugins ausgeführt wird
add_action( 'admin_menu', 'simpbook_clean_dashboard_for_demo_user', 999 );

/**
 * Redirect Subscriber zum Plugin-Dashboard
 * Verhindert Zugriff auf WordPress Standard-Dashboard
 */
function simpbook_redirect_subscriber_to_plugin() {
    $user = wp_get_current_user();
    if ( ! in_array( 'administrator', (array) $user->roles ) && in_array( 'subscriber', (array) $user->roles ) ) {
        // Prüfen ob wir gerade auf dem Dashboard (index.php) oder Profil (profile.php) sind
        global $pagenow;
        if ( $pagenow == 'index.php' || $pagenow == 'profile.php' ) {
            // Weiterleitung zum neuen Dashboard
            wp_safe_redirect( admin_url( 'admin.php?page=simpbook-dashboard' ) );
            exit;
        }
    }
}
add_action( 'admin_init', 'simpbook_redirect_subscriber_to_plugin' );

// === CRON-JOB FUNKTIONEN FÜR ERINNERUNGS-E-MAILS ===

/**
 * Registriert den Cron-Job für Erinnerungs-E-Mails.
 */
function simpbook_schedule_reminder_emails() {
    if (!wp_next_scheduled('simpbook_send_reminder_emails')) {
        wp_schedule_event(time(), 'hourly', 'simpbook_send_reminder_emails');
    }
}

/**
 * Prüft ob Cron-Job registriert ist und registriert ihn falls nötig.
 */
function simpbook_maybe_schedule_reminder_emails() {
    if (!wp_next_scheduled('simpbook_send_reminder_emails')) {
        simpbook_schedule_reminder_emails();
    }
}

/**
 * Entfernt den Cron-Job für Erinnerungs-E-Mails.
 */
function simpbook_unschedule_reminder_emails() {
    $timestamp = wp_next_scheduled('simpbook_send_reminder_emails');
    if ($timestamp) {
        wp_unschedule_event($timestamp, 'simpbook_send_reminder_emails');
    }
}

/**
 * Cron-Job Handler: Sendet Erinnerungs-E-Mails für anstehende Termine.
 */
function simpbook_send_reminder_emails_cron() {
    // Prüfe ob Erinnerungs-E-Mails aktiviert sind
    $erinnerung_aktiv = simpbook_get_option('simpbook_erinnerung_aktiv', 1);
    if (!$erinnerung_aktiv) {
        return;
    }

    // Stunden vor Termin abrufen
    $stunden_vor_termin = intval(simpbook_get_option('simpbook_erinnerung_vor_stunden', 24));
    if ($stunden_vor_termin < 1) {
        return;
    }

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

    // Berechne den Zeitpunkt X Stunden vor Termin (korrigiert)
    // Wir suchen nach Reservierungen, die GENAU in X Stunden stattfinden
    // (mit einer Toleranz von 1 Stunde um Cron-Timing-Probleme zu vermeiden)
    $jetzt_timestamp = current_time('timestamp');
    $target_timestamp = $jetzt_timestamp + ($stunden_vor_termin * 3600);
    $tolerance = 3600; // 1 Stunde Toleranz
    
    $from_timestamp = $target_timestamp - $tolerance;
    $to_timestamp = $target_timestamp + $tolerance;
    
    $from_str = gmdate('Y-m-d H:i:s', $from_timestamp);
    $to_str = gmdate('Y-m-d H:i:s', $to_timestamp);

    // Hole Reservierungen, die:
    // 1. Status BESTÄTIGT haben
    // 2. Nicht storniert sind
    // 3. Erinnerung noch nicht gesendet wurde
    // 4. Termin liegt in der Zeitspanne: JETZT + X Stunden (±1 Stunde Toleranz)
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
    $reservierungen = $wpdb->get_results($wpdb->prepare(
        "SELECT * FROM %i
        WHERE status = 'BESTÄTIGT'
        AND storniert = 0
        AND erinnerung_gesendet = 0
        AND CONCAT(datum, ' ', uhrzeit) >= %s
        AND CONCAT(datum, ' ', uhrzeit) <= %s",
        $tabellen_name,
        $from_str,
        $to_str
    ));

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

    // Plugin-Instanz für E-Mail-Versand
    global $simpbook_db_reservierungen_instance;
    if (!isset($simpbook_db_reservierungen_instance)) {
        $simpbook_db_reservierungen_instance = new simpbook_DB_Reservierungen();
    }

    foreach ($reservierungen as $reservierung) {
        // Erinnerungs-E-Mail senden
        $success = $simpbook_db_reservierungen_instance->simpbook_sende_erinnerungs_email($reservierung->id);

        if ($success) {
            // Flag setzen
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->update(
                $tabellen_name,
                ['erinnerung_gesendet' => 1],
                ['id' => $reservierung->id],
                ['%d'],
                ['%d']
            );
        }
    }
}
add_action('simpbook_send_reminder_emails', 'simpbook_send_reminder_emails_cron');

// === AJAX HANDLER ===

/**
 * AJAX Handler zum Löschen mehrerer Reservierungen
 */
function simpbook_delete_multiple_reservierungen() {
    // Nonce überprüfen
    if (!isset($_POST['simpbook_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['simpbook_nonce'])), 'simpbook_delete_multiple_reservierungen_nonce')) {
        wp_send_json_error('Nonce verification failed');
    }

    // Überprüfen Sie, ob der Benutzer die Berechtigung hat
    if (!current_user_can('read')) {
        wp_send_json_error('Insufficient permissions');
    }

    // IDs abrufen
    if (!isset($_POST['simpbook_ids']) || !is_array($_POST['simpbook_ids'])) {
        wp_send_json_error('No IDs provided');
    }

    $ids = array_map('intval', $_POST['simpbook_ids']);

    // Datenbankinstanz abrufen
    global $wpdb;
    $table = $wpdb->prefix . 'buchungen';

    $deleted_count = 0;
    foreach ($ids as $id) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
        $result = $wpdb->delete($table, ['id' => $id], ['%d']);
        if ($result !== false) {
            $deleted_count++;
        }
    }

    wp_send_json_success([
        'deleted' => $deleted_count,
        'total' => count($ids),
        'message' => sprintf(
            /* translators: 1: number of deleted bookings, 2: total number of bookings */
            esc_html__('%1$d of %2$d bookings deleted.', 'simple-appointment-booking'),
            $deleted_count,
            count($ids)
        )
    ]);
}
add_action('wp_ajax_simpbook_delete_multiple_reservierungen', 'simpbook_delete_multiple_reservierungen');

// === PWA HELPER FUNKTIONEN ===

/**
 * Prüft ob im PWA-Modus (über URL-Parameter UND PWA aktiviert)
 * 
 * @return bool True wenn PWA-Modus aktiv und PWA in Einstellungen aktiviert
 */
function simpbook_is_pwa_mode() {
    // Prüfen ob PWA in Einstellungen aktiviert ist
    $pwa_enabled = get_option('simpbook_pwa_enabled', '1') === '1';
    
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Simple GET check for display mode
    $pwa_param = isset($_GET['pwa']) && $_GET['pwa'] === '1';
    
    return $pwa_enabled && $pwa_param;
}

/**
 * Prüft ob PWA in den Einstellungen aktiviert ist
 * 
 * @return bool True wenn PWA aktiviert
 */
function simpbook_is_pwa_enabled() {
    return get_option('simpbook_pwa_enabled', '1') === '1';
}

/**
 * Prüft ob PWA-Navigation angezeigt werden soll
 * Kombiniert PWA-Modus mit Mobile-Check
 * 
 * @return bool True wenn PWA-Navigation angezeigt werden soll
 */
function simpbook_should_show_pwa_nav() {
    return simpbook_is_pwa_mode();
}

/**
 * Fügt PWA-Parameter zu Admin-URLs hinzu
 * 
 * @param string $page_slug WordPress Admin Page Slug
 * @param array $additional_params Zusätzliche Query-Parameter
 * @return string URL mit PWA-Parameter
 */
function simpbook_pwa_url($page_slug, $additional_params = array()) {
    $params = array_merge(array('page' => $page_slug, 'pwa' => '1'), $additional_params);
    return add_query_arg($params, admin_url('admin.php'));
}

/**
 * Gibt eine Form-Action URL zurück, die den PWA-Modus beibehält
 * 
 * @param string $page_slug Optional: spezifischer Page-Slug
 * @param array $additional_params Zusätzliche Query-Parameter
 * @return string Form Action URL
 */
function simpbook_get_form_action($page_slug = '', $additional_params = array()) {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    $is_pwa = isset($_GET['pwa']) && $_GET['pwa'] === '1';
    
    if (!$is_pwa) {
        return ''; // Standard-Verhalten: leere Action = aktuelle URL
    }
    
    // Aktuelle Seite verwenden wenn nicht angegeben
    if (empty($page_slug)) {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $page_slug = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
    }
    
    $params = array_merge(
        array('page' => $page_slug, 'pwa' => '1'),
        $additional_params
    );
    
    // Bestehende Parameter wie 'id' beibehalten
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    if (isset($_GET['id'])) {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $params['id'] = intval($_GET['id']);
    }
    
    return add_query_arg($params, admin_url('admin.php'));
}

/**
 * Fügt PWA-Parameter zu einer URL hinzu falls im PWA-Modus
 * 
 * @param string $url Die URL
 * @return string URL mit optionalem PWA-Parameter
 */
function simpbook_maybe_add_pwa_param($url) {
    if (simpbook_is_pwa_mode()) {
        return add_query_arg('pwa', '1', $url);
    }
    return $url;
}

/**
 * Führt einen Redirect durch, der den PWA-Modus beibehält
 * 
 * @param string $url Ziel-URL
 * @param bool $exit Ob exit() aufgerufen werden soll
 */
function simpbook_pwa_redirect($url, $exit = true) {
    $url = simpbook_maybe_add_pwa_param($url);
    wp_safe_redirect($url);
    if ($exit) {
        exit;
    }
}

/**
 * Holt aktuelle Page aus URL
 * 
 * @return string Page-Slug oder leerer String
 */
function simpbook_get_current_page() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Simple GET check for page identification
    return isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
}

/**
 * Prüft ob Zurück-Button angezeigt werden soll
 * Nicht auf Hauptseiten (Dashboard, Kalender, Reservierungen, Settings)
 * 
 * @return bool True wenn Zurück-Button angezeigt werden soll
 */
function simpbook_show_back_button() {
    $current_page = simpbook_get_current_page();
    $main_pages = array(
        'simpbook-dashboard',
        'simpbook-kalender', 
        'simpbook-reservierungen',
        'simpbook-reservierungen-einstellungen'
    );
    return !in_array($current_page, $main_pages, true);
}

/**
 * Holt den Seitentitel für die PWA-Navigation
 * 
 * @return string Lokalisierter Seitentitel
 */
function simpbook_get_pwa_page_title() {
    $current_page = simpbook_get_current_page();
    
    $page_titles = array(
        'simpbook-dashboard' => __('Dashboard', 'simple-appointment-booking'),
        'simpbook-kalender' => __('Calendar', 'simple-appointment-booking'),
        'simpbook-reservierungen' => __('Bookings', 'simple-appointment-booking'),
        'simpbook-reservierungen-neu' => __('New Booking', 'simple-appointment-booking'),
        'simpbook-dienstleistungen' => __('Services', 'simple-appointment-booking'),
        'simpbook-mitarbeiter' => __('Staff', 'simple-appointment-booking'),
        'simpbook-statistiken' => __('Statistics', 'simple-appointment-booking'),
        'simpbook-reservierungen-einstellungen' => __('Settings', 'simple-appointment-booking'),
        'simpbook-app-einstellungen' => __('App', 'simple-appointment-booking'),
    );
    
    // Prüfe auf Bearbeitungsseiten
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Simple GET check for page identification
    $action = isset($_GET['simpbook_aktion']) ? sanitize_text_field(wp_unslash($_GET['simpbook_aktion'])) : '';
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Simple GET check for page identification
    $id = isset($_GET['simpbook_id']) ? intval($_GET['simpbook_id']) : 0;
    
    if ($current_page === 'simpbook-dienstleistungen' && ($action === 'bearbeiten' || $id > 0)) {
        return $id > 0 ? __('Edit Service', 'simple-appointment-booking') : __('Neue Dienstleistung', 'simple-appointment-booking');
    }
    
    if ($current_page === 'simpbook-mitarbeiter' && ($action === 'bearbeiten' || $id > 0)) {
        return $id > 0 ? __('Edit Staff Member', 'simple-appointment-booking') : __('Neuer Mitarbeiter', 'simple-appointment-booking');
    }
    
    if ($current_page === 'simpbook-reservierungen' && $id > 0) {
        return __('Edit Booking', 'simple-appointment-booking');
    }
    
    return isset($page_titles[$current_page]) ? $page_titles[$current_page] : 'PocketBooking';
}

/**
 * Holt den aktuellen Mitarbeiter für den eingeloggten WP-User
 * 
 * @return object|null Mitarbeiter-Objekt oder null
 */
function simpbook_get_current_mitarbeiter() {
    if (!is_user_logged_in()) {
        return null;
    }
    return simpbook_get_mitarbeiter_for_wp_user(get_current_user_id());
}

/**
 * Holt WP-User für einen Mitarbeiter
 * 
 * @param int $mitarbeiter_id Mitarbeiter-ID
 * @return WP_User|null WP_User-Objekt oder null
 */
function simpbook_get_wp_user_for_mitarbeiter($mitarbeiter_id) {
    global $wpdb;
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
    $wp_user_id = $wpdb->get_var($wpdb->prepare(
        "SELECT wp_user_id FROM {$wpdb->prefix}mitarbeiter WHERE id = %d",
        $mitarbeiter_id
    ));
    return $wp_user_id ? get_user_by('ID', $wp_user_id) : null;
}

/**
 * Holt Mitarbeiter für einen WP-User
 * 
 * @param int $user_id WordPress User-ID
 * @return object|null Mitarbeiter-Objekt oder null
 */
function simpbook_get_mitarbeiter_for_wp_user($user_id) {
    global $wpdb;
    
    // Erst User-Meta prüfen
    $mitarbeiter_id = get_user_meta($user_id, 'simpbook_mitarbeiter_id', true);
    
    if (!$mitarbeiter_id) {
        // Fallback: Suche in Mitarbeiter-Tabelle
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
        $mitarbeiter_id = $wpdb->get_var($wpdb->prepare(
            "SELECT id FROM {$wpdb->prefix}mitarbeiter WHERE wp_user_id = %d",
            $user_id
        ));
    }
    
    if (!$mitarbeiter_id) {
        return null;
    }
    
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Booking system requires direct DB access for real-time data
    return $wpdb->get_row($wpdb->prepare(
        "SELECT * FROM {$wpdb->prefix}mitarbeiter WHERE id = %d",
        $mitarbeiter_id
    ));
}

/**
 * Prüft ob User Zugriff auf PWA hat
 * 
 * @return bool True wenn Zugriff erlaubt
 */
function simpbook_can_access_pwa() {
    if (!is_user_logged_in()) {
        return false;
    }
    
    // Admins haben immer Zugriff
    if (current_user_can('manage_options')) {
        return true;
    }
    
    // Booking Manager Role
    if (current_user_can('manage_booking_app')) {
        return true;
    }
    
    return false;
}

/**
 * Generiert PWA API-Token für einen User
 * 
 * @param int $user_id WordPress User-ID
 * @return string API-Token
 */
function simpbook_generate_pwa_token($user_id) {
    $token = wp_hash($user_id . time() . wp_salt('auth'));
    update_user_meta($user_id, 'simpbook_pwa_api_token', $token);
    update_user_meta($user_id, 'simpbook_pwa_token_expiry', time() + (7 * DAY_IN_SECONDS));
    return $token;
}

/**
 * Validiert PWA API-Token
 * 
 * @param string $token API-Token
 * @param int $user_id WordPress User-ID
 * @return bool True wenn Token gültig
 */
function simpbook_validate_pwa_token($token, $user_id) {
    $stored_token = get_user_meta($user_id, 'simpbook_pwa_api_token', true);
    $expiry = get_user_meta($user_id, 'simpbook_pwa_token_expiry', true);
    
    if ($token !== $stored_token || time() > intval($expiry)) {
        return false;
    }
    
    return true;
}

/**
 * Löscht PWA API-Token für einen User
 * 
 * @param int $user_id WordPress User-ID
 */
function simpbook_clear_pwa_token($user_id) {
    delete_user_meta($user_id, 'simpbook_pwa_api_token');
    delete_user_meta($user_id, 'simpbook_pwa_token_expiry');
}

/**
 * AJAX Handler: Session-Check für PWA
 */
function simpbook_ajax_check_pwa_session() {
    if (is_user_logged_in() && simpbook_can_access_pwa()) {
        wp_send_json_success(array('logged_in' => true));
    } else {
        wp_send_json_error(array('logged_in' => false), 401);
    }
}
add_action('wp_ajax_simpbook_check_pwa_session', 'simpbook_ajax_check_pwa_session');
add_action('wp_ajax_nopriv_simpbook_check_pwa_session', 'simpbook_ajax_check_pwa_session');

/**
 * AJAX Handler: PWA Logout
 */
function simpbook_ajax_pwa_logout() {
    if (is_user_logged_in()) {
        simpbook_clear_pwa_token(get_current_user_id());
        wp_logout();
    }
    wp_send_json_success(array('logged_out' => true));
}
add_action('wp_ajax_simpbook_pwa_logout', 'simpbook_ajax_pwa_logout');

/**
 * AJAX Handler: Setup-Wizard-Hinweis verwerfen
 */
function simpbook_ajax_dismiss_wizard_notice() {
    check_ajax_referer('simpbook_dismiss_wizard', 'nonce');
    
    if (!current_user_can('manage_options')) {
        wp_send_json_error(array('message' => 'Keine Berechtigung'));
    }
    
    update_option('simpbook_wizard_notice_dismissed', true);
    wp_send_json_success();
}
add_action('wp_ajax_simpbook_dismiss_wizard_notice', 'simpbook_ajax_dismiss_wizard_notice');


// === DIENSTLEISTUNGS-KATEGORIEN FUNKTIONEN ===

/**
 * Holt alle Dienstleistungs-Kategorien
 * 
 * @param string $orderby Sortierfeld (default: 'sortierung')
 * @param string $order Sortierrichtung (default: 'ASC')
 * @return array Array von Kategorie-Objekten
 */
function simpbook_get_all_kategorien($orderby = 'sortierung', $order = 'ASC') {
    global $wpdb;
    $table = $wpdb->prefix . 'simpbook_dienstleistung_kategorien';
    
    // Whitelist für Sortierfelder
    $allowed_orderby = array('id', 'name', 'sortierung', 'erstellungsdatum');
    if (!in_array($orderby, $allowed_orderby)) {
        $orderby = 'sortierung';
    }
    
    $order = strtoupper($order) === 'DESC' ? 'DESC' : 'ASC';
    
    $sql = "SELECT * FROM {$table} ORDER BY {$orderby} {$order}";
    // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    return $wpdb->get_results($sql);
}

/**
 * Holt eine einzelne Kategorie nach ID
 * 
 * @param int $id Kategorie-ID
 * @return object|null Kategorie-Objekt oder null
 */
function simpbook_get_kategorie($id) {
    global $wpdb;
    $table = $wpdb->prefix . 'simpbook_dienstleistung_kategorien';
    
    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
    $result = $wpdb->get_row($wpdb->prepare(
        "SELECT * FROM {$table} WHERE id = %d",
        intval($id)
    ));
    // phpcs:enable
    
    return $result;
}

/**
 * Holt alle Dienstleistungen einer bestimmten Kategorie
 * 
 * @param int $kategorie_id Kategorie-ID
 * @return array Array von Dienstleistungs-Objekten
 */
function simpbook_get_dienstleistungen_by_kategorie($kategorie_id) {
    global $wpdb;
    $table = $wpdb->prefix . 'dienstleistungen';
    
    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
    $results = $wpdb->get_results($wpdb->prepare(
        "SELECT * FROM {$table} WHERE kategorie_id = %d ORDER BY name ASC",
        intval($kategorie_id)
    ));
    // phpcs:enable
    
    return $results;
}

/**
 * Holt alle Dienstleistungen ohne Kategorie
 * 
 * @return array Array von Dienstleistungs-Objekten
 */
function simpbook_get_dienstleistungen_ohne_kategorie() {
    global $wpdb;
    $table = $wpdb->prefix . 'dienstleistungen';
    
    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
    $results = $wpdb->get_results(
        "SELECT * FROM {$table} WHERE kategorie_id IS NULL OR kategorie_id = 0 ORDER BY name ASC"
    );
    // phpcs:enable
    
    return $results;
}

/**
 * Prüft ob kategorisierte Dienstleistungen existieren
 * 
 * @return bool True wenn mindestens eine Dienstleistung einer Kategorie zugeordnet ist
 */
function simpbook_has_kategorisierte_dienstleistungen() {
    global $wpdb;
    $table = $wpdb->prefix . 'dienstleistungen';
    
    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
    $count = $wpdb->get_var(
        "SELECT COUNT(*) FROM {$table} WHERE kategorie_id IS NOT NULL AND kategorie_id > 0"
    );
    // phpcs:enable
    
    return intval($count) > 0;
}

/**
 * Speichert eine Kategorie (Neu oder Update)
 * 
 * @param array $data Kategorie-Daten (name, beschreibung, sortierung)
 * @param int|null $id Kategorie-ID für Update, null für neue Kategorie
 * @return int|false Eingefügte/aktualisierte ID oder false bei Fehler
 */
function simpbook_save_kategorie($data, $id = null) {
    global $wpdb;
    $table = $wpdb->prefix . 'simpbook_dienstleistung_kategorien';
    
    $insert_data = array(
        'name' => sanitize_text_field($data['name']),
        'beschreibung' => isset($data['beschreibung']) ? sanitize_textarea_field($data['beschreibung']) : '',
        'sortierung' => isset($data['sortierung']) ? intval($data['sortierung']) : 0,
        'farbe' => isset($data['farbe']) ? sanitize_hex_color($data['farbe']) : '#2271b1'
    );
    
    if ($id !== null && $id > 0) {
        // Update
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $result = $wpdb->update(
            $table,
            $insert_data,
            array('id' => intval($id)),
            array('%s', '%s', '%d', '%s'),
            array('%d')
        );
        return $result !== false ? $id : false;
    } else {
        // Insert
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $result = $wpdb->insert(
            $table,
            $insert_data,
            array('%s', '%s', '%d', '%s')
        );
        return $result ? $wpdb->insert_id : false;
    }
}

/**
 * Löscht eine Kategorie
 * 
 * @param int $id Kategorie-ID
 * @param bool $reset_dienstleistungen Setzt kategorie_id der zugehörigen Dienstleistungen auf NULL
 * @return bool True bei Erfolg
 */
function simpbook_delete_kategorie($id, $reset_dienstleistungen = true) {
    global $wpdb;
    $kategorien_table = $wpdb->prefix . 'simpbook_dienstleistung_kategorien';
    $dienstleistungen_table = $wpdb->prefix . 'dienstleistungen';
    
    if ($reset_dienstleistungen) {
        // Setze kategorie_id auf NULL für alle Dienstleistungen dieser Kategorie
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->update(
            $dienstleistungen_table,
            array('kategorie_id' => null),
            array('kategorie_id' => intval($id)),
            array('%d'),
            array('%d')
        );
    }
    
    // Lösche die Kategorie
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $result = $wpdb->delete(
        $kategorien_table,
        array('id' => intval($id)),
        array('%d')
    );
    
    return $result !== false;
}

/**
 * Zählt Dienstleistungen pro Kategorie
 * 
 * @param int $kategorie_id Kategorie-ID
 * @return int Anzahl der Dienstleistungen
 */
function simpbook_count_dienstleistungen_in_kategorie($kategorie_id) {
    global $wpdb;
    $table = $wpdb->prefix . 'dienstleistungen';
    
    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
    $count = $wpdb->get_var($wpdb->prepare(
        "SELECT COUNT(*) FROM {$table} WHERE kategorie_id = %d",
        intval($kategorie_id)
    ));
    // phpcs:enable
    
    return intval($count);
}

/**
 * Holt alle Dienstleistungen gruppiert nach Kategorie
 * 
 * @return array Assoziatives Array mit Kategorien und ihren Dienstleistungen
 */
function simpbook_get_dienstleistungen_grouped() {
    $kategorien = simpbook_get_all_kategorien();
    $result = array();
    
    // Kategorisierte Dienstleistungen
    foreach ($kategorien as $kategorie) {
        $dienstleistungen = simpbook_get_dienstleistungen_by_kategorie($kategorie->id);
        if (!empty($dienstleistungen)) {
            $result[] = array(
                'kategorie' => $kategorie,
                'dienstleistungen' => $dienstleistungen
            );
        }
    }
    
    // Nicht kategorisierte Dienstleistungen
    $ohne_kategorie = simpbook_get_dienstleistungen_ohne_kategorie();
    if (!empty($ohne_kategorie)) {
        $result[] = array(
            'kategorie' => null,
            'dienstleistungen' => $ohne_kategorie
        );
    }
    
    return $result;
}

/**
 * Aktualisiert die Kategorie einer Dienstleistung
 * 
 * @param int $dienstleistung_id Dienstleistungs-ID
 * @param int|null $kategorie_id Kategorie-ID oder null zum Entfernen
 * @return bool True bei Erfolg
 */
function simpbook_update_dienstleistung_kategorie($dienstleistung_id, $kategorie_id) {
    global $wpdb;
    $table = $wpdb->prefix . 'dienstleistungen';
    
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $result = $wpdb->update(
        $table,
        array('kategorie_id' => $kategorie_id === null ? null : intval($kategorie_id)),
        array('id' => intval($dienstleistung_id)),
        array('%d'),
        array('%d')
    );
    
    return $result !== false;
}

/**
 * Verfügbare Mitarbeiter für eine Buchung ermitteln
 * 
 * @param int $dienstleistung_id ID der Dienstleistung
 * @param string $datum Datum im Format YYYY-MM-DD oder d.m.Y
 * @param string $uhrzeit Uhrzeit im Format HH:MM:SS oder HH:MM
 * @return array Array mit verfügbaren Mitarbeitern (id, name)
 */
function simpbook_get_verfuegbare_mitarbeiter_fuer_buchung($dienstleistung_id, $datum, $uhrzeit) {
    if ($dienstleistung_id < 1) {
        return [];
    }

    // Mitarbeiter für diese Dienstleistung laden
    $mitarbeiter = simpbook_get_mitarbeiter_fuer_dienstleistung($dienstleistung_id, true, false);
    
    if (empty($mitarbeiter)) {
        return [];
    }

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

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

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

    if ($datum_obj === false) {
        return [];
    }

    // 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';

    // Uhrzeit parsen (Format HH:MM oder HH:MM:SS)
    $uhrzeit_parts = explode(':', $uhrzeit);
    $stunden = isset($uhrzeit_parts[0]) ? intval($uhrzeit_parts[0]) : 0;
    $minuten = isset($uhrzeit_parts[1]) ? intval($uhrzeit_parts[1]) : 0;
    $buchungs_zeit_minuten = $stunden * 60 + $minuten;

    // Gefilterte Mitarbeiter
    $verfuegbare_mitarbeiter = [];

    foreach ($mitarbeiter as $m) {
        $ist_verfuegbar = false;
        
        // 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') {
                // Prüfe ob die Buchungszeit innerhalb der Arbeitszeiten liegt
                $von = $arbeitszeiten[$wochentag_key]['beginn'] ?? $arbeitszeiten[$wochentag_key]['of'] ?? '';
                $bis = $arbeitszeiten[$wochentag_key]['ende'] ?? $arbeitszeiten[$wochentag_key]['bis'] ?? '';
                
                if (!empty($von) && !empty($bis)) {
                    list($von_h, $von_m) = explode(':', $von);
                    list($bis_h, $bis_m) = explode(':', $bis);
                    $von_minuten = intval($von_h) * 60 + intval($von_m);
                    $bis_minuten = intval($bis_h) * 60 + intval($bis_m);
                    
                    if ($buchungs_zeit_minuten >= $von_minuten && $buchungs_zeit_minuten < $bis_minuten) {
                        $ist_verfuegbar = true;
                    }
                }
            }
        } 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') {
                // Prüfe globale Öffnungszeiten
                $von = $wochentag_zeiten_cfg[$wochentag_key]['beginn'] ?? $wochentag_zeiten_cfg[$wochentag_key]['of'] ?? '';
                $bis = $wochentag_zeiten_cfg[$wochentag_key]['ende'] ?? $wochentag_zeiten_cfg[$wochentag_key]['bis'] ?? '';
                
                if (!empty($von) && !empty($bis)) {
                    list($von_h, $von_m) = explode(':', $von);
                    list($bis_h, $bis_m) = explode(':', $bis);
                    $von_minuten = intval($von_h) * 60 + intval($von_m);
                    $bis_minuten = intval($bis_h) * 60 + intval($bis_m);
                    
                    if ($buchungs_zeit_minuten >= $von_minuten && $buchungs_zeit_minuten < $bis_minuten) {
                        $ist_verfuegbar = true;
                    }
                }
            }
        }
        
        if ($ist_verfuegbar) {
            $verfuegbare_mitarbeiter[] = [
                'id' => intval($m->id),
                'name' => $m->name
            ];
        }
    }

    return $verfuegbare_mitarbeiter;
}

/**
 * Builds a full HTML email wrapper for admin notification emails.
 * Uses the plugin's design colors (container_background, text_color) for the header.
 *
 * @param string $subject      The email subject (shown in sub-header).
 * @param string $html_content Already-built HTML content for the email body.
 * @param string $company_name The company/business name.
 * @return string Full HTML email string.
 */
function simpbook_build_admin_html_email( string $subject, string $html_content, string $company_name ): string {
    $header_color      = get_option( 'simpbook_container_background', '#8bbce4' );
    $header_text_color = get_option( 'simpbook_text_color', '#000000' );
    $sub_color         = '#f0f7ff';
    $logo_url          = get_option( 'simpbook_email_header_logo', '' );

    if ( $logo_url ) {
        $header_content = '<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr>'
            . '<td style="width:70%;vertical-align:middle;padding-right:16px;">'
            . '<h1 style="margin:0;font-size:20px;font-weight:700;color:' . esc_attr( $header_text_color ) . ';line-height:1.3;">' . esc_html( $company_name ) . '</h1>'
            . '</td>'
            . '<td style="width:30%;vertical-align:middle;text-align:right;">'
            . '<img src="' . esc_url( $logo_url ) . '" alt="' . esc_attr( $company_name ) . '" style="max-height:60px;max-width:100%;display:inline-block;">'
            . '</td></tr></table>';
    } else {
        $header_content = '<h1 style="margin:0;font-size:20px;font-weight:700;color:' . esc_attr( $header_text_color ) . ';">' . esc_html( $company_name ) . '</h1>';
    }

    $html  = '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"></head>';
    $html .= '<body style="margin:0;padding:0;background:#f4f4f4;font-family:Arial,sans-serif;">';
    $html .= '<table width="100%" cellpadding="0" cellspacing="0" border="0" style="background:#f4f4f4;padding:30px 0;"><tr><td align="center">';
    $html .= '<table width="600" cellpadding="0" cellspacing="0" border="0" style="max-width:600px;width:100%;background:#ffffff;border-radius:8px;overflow:hidden;box-shadow:0 2px 8px rgba(0,0,0,0.1);">';
    $html .= '<tr><td style="background:' . esc_attr( $header_color ) . ';padding:28px 32px;">' . $header_content . '</td></tr>';
    $html .= '<tr><td style="background:' . esc_attr( $sub_color ) . ';padding:12px 32px;">';
    $html .= '<p style="margin:0;font-size:14px;font-weight:600;color:#1f2937;">' . esc_html( $subject ) . '</p></td></tr>';
    $html .= '<tr><td style="padding:32px;color:#374151;font-size:15px;line-height:1.6;">' . $html_content . '</td></tr>';
    $html .= '<tr><td style="background:#f9fafb;padding:20px 32px;border-top:1px solid #e5e7eb;">';
    $html .= '<p style="margin:0;font-size:12px;color:#9ca3af;text-align:center;">' . esc_html( $company_name ) . '</p></td></tr>';
    $html .= '</table></td></tr></table></body></html>';

    return $html;
}

/**
 * Builds an HTML-wrapped guest email with a color scheme based on email type.
 *
 * @param string $subject    The email subject (shown in sub-header).
 * @param string $plain_text The plain-text message body.
 * @param string $company_name The company/business name.
 * @param string $option_key  The email template option key used to derive the color scheme.
 * @return string Full HTML email string.
 */
function simpbook_build_guest_html_email( string $subject, string $plain_text, string $company_name, string $option_key ): string {
    // --- Color scheme ---
    // Check 'bestaetigungs' BEFORE 'bestaetigt' (it contains 'bestaetigt' as substring)
    if ( strpos( $option_key, 'bestaetigungs' ) !== false ) {
        // Booking request — use the plugin's design settings colors
        $header_color      = get_option( 'simpbook_container_background', '#8bbce4' );
        $header_text_color = get_option( 'simpbook_text_color', '#000000' );
        $sub_color         = '#f0f7ff';
    } elseif ( strpos( $option_key, 'bestaetigt' ) !== false ) {
        $header_color      = '#059669';
        $header_text_color = '#ffffff';
        $sub_color         = '#a7f3d0';
    } elseif ( strpos( $option_key, 'abgelehnt' ) !== false || strpos( $option_key, 'absage' ) !== false ) {
        $header_color      = '#dc2626';
        $header_text_color = '#ffffff';
        $sub_color         = '#fecaca';
    } elseif ( strpos( $option_key, 'storniert' ) !== false ) {
        $header_color      = '#d97706';
        $header_text_color = '#ffffff';
        $sub_color         = '#fde68a';
    } else {
        $header_color      = '#1a4a8a';
        $header_text_color = '#ffffff';
        $sub_color         = '#c7d2fe';
    }

    // --- Logo ---
    $logo_url = get_option( 'simpbook_email_header_logo', '' );

    // --- Convert plain text to HTML paragraphs ---
    $body_html = '';
    $lines     = explode( "\n", $plain_text );
    $paragraph = '';
    foreach ( $lines as $line ) {
        $line = trim( $line );
        if ( $line === '' ) {
            if ( $paragraph !== '' ) {
                $body_html .= '<p style="margin:0 0 12px 0;">' . $paragraph . '</p>' . "\n";
                $paragraph  = '';
            }
        } else {
            $linked    = preg_replace(
                '#(https?://[^\s<>"]+)#',
                '<a href="$1" style="color:' . esc_attr( $header_color ) . ';">$1</a>',
                esc_html( $line )
            );
            $paragraph .= ( $paragraph !== '' ? '<br>' : '' ) . $linked;
        }
    }
    if ( $paragraph !== '' ) {
        $body_html .= '<p style="margin:0 0 12px 0;">' . $paragraph . '</p>' . "\n";
    }

    // --- Header content (two-column with logo, or single column) ---
    if ( $logo_url ) {
        $header_content = '<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr>'
            . '<td style="width:70%;vertical-align:middle;padding-right:16px;">'
            . '<h1 style="margin:0;font-size:20px;font-weight:700;color:' . esc_attr( $header_text_color ) . ';line-height:1.3;">' . esc_html( $company_name ) . '</h1>'
            . '</td>'
            . '<td style="width:30%;vertical-align:middle;text-align:right;">'
            . '<img src="' . esc_url( $logo_url ) . '" alt="' . esc_attr( $company_name ) . '" style="max-height:60px;max-width:100%;display:inline-block;">'
            . '</td></tr></table>';
    } else {
        $header_content = '<h1 style="margin:0;font-size:20px;font-weight:700;color:' . esc_attr( $header_text_color ) . ';">' . esc_html( $company_name ) . '</h1>';
    }

    // --- Assemble HTML ---
    $html  = '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"></head>';
    $html .= '<body style="margin:0;padding:0;background:#f4f4f4;font-family:Arial,sans-serif;">';
    $html .= '<table width="100%" cellpadding="0" cellspacing="0" border="0" style="background:#f4f4f4;padding:30px 0;"><tr><td align="center">';
    $html .= '<table width="600" cellpadding="0" cellspacing="0" border="0" style="max-width:600px;width:100%;background:#ffffff;border-radius:8px;overflow:hidden;box-shadow:0 2px 8px rgba(0,0,0,0.1);">';
    // Header
    $html .= '<tr><td style="background:' . esc_attr( $header_color ) . ';padding:28px 32px;">' . $header_content . '</td></tr>';
    // Sub-header (subject)
    $html .= '<tr><td style="background:' . esc_attr( $sub_color ) . ';padding:12px 32px;">';
    $html .= '<p style="margin:0;font-size:14px;font-weight:600;color:#1f2937;">' . esc_html( $subject ) . '</p></td></tr>';
    // Body
    $html .= '<tr><td style="padding:32px;color:#374151;font-size:15px;line-height:1.6;">' . $body_html . '</td></tr>';
    // Footer
    $html .= '<tr><td style="background:#f9fafb;padding:20px 32px;border-top:1px solid #e5e7eb;">';
    $html .= '<p style="margin:0;font-size:12px;color:#9ca3af;text-align:center;">' . esc_html( $company_name ) . '</p></td></tr>';
    $html .= '</table></td></tr></table></body></html>';

    return $html;
}
