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

class WAE_Admin {
    private static $progress_steps = array(
        1 => 35,
        2 => 75,
        3 => 100,
    );

    private static $tri_fields = array(
        'free_ceremony_possible','registry_office_on_site','church_ceremony_possible','outdoor_possible','indoor_possible','air_conditioned','rain_backup','barrier_free',
        'playground','childcare_room','changing_room','kids_welcome','dogs_allowed','hotel_available','camper_parking','shuttle_service','regional_catering','green_power','sustainable_concept',
        'wifi','stage','dancefloor','charging_stations','free_service_providers','midnight_snack','fireworks','fixed_catering_partners'
    );

    public static function init() {
        add_action('admin_menu', array(__CLASS__, 'admin_menu'));
        add_action('admin_init', array(__CLASS__, 'register_settings'));
        add_action('admin_post_wae_generate_test_page', array(__CLASS__, 'handle_generate_test_page'));
        add_action('admin_post_wae_step0_save_and_scan', array(__CLASS__, 'handle_step0_save_and_scan'));
        add_action('admin_post_wae_step1_save', array(__CLASS__, 'handle_step1_save'));
        add_action('admin_post_wae_step2_save_send', array(__CLASS__, 'handle_step2_save_send'));
        add_action('admin_post_wae_step3_save_create', array(__CLASS__, 'handle_step3_save_create'));
        add_action('admin_post_wae_enable_sitemap', array(__CLASS__, 'handle_enable_sitemap'));
        add_action('admin_post_wae_sync_partner', array(__CLASS__, 'handle_sync_partner'));
        add_action('wp_ajax_wae_geocode_address', array(__CLASS__, 'ajax_geocode_address'));
        add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_admin_assets'));
    }

    public static function enqueue_admin_assets($hook) {
        if (strpos((string)$hook, 'wae-') === false && strpos((string)$hook, 'wedding-ai-engine') === false) { return; }
        wp_enqueue_media();
        wp_enqueue_script('wae-admin', WAE_PLUGIN_URL . 'assets/admin.js', array('jquery'), WAE_VERSION, true);
        wp_localize_script('wae-admin', 'WAE_ADMIN', array('ajaxUrl' => admin_url('admin-ajax.php'), 'geocodeNonce' => wp_create_nonce('wae_geocode_address')));
        wp_enqueue_style('wae-admin', WAE_PLUGIN_URL . 'assets/admin.css', array(), WAE_VERSION);
    }

    public static function admin_menu() {
        add_menu_page('Wedding AI Engine', 'Wedding AI Engine', 'manage_options', 'wae-dashboard', array(__CLASS__, 'render_dashboard'), 'dashicons-admin-site-alt3', 58);
        add_submenu_page('wae-dashboard', 'Übersicht', 'Übersicht', 'manage_options', 'wae-dashboard', array(__CLASS__, 'render_dashboard'));
        add_submenu_page('wae-dashboard', 'Schritt 0: KI- & Sichtbarkeitscheck', '0. KI-Check', 'manage_options', 'wae-visibility-check', array(__CLASS__, 'render_visibility_check'));
        add_submenu_page('wae-dashboard', 'Schritt 1: Eventlocation', '1. Eventlocation', 'manage_options', 'wae-location', array(__CLASS__, 'render_location'));
        add_submenu_page('wae-dashboard', 'Schritt 2: Eventlocation-Profil', '2. Eventlocation-Profil', 'manage_options', 'wae-network', array(__CLASS__, 'render_network'));
        add_submenu_page('wae-dashboard', 'Schritt 3: Trauredner-Service', '3. Trauredner-Service', 'manage_options', 'wae-landingpage', array(__CLASS__, 'render_landingpage'));
    }

    public static function register_settings() {
        register_setting('wae_options_group', 'wae_options', array(__CLASS__, 'sanitize_options'));
    }

    public static function sanitize_options($input) {
        $old = get_option('wae_options', array());
        $out = is_array($old) ? $old : array();
        $fields_text = array(
            'mode','location_name','street','zip','city','country','phone','email','website','wedding_page_url','contact_name','contact_role',
            'instagram','facebook','pinterest','youtube','tiktok','linkedin','xing','whatsapp','visitor_tone','matching_shape','primary_color','button_color','button_text_color','capacity_note','price_note','parking_count','hotel_rooms','sustainability_note','family_note','comfort_note','latitude','longitude','core_api_base','update_channel'
        );
        foreach ($fields_text as $field) {
            if (isset($input[$field])) {
                $out[$field] = sanitize_text_field(wp_unslash($input[$field]));
            }
        }
        foreach (array('instagram','facebook','pinterest','youtube','tiktok','linkedin','xing') as $social_field) {
            if (isset($input[$social_field])) {
                $out[$social_field] = esc_url_raw(wp_unslash($input[$social_field]));
            }
        }
        if (isset($input['visitor_tone'])) {
            $tone = sanitize_key(wp_unslash($input['visitor_tone']));
            $out['visitor_tone'] = in_array($tone, array('du','sie'), true) ? $tone : 'du';
        }
        if (isset($input['matching_shape'])) {
            $shape = sanitize_key(wp_unslash($input['matching_shape']));
            $out['matching_shape'] = in_array($shape, array('rounded','square'), true) ? $shape : 'rounded';
        }
        foreach (self::$tri_fields as $field) {
            if (isset($input[$field])) {
                $out[$field] = self::sanitize_tri_state($input[$field]);
            }
        }
        $fields_bool = array('landingpage_enabled','network_directory_optin','network_contact_optin','market_report_optin','plugin_stats_optin','network_early_access_optin','auto_updates_enabled','sandbox_mode','simple_sitemap_enabled');
        foreach ($fields_bool as $field) {
            /*
             * Wichtig: Die Einstellungsseiten speichern jeweils nur ihren eigenen Formularbereich.
             * Checkboxen dürfen deshalb nur dann auf 0 gesetzt werden, wenn sie im aktuellen Formular
             * tatsächlich vorkommen. Andernfalls würden andere Schritte beim Speichern versehentlich
             * zurückgesetzt.
             */
            if (array_key_exists($field, $input)) {
                $out[$field] = !empty($input[$field]) ? '1' : '0';
            }
        }
        if (isset($input['wedding_page_id'])) {
            $out['wedding_page_id'] = absint($input['wedding_page_id']);
        }
        foreach (array('contact_page_id','gallery_page_id','prices_page_id','overnight_page_id','directions_page_id','terms_page_id','privacy_page_id','imprint_page_id') as $page_field) {
            if (isset($input[$page_field])) {
                $out[$page_field] = absint($input[$page_field]);
            }
        }
        if (isset($input['opening_hours']) && is_array($input['opening_hours'])) {
            $out['opening_hours'] = array();
            foreach ($input['opening_hours'] as $day => $row) {
                if (!is_array($row)) { continue; }
                $day_key = sanitize_key($day);
                $out['opening_hours'][$day_key] = array(
                    'open' => !empty($row['open']) ? '1' : '0',
                    'from' => isset($row['from']) ? sanitize_text_field(wp_unslash($row['from'])) : '',
                    'to' => isset($row['to']) ? sanitize_text_field(wp_unslash($row['to'])) : '',
                );
            }
        }
        foreach (array('appointments_only','viewings_by_appointment','evening_appointments') as $field) {
            if (array_key_exists($field, $input)) {
                $out[$field] = !empty($input[$field]) ? '1' : '0';
            }
        }
        /*
         * Räume/Bereiche nur aktualisieren, wenn das aktuelle Formular auch Räume sendet.
         * Beim Speichern von Schritt 2 oder Schritt 3 sind keine rooms[]-Felder vorhanden.
         * Die alte Logik hat dann $out['rooms'] = array() gesetzt und damit alle Raumdaten
         * inklusive Bilder gelöscht.
         */
        if (array_key_exists('rooms', $input)) {
            $out['rooms'] = array();
            if (!empty($input['rooms']) && is_array($input['rooms'])) {
                foreach ($input['rooms'] as $room) {
                if (!is_array($room)) { continue; }
                $name = isset($room['name']) ? sanitize_text_field(wp_unslash($room['name'])) : '';
                $has_data = $name !== '' || !empty($room['description']) || !empty($room['capacity_max']) || !empty($room['image_1']) || !empty($room['image_2']);
                if (!$has_data) { continue; }
                $out['rooms'][] = array(
                    'name' => $name,
                    'description' => isset($room['description']) ? sanitize_textarea_field(wp_unslash($room['description'])) : '',
                    'capacity_min' => isset($room['capacity_min']) ? absint($room['capacity_min']) : 0,
                    'capacity_max' => isset($room['capacity_max']) ? absint($room['capacity_max']) : 0,
                    'price_from' => isset($room['price_from']) ? sanitize_text_field(wp_unslash($room['price_from'])) : '',
                    'price_to' => isset($room['price_to']) ? sanitize_text_field(wp_unslash($room['price_to'])) : '',
                    'image_1' => isset($room['image_1']) ? absint($room['image_1']) : 0,
                    'image_2' => isset($room['image_2']) ? absint($room['image_2']) : 0,
                    'free_ceremony' => isset($room['free_ceremony']) ? self::sanitize_tri_state($room['free_ceremony']) : 'unknown',
                    'party' => isset($room['party']) ? self::sanitize_tri_state($room['party']) : 'unknown',
                    'indoor' => isset($room['indoor']) ? self::sanitize_tri_state($room['indoor']) : 'unknown',
                    'outdoor' => isset($room['outdoor']) ? self::sanitize_tri_state($room['outdoor']) : 'unknown',
                    'air_conditioned' => isset($room['air_conditioned']) ? self::sanitize_tri_state($room['air_conditioned']) : 'unknown',
                    'barrier_free' => isset($room['barrier_free']) ? self::sanitize_tri_state($room['barrier_free']) : 'unknown',
                    'rain_backup' => isset($room['rain_backup']) ? self::sanitize_tri_state($room['rain_backup']) : 'unknown',
                );
            }
        }
        }
        return $out;
    }

    private static function sanitize_tri_state($value) {
        $value = sanitize_key(wp_unslash($value));
        return in_array($value, array('yes','no','request','unknown'), true) ? $value : 'unknown';
    }

    public static function get_options() {
        $defaults = array('mode'=>'development','matching_shape'=>'rounded','landingpage_enabled'=>'0','visitor_tone'=>'du','country'=>'Deutschland','rooms'=>array(), 'latitude'=>'', 'longitude'=>'', 'opening_hours'=>array(), 'auto_updates_enabled'=>'0', 'core_api_base'=>'https://rent-a-pastor.com/wp-json/rentapastor/v1', 'partner_uuid'=>'', 'partner_api_key'=>'', 'partner_api_secret'=>'', 'partner_sync_status'=>'', 'partner_last_sync'=>'', 'partner_sync_message'=>'', 'sandbox_mode'=>'1', 'update_channel'=>'stable', 'plugin_instance_id'=>'', 'simple_sitemap_enabled'=>'0');
        foreach (self::$tri_fields as $field) { $defaults[$field] = 'unknown'; }
        return wp_parse_args(get_option('wae_options', array()), $defaults);
    }

    public static function handle_generate_test_page() {
        check_admin_referer('wae_generate_test_page');
        $result = WAE_Page_Generator::generate_test_landingpage();
        $url = admin_url('admin.php?page=wae-landingpage');
        if (is_wp_error($result)) { $url = add_query_arg('wae_error', rawurlencode($result->get_error_message()), $url); }
        else { $url = add_query_arg('wae_generated', (int)$result, $url); }
        wp_safe_redirect($url); exit;
    }



    private static function purge_known_caches($o = array()) {
        $page_id = 0;
        if (is_array($o) && !empty($o['wedding_page_id'])) { $page_id = (int) $o['wedding_page_id']; }
        if ($page_id) {
            clean_post_cache($page_id);
            if (function_exists('wp_cache_post_change')) { @wp_cache_post_change($page_id); }
        }
        if (function_exists('wpfc_clear_all_cache')) { @wpfc_clear_all_cache(true); }
        global $wp_fastest_cache;
        if (is_object($wp_fastest_cache)) {
            if (method_exists($wp_fastest_cache, 'deleteCache')) { @ $wp_fastest_cache->deleteCache(true); }
            if (method_exists($wp_fastest_cache, 'deleteAllCache')) { @ $wp_fastest_cache->deleteAllCache(true); }
        }
        if (function_exists('w3tc_flush_all')) { @w3tc_flush_all(); }
        if (function_exists('rocket_clean_domain')) { @rocket_clean_domain(); }
        if (function_exists('wp_cache_clear_cache')) { @wp_cache_clear_cache(); }
        if (defined('LSCWP_V')) { do_action('litespeed_purge_all'); }
        do_action('wae_after_cache_purge', $page_id, $o);
    }

    public static function handle_step0_save_and_scan() {
        if (!current_user_can('manage_options')) { wp_die('Keine Berechtigung.'); }
        check_admin_referer('wae_step0_save_and_scan');
        $posted = isset($_POST['wae_options']) && is_array($_POST['wae_options']) ? wp_unslash($_POST['wae_options']) : array();
        $current = get_option('wae_options', array());
        $merged = is_array($current) ? $current : array();
        foreach (array('wedding_page_id','wedding_page_url','auto_updates_enabled','sandbox_mode') as $key) {
            if (array_key_exists($key, $posted)) { $merged[$key] = $posted[$key]; }
        }
        $clean = self::sanitize_options($merged);
        update_option('wae_options', $clean, false);
        self::purge_known_caches($clean);
        wp_safe_redirect(add_query_arg(array('page'=>'wae-visibility-check','wae_run_check'=>'1','wae_saved'=>'1'), admin_url('admin.php')) . '#wae-step-0-result');
        exit;
    }

    private static function save_posted_options() {
        $posted = isset($_POST['wae_options']) && is_array($_POST['wae_options']) ? wp_unslash($_POST['wae_options']) : array();
        $current = get_option('wae_options', array());
        $merged = is_array($current) ? $current : array();
        foreach ($posted as $key => $value) { $merged[$key] = $value; }
        $clean = self::sanitize_options($merged);
        if ((empty($clean['latitude']) || empty($clean['longitude'])) && (!empty($clean['zip']) || !empty($clean['city']))) {
            $geo = self::lookup_geo($clean['zip'] ?? '', $clean['city'] ?? '');
            if ($geo) {
                $clean['latitude'] = isset($geo['lat']) ? (string)$geo['lat'] : ($clean['latitude'] ?? '');
                $clean['longitude'] = isset($geo['lng']) ? (string)$geo['lng'] : ($clean['longitude'] ?? '');
                $clean['geo_lookup_note'] = 'Automatisch aus lokaler Rent-a-Pastor-Ortsdatenbank übernommen.';
            }
        }
        update_option('wae_options', $clean, false);
        self::purge_known_caches($clean);
        return $clean;
    }

    public static function handle_step1_save() {
        if (!current_user_can('manage_options')) { wp_die('Keine Berechtigung.'); }
        check_admin_referer('wae_step1_save');
        self::save_posted_options();
        wp_safe_redirect(add_query_arg(array('page'=>'wae-location','wae_saved'=>'1'), admin_url('admin.php')) . '#wae-step-1-saved');
        exit;
    }

    public static function handle_step2_save_send() {
        if (!current_user_can('manage_options')) { wp_die('Keine Berechtigung.'); }
        check_admin_referer('wae_step2_save_send');
        $o = self::save_posted_options();
        self::sync_partner_data($o);
        wp_safe_redirect(add_query_arg(array('page'=>'wae-network','wae_synced'=>'1'), admin_url('admin.php')) . '#wae-step-2-status');
        exit;
    }

    public static function handle_step3_save_create() {
        if (!current_user_can('manage_options')) { wp_die('Keine Berechtigung.'); }
        check_admin_referer('wae_step3_save_create');
        self::save_posted_options();
        try {
            $result = WAE_Page_Generator::generate_test_landingpage();
        } catch (Throwable $e) {
            $result = new WP_Error('wae_generation_exception', $e->getMessage());
        }
        $url = admin_url('admin.php?page=wae-landingpage');
        if (is_wp_error($result)) {
            $url = add_query_arg('wae_error', rawurlencode($result->get_error_message()), $url);
        } else {
            $url = add_query_arg('wae_generated', (int)$result, $url);
        }
        wp_safe_redirect($url . '#wae-step-3-status');
        exit;
    }

    public static function handle_sync_partner() {
        if (!current_user_can('manage_options')) { wp_die('Keine Berechtigung.'); }
        check_admin_referer('wae_sync_partner');
        self::sync_partner_data(self::get_options());
        wp_safe_redirect(add_query_arg(array('page'=>'wae-network','wae_synced'=>'1'), admin_url('admin.php')) . '#wae-step-2-status');
        exit;
    }

    private static function sync_partner_data($o) {
        $payload = self::build_partner_payload($o);
        $base = !empty($o['core_api_base']) ? untrailingslashit($o['core_api_base']) : 'https://rent-a-pastor.com/wp-json/rentapastor/v1';
        $endpoint = empty($o['partner_api_key']) || empty($o['partner_api_secret']) ? $base . '/partner/register' : $base . '/partner/update';
        $args = array(
            'timeout' => 15,
            'headers' => array('Content-Type'=>'application/json'),
            'body' => wp_json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
        );
        if (!empty($o['partner_api_key']) && !empty($o['partner_api_secret'])) {
            $args['headers']['x-rap-partner-key'] = $o['partner_api_key'];
            $args['headers']['x-rap-partner-secret'] = $o['partner_api_secret'];
        }
        $response = wp_remote_post($endpoint, $args);
        $opts = get_option('wae_options', array());
        if (!is_array($opts)) { $opts = array(); }
        $opts['partner_last_sync'] = current_time('mysql');
        $opts['partner_last_endpoint'] = esc_url_raw($endpoint);
        if (is_wp_error($response)) {
            $opts['partner_sync_status'] = 'error';
            $opts['partner_sync_message'] = $response->get_error_message();
        } else {
            $code = wp_remote_retrieve_response_code($response);
            $body = json_decode((string)wp_remote_retrieve_body($response), true);
            if ($code >= 200 && $code < 300 && is_array($body) && !empty($body['success'])) {
                $opts['partner_sync_status'] = 'success';
                $opts['partner_sync_message'] = isset($body['message']) ? sanitize_text_field($body['message']) : 'Daten wurden übertragen.';
                if (!empty($body['partner_uuid'])) { $opts['partner_uuid'] = sanitize_text_field($body['partner_uuid']); }
                if (!empty($body['api_key'])) { $opts['partner_api_key'] = sanitize_text_field($body['api_key']); }
                if (!empty($body['api_secret'])) { $opts['partner_api_secret'] = sanitize_text_field($body['api_secret']); }
            } else {
                $opts['partner_sync_status'] = 'error';
                $opts['partner_sync_message'] = is_array($body) && !empty($body['message']) ? sanitize_text_field($body['message']) : 'Übertragung fehlgeschlagen. HTTP ' . (int)$code;
            }
        }
        update_option('wae_options', $opts, false);
    }

    private static function build_partner_payload($o) {
        $rooms = self::prepare_rooms_for_payload(!empty($o['rooms']) && is_array($o['rooms']) ? $o['rooms'] : array());
        $linked_pages = self::prepare_linked_pages_for_payload($o);
        $service_flags = self::prepare_service_flags_for_payload($o);
        $social_profiles = self::prepare_social_profiles_for_payload($o);
        $wedding_flags = array(
            'free_ceremony_possible' => $o['free_ceremony_possible'] ?? 'unknown',
            'registry_office_on_site' => $o['registry_office_on_site'] ?? 'unknown',
            'church_ceremony_possible' => $o['church_ceremony_possible'] ?? 'unknown',
            'indoor_possible' => $o['indoor_possible'] ?? 'unknown',
            'outdoor_possible' => $o['outdoor_possible'] ?? 'unknown',
            'rain_backup' => $o['rain_backup'] ?? 'unknown',
            'barrier_free' => $o['barrier_free'] ?? 'unknown',
        );
        return array(
            'partner_type' => 'eventlocation',
            'business' => array(
                'name' => $o['location_name'] ?? '',
                'website' => $o['website'] ?? home_url('/'),
                'email' => $o['email'] ?? '',
                'phone' => $o['phone'] ?? '',
                'wedding_page_url' => self::selected_wedding_url($o),
                'linked_pages' => $linked_pages,
                'same_as' => self::social_profile_urls($social_profiles),
                'social_profiles' => $social_profiles,
            ),
            'contact' => array(
                'name' => $o['contact_name'] ?? '',
                'role' => $o['contact_role'] ?? '',
                'email' => $o['email'] ?? '',
                'phone' => $o['phone'] ?? '',
                'whatsapp' => $o['whatsapp'] ?? '',
            ),
            'location' => array(
                'street' => $o['street'] ?? '',
                'zip' => $o['zip'] ?? '',
                'city' => $o['city'] ?? '',
                'country' => $o['country'] ?? 'Deutschland',
                'latitude' => $o['latitude'] ?? '',
                'longitude' => $o['longitude'] ?? '',
                'opening_hours' => $o['opening_hours'] ?? array(),
                'appointments_only' => !empty($o['appointments_only']),
                'viewings_by_appointment' => !empty($o['viewings_by_appointment']),
                'evening_appointments' => !empty($o['evening_appointments']),
            ),
            'weddings' => $wedding_flags,
            'rooms' => $rooms,
            'images' => self::collect_payload_images($rooms),
            'services' => array(
                'family' => array('kids_welcome'=>$o['kids_welcome'] ?? 'unknown','playground'=>$o['playground'] ?? 'unknown','childcare_room'=>$o['childcare_room'] ?? 'unknown','changing_room'=>$o['changing_room'] ?? 'unknown','dogs_allowed'=>$o['dogs_allowed'] ?? 'unknown'),
                'overnight' => array('hotel_available'=>$o['hotel_available'] ?? 'unknown','hotel'=>$o['hotel_available'] ?? 'unknown','camper_parking'=>$o['camper_parking'] ?? 'unknown','rv_parking'=>$o['camper_parking'] ?? 'unknown','shuttle_service'=>$o['shuttle_service'] ?? 'unknown','hotel_rooms'=>$o['hotel_rooms'] ?? ''),
                'comfort' => array('wifi'=>$o['wifi'] ?? 'unknown','stage'=>$o['stage'] ?? 'unknown','dancefloor'=>$o['dancefloor'] ?? 'unknown','air_conditioned'=>$o['air_conditioned'] ?? 'unknown','charging_stations'=>$o['charging_stations'] ?? 'unknown'),
                'sustainability' => array('regional_catering'=>$o['regional_catering'] ?? 'unknown','green_power'=>$o['green_power'] ?? 'unknown','sustainable_concept'=>$o['sustainable_concept'] ?? 'unknown'),
                'vendors' => array('free_service_providers'=>$o['free_service_providers'] ?? 'unknown','midnight_snack'=>$o['midnight_snack'] ?? 'unknown','fireworks'=>$o['fireworks'] ?? 'unknown','fixed_catering_partners'=>$o['fixed_catering_partners'] ?? 'unknown'),
                'flat' => $service_flags,
            ),
            'linked_pages' => $linked_pages,
            'landingpage' => array('generated_landingpage_id'=>$o['generated_landingpage_id'] ?? 0,'url'=>self::generated_landingpage_url($o),'tone'=>$o['visitor_tone'] ?? 'du','matching_shape'=>$o['matching_shape'] ?? 'rounded'),
            'consents' => array(
                'partner_directory' => !empty($o['network_directory_optin']),
                'contact_allowed' => !empty($o['network_contact_optin']),
                'market_reports_anonymous' => !empty($o['market_report_optin']),
                'plugin_statistics' => !empty($o['plugin_stats_optin']),
                'development_partner' => !empty($o['network_early_access_optin']),
                'consent_text_version' => '0.5.16-public-data-prep',
                'consented_at' => current_time('mysql'),
            ),
            'data_quality' => array(
                'schema_payload_version' => '0.5.16',
                'last_verified' => current_time('c'),
                'source' => 'Wedding AI Engine',
                'public_database_goal' => 'complete_eventlocation_dataset',
            ),
            'plugin' => array('name'=>'Wedding AI Engine','version'=>WAE_VERSION,'site_url'=>home_url('/'),'instance_id'=>$o['plugin_instance_id'] ?? '','sandbox'=>!empty($o['sandbox_mode']),'update_channel'=>$o['update_channel'] ?? 'stable'),
            'sandbox' => !empty($o['sandbox_mode']),
            'field_test' => true,
        );
    }

    public static function ajax_geocode_address() {
        check_ajax_referer('wae_geocode_address', 'nonce');
        if (!current_user_can('manage_options')) { wp_send_json_error(array('message'=>'Keine Berechtigung.')); }
        $zip = isset($_POST['zip']) ? sanitize_text_field(wp_unslash($_POST['zip'])) : '';
        $city = isset($_POST['city']) ? sanitize_text_field(wp_unslash($_POST['city'])) : '';
        $geo = self::lookup_geo($zip, $city);
        if (!$geo) {
            wp_send_json_error(array(
                'message'=>'Für diese PLZ/Ort-Kombination wurden keine Koordinaten gefunden.',
                'debug'=>'Gesucht wurde: PLZ „' . $zip . '“, Ort „' . $city . '“. Die lokale Ortsdatenbank wurde geladen, aber es gab keinen passenden Treffer.'
            ));
        }
        wp_send_json_success($geo);
    }

    private static function normalize_geo_string($value) {
        $value = trim((string)$value);
        $value = str_replace(array('ä','ö','ü','Ä','Ö','Ü','ß'), array('ae','oe','ue','ae','oe','ue','ss'), $value);
        $value = function_exists('mb_strtolower') ? mb_strtolower($value, 'UTF-8') : strtolower($value);
        $value = preg_replace('/\s+/', ' ', $value);
        return trim($value);
    }

    private static function lookup_geo($zip, $city) {
        $zip = preg_replace('/[^0-9]/', '', (string)$zip);
        $city = trim((string)$city);
        if ($zip === '' && $city === '') { return null; }
        $city_l = self::normalize_geo_string($city);

        /*
         * v0.5.9: Im Feldtest erzeugte der GPS-AJAX-Call auf Shared Hosting HTTP 500.
         * Ursache war sehr wahrscheinlich das Dekodieren des großen kombinierten PLZ-/City-Index.
         * Deshalb wird zuerst eine kleine ZIP-only-Datei geladen. Für normale Adressen ist die PLZ
         * der stabilste Schlüssel und für Matching/Schema reichen Ortskoordinaten völlig aus.
         */
        $zip_file = WAE_PLUGIN_DIR . 'data/ortsdaten-plz-only.json';
        if ($zip !== '' && file_exists($zip_file)) {
            $index = json_decode((string)file_get_contents($zip_file), true);
            if (is_array($index) && !empty($index['zip'][$zip])) {
                $candidate = $index['zip'][$zip];
                $candidate['source'] = 'local_zip_index';
                return $candidate;
            }
        }

        // Schlanker City-Fallback nur, wenn keine PLZ angegeben wurde.
        $index_file = WAE_PLUGIN_DIR . 'data/ortsdaten-plz-index.json';
        if ($zip === '' && $city_l !== '' && file_exists($index_file)) {
            $index = json_decode((string)file_get_contents($index_file), true);
            if (is_array($index) && !empty($index['city'][$city_l])) {
                $candidate = $index['city'][$city_l];
                $candidate['source'] = 'local_city_index';
                return $candidate;
            }
        }

        return null;
    }

    private static function render_header($title) {
        echo '<div class="wrap wae-wrap"><h1>' . esc_html($title) . '</h1>';
    }

    private static function progress_card($step, $score, $title, $text) {
        $step_label = is_numeric($step) ? 'Schritt ' . (int)$step . ' von 3' : 'Schritt ' . $step;
        $score = max(0, min(100, (int)$score));
        $done_text = $score >= 100 ? '100 % der empfohlenen Einrichtung abgeschlossen' : $score . '% der empfohlenen Einrichtung abgeschlossen';
        echo '<div class="wae-progress-card"><div class="wae-step">' . esc_html($step_label) . '</div><h2>' . esc_html($title) . '</h2><div class="wae-bar"><span style="width:' . esc_attr($score) . '%"></span></div><p><strong>' . esc_html($done_text) . '</strong></p><p>' . esc_html($text) . '</p></div>';
    }

    private static function generated_service_page($o) {
        if (!empty($o['generated_landingpage_id'])) {
            $post = get_post((int) $o['generated_landingpage_id']);
            if ($post instanceof WP_Post && $post->post_type === 'page') { return $post; }
        }
        $parent_id = !empty($o['wedding_page_id']) ? (int) $o['wedding_page_id'] : 0;
        if ($parent_id) {
            $children = get_posts(array(
                'post_type' => 'page',
                'post_status' => array('publish','draft','pending','private'),
                'post_parent' => $parent_id,
                'name' => 'trauredner',
                'numberposts' => 1,
            ));
            if (!empty($children[0]) && $children[0] instanceof WP_Post) { return $children[0]; }
        }
        return null;
    }

    private static function completed_steps($o) {
        $completed = 0;
        if (!empty($o['wedding_page_id']) || !empty($o['wedding_page_url'])) { $completed++; }
        if (!empty($o['location_name']) && !empty($o['zip']) && !empty($o['city']) && !empty($o['latitude']) && !empty($o['longitude'])) { $completed++; }
        if ((!empty($o['partner_sync_status']) && $o['partner_sync_status'] === 'success') || !empty($o['partner_uuid']) || !empty($o['network_directory_optin'])) { $completed++; }
        $service_page = self::generated_service_page($o);
        if ($service_page instanceof WP_Post && $service_page->post_status === 'publish') { $completed++; }
        return min(4, $completed);
    }

    public static function calculate_score($o) {
        return self::completed_steps($o) * 25;
    }

    public static function render_dashboard() {
        $o = self::get_options();
        self::render_header('Wedding AI Engine – Übersicht');
        echo '<div class="wae-hero"><h2>Willkommen bei Wedding AI Engine 👋</h2><p>Wedding AI Engine begleitet Eventlocations Schritt für Schritt: Zuerst wird die bestehende Hochzeitsseite geprüft, anschließend werden die wichtigsten Angaben zur Location erfasst. Danach kann ein kostenloses Eventlocation-Profil vorbereitet und ein Trauredner-Service für Brautpaare veröffentlicht werden.</p><p>Der Gedanke bleibt einfach: Ihr pflegt Eure Informationen einmal. Daraus entstehen strukturierte Daten, bessere Inhalte, natürliche Verlinkungen und später ein öffentliches Profil im Wedding AI Verzeichnis.</p></div>';
        $score = self::calculate_score($o);
        $service_page = self::generated_service_page($o);
        if ($score >= 100) {
            self::progress_card('0–3', $score, 'Herzlichen Glückwunsch!', 'Eure Eventlocation ist vollständig eingerichtet: Hochzeitsseite analysiert, strukturierte Daten veröffentlicht, Eventlocation-Profil vorbereitet und Trauredner-Service aktiv.');
            echo '<div class="wae-intro"><h2>Alles erledigt</h2><p>✅ Hochzeitsseite analysiert · ✅ Strukturierte Daten aktiv · ✅ Eventlocation-Profil eingerichtet · ✅ Trauredner-Service veröffentlicht · ✅ Matching und FAQ aktiv</p>';
            if ($service_page instanceof WP_Post) {
                echo '<p><a class="button button-primary" href="'.esc_url(get_permalink($service_page)).'" target="_blank" rel="noopener">Trauredner-Service ansehen</a></p>';
            }
            echo '</div>';
        } else {
            self::progress_card('0–3', $score, 'Aktueller Einrichtungsstand', 'Schritt 0 prüft die Hochzeitsseite. Schritt 1 erfasst Eure Eventlocation. Schritt 2 bereitet das kostenlose Eventlocation-Profil vor. Schritt 3 veröffentlicht den zusätzlichen Trauredner-Service.');
        }
        echo '<div class="wae-grid">';
        self::dashboard_tile('0. KI- & Sichtbarkeitscheck', 'Bestehende Hochzeitsseite prüfen: Schema, SEO-Grundlagen, Plugins und KI-Lesbarkeit.', admin_url('admin.php?page=wae-visibility-check'), self::completed_steps($o) >= 1 ? '✓' : 'Analyse');
        self::dashboard_tile('1. Eventlocation einrichten', 'Daten, GPS, Öffnungszeiten, Räume und verknüpfte Seiten erfassen.', admin_url('admin.php?page=wae-location'), self::completed_steps($o) >= 2 ? '✓' : 'Basis');
        self::dashboard_tile('2. Eventlocation-Profil', 'Kostenlose Aufnahme ins Wedding AI Verzeichnis nach redaktioneller Prüfung vorbereiten.', admin_url('admin.php?page=wae-network'), self::completed_steps($o) >= 3 ? '✓' : 'Profil');
        self::dashboard_tile('3. Trauredner-Service', 'Trauredner-Landingpage mit Matchingtool als Zusatzservice für Brautpaare veröffentlichen.', admin_url('admin.php?page=wae-landingpage'), self::completed_steps($o) >= 4 ? '✓' : 'Service');
        echo '</div>';
        echo '<p class="wae-version-note">Wedding AI Engine v'.esc_html(WAE_VERSION).'</p>';
        echo '</div>';
    }

    private static function dashboard_tile($title, $text, $url, $badge) {
        echo '<div class="wae-tile"><span class="wae-badge">'.esc_html($badge).'</span><h3>'.esc_html($title).'</h3><p>'.esc_html($text).'</p><p><a class="button button-primary" href="'.esc_url($url).'">Öffnen</a></p></div>';
    }

    public static function render_visibility_check() {
        $o = self::get_options();
        self::render_header('Schritt 0: KI- & Sichtbarkeitscheck');
        $platform = self::platform_info($o);
        echo '<div class="wae-hero"><h2>Herzlich willkommen bei Wedding AI Engine 👋</h2><p>In diesem ersten Schritt wählt Ihr die bestehende Hochzeitsseite aus, aktiviert auf Wunsch automatische Updates und startet anschließend den KI- & Sichtbarkeitscheck. Die ausgewählte Hochzeitsseite wird später nicht sichtbar verändert. Wedding AI Engine ergänzt dort nur strukturierte Daten im Hintergrund.</p><p>Die hier gewählte Hochzeitsseite wird automatisch in Schritt 1 übernommen. Ihr müsst die URL also nicht doppelt pflegen. Daten werden erst in Schritt 2 aktiv übertragen und erst nach redaktioneller Prüfung veröffentlicht.</p></div>';
        if (!empty($_GET['wae_saved'])) { echo '<div class="notice notice-success inline"><p>Einrichtung gespeichert. Der KI- & Sichtbarkeitstest wurde gestartet.</p></div>'; }
        echo '<div class="wae-section"><div class="wae-section-inner"><h2>Verbindung zur Rent-a-Pastor Plattform</h2>';
        if (!empty($platform['ok'])) {
            echo '<p><strong>Status:</strong> Verbindung hergestellt.</p>';
            if (!empty($platform['summary'])) { echo '<p>'.esc_html($platform['summary']).'</p>'; }
        } else {
            echo '<p><strong>Status:</strong> Noch nicht geprüft oder aktuell nicht erreichbar.</p><p>Das ist für die lokale Einrichtung nicht kritisch. Daten werden ohnehin erst in Schritt 2 aktiv übertragen.</p>';
        }
        echo '</div></div>';
        echo '<form method="post" action="'.esc_url(admin_url('admin-post.php')).'">';
        wp_nonce_field('wae_step0_save_and_scan');
        echo '<input type="hidden" name="action" value="wae_step0_save_and_scan">';
        echo '<div class="wae-section"><div class="wae-section-inner">';
        echo '<h2>1. Landingpage für Hochzeiten auswählen</h2><p>Wählt hier die bestehende Hochzeitsseite aus. Auf dieser Seite gibt Wedding AI Engine später ausschließlich Schema im Hintergrund aus. Es wird kein sichtbarer FAQ-Block eingefügt und es wird kein Shortcode benötigt. So bleibt das bestehende Layout geschützt.</p>';
        echo '<table class="form-table">';
        self::page_select_row('Landingpage für Hochzeiten', 'wedding_page_id', $o);
        self::text_row('Fallback-URL, falls die Seite nicht auswählbar ist', 'wedding_page_url', $o);
        echo '</table>';
        echo '<h2>2. Updates</h2><p>Wedding AI Engine kann verfügbare Updates wie andere WordPress-Plugins anzeigen. Automatische Updates werden nur ausgeführt, wenn Ihr sie ausdrücklich aktiviert.</p>';
        echo '<table class="form-table">';
        self::checkbox_row('Automatische Updates erlauben', 'auto_updates_enabled', $o);
        self::checkbox_row('Eintrag vor Veröffentlichung prüfen lassen', 'sandbox_mode', $o);
        echo '</table>';
        echo '<p><button type="submit" class="button button-primary button-hero">Speichern & KI-Test starten</button></p>';
        echo '</div></div></form>';
        $run = !empty($_GET['wae_run_check']);
        if (!$run) { echo '</div>'; return; }
        $target = self::selected_wedding_url($o);
        $result = self::scan_url($target);
        echo '<div id="wae-step-0-result" class="wae-scan-result">';
        echo '<h2>KI- & Sichtbarkeitsindex</h2><div class="wae-score-big">'.esc_html($result['score']).'%</div>';
        echo '<p>'.esc_html($result['summary']).'</p>';
        foreach ($result['groups'] as $group) {
            echo '<div class="wae-scan-group"><h3>'.esc_html($group['title']).'</h3><ul>';
            foreach ($group['items'] as $item) { echo '<li class="'.esc_attr($item['state']).'">'.wp_kses_post($item['label']).'</li>'; }
            echo '</ul></div>';
        }
        if (empty($result['sitemap_found'])) {
            echo '<div class="wae-intro"><h3>XML-Sitemap fehlt?</h3><p>Wenn kein SEO-Plugin eine Sitemap ausgibt, kann Wedding AI Engine eine einfache technische Sitemap bereitstellen. Nutzt diese Option nur, wenn wirklich keine WordPress-, Yoast-, RankMath- oder AIOSEO-Sitemap vorhanden ist.</p>';
            echo '<form method="post" action="'.esc_url(admin_url('admin-post.php')).'">';
            wp_nonce_field('wae_enable_sitemap');
            echo '<input type="hidden" name="action" value="wae_enable_sitemap"><button class="button button-secondary">Einfache XML-Sitemap aktivieren</button></form></div>';
        }
        echo '<div class="wae-intro"><h3>Das macht Wedding AI Engine nach der Einrichtung</h3><p>Nach Schritt 1 ergänzt das Plugin strukturierte Daten für Eure Eventlocation, GPS-Koordinaten, Öffnungszeiten, Ansprechpartner und Raumdaten auf der ausgewählten Hochzeitsseite. Sichtbare Inhalte werden dort nicht verändert. Erst der optionale Trauredner-Service aus Schritt 3 erstellt eine eigene sichtbare Seite mit Matchingtool und FAQs.</p></div>';
        echo '</div></div>';
    }

    private static function platform_info($o) {
        $base = !empty($o['core_api_base']) ? untrailingslashit($o['core_api_base']) : 'https://rent-a-pastor.com/wp-json/rentapastor/v1';
        $cache_key = 'wae_platform_info_' . md5($base);
        $cached = get_transient($cache_key);
        if (is_array($cached)) { return $cached; }
        $res = wp_remote_get($base . '/platform/info', array('timeout'=>8));
        if (is_wp_error($res)) { return array('ok'=>false, 'message'=>$res->get_error_message()); }
        $code = wp_remote_retrieve_response_code($res);
        $body = json_decode((string)wp_remote_retrieve_body($res), true);
        $out = array('ok'=>($code >= 200 && $code < 300), 'summary'=>'');
        if (is_array($body)) {
            $out['summary'] = !empty($body['message']) ? sanitize_text_field($body['message']) : 'Die Plattform-API ist erreichbar.';
            $out['raw'] = $body;
        }
        set_transient($cache_key, $out, 12 * HOUR_IN_SECONDS);
        return $out;
    }

    private static function selected_wedding_url($o) {
        if (!empty($o['wedding_page_id'])) {
            $url = get_permalink((int)$o['wedding_page_id']);
            if ($url) { return $url; }
        }
        if (!empty($o['wedding_page_url'])) { return esc_url_raw($o['wedding_page_url']); }
        return home_url('/');
    }


    private static function generated_landingpage_url($o) {
        if (!empty($o['generated_landingpage_id'])) {
            $url = get_permalink((int) $o['generated_landingpage_id']);
            if ($url) { return esc_url_raw($url); }
        }
        return '';
    }

    private static function prepare_rooms_for_payload($rooms) {
        $out = array();
        foreach ($rooms as $room) {
            if (!is_array($room)) { continue; }
            $prepared = $room;
            $prepared['images'] = array();
            foreach (array('image_1','image_2') as $image_key) {
                $image = self::attachment_payload(isset($room[$image_key]) ? (int) $room[$image_key] : 0);
                if ($image) { $prepared['images'][] = $image; }
            }
            // Für Abwärtskompatibilität bleiben die IDs erhalten. Zusätzlich werden saubere URLs geliefert.
            $prepared['image_urls'] = array_values(array_filter(array_map(function($img) { return $img['url'] ?? ''; }, $prepared['images'])));
            $out[] = $prepared;
        }
        return $out;
    }

    private static function attachment_payload($attachment_id) {
        if (!$attachment_id) { return null; }
        $url = wp_get_attachment_image_url($attachment_id, 'full');
        if (!$url) { return null; }
        $meta = wp_get_attachment_metadata($attachment_id);
        $alt = get_post_meta($attachment_id, '_wp_attachment_image_alt', true);
        $post = get_post($attachment_id);
        return array_filter(array(
            'id' => $attachment_id,
            'url' => esc_url_raw($url),
            'alt' => is_string($alt) ? sanitize_text_field($alt) : '',
            'caption' => $post instanceof WP_Post ? sanitize_text_field($post->post_excerpt) : '',
            'title' => $post instanceof WP_Post ? sanitize_text_field($post->post_title) : '',
            'width' => is_array($meta) && !empty($meta['width']) ? (int) $meta['width'] : null,
            'height' => is_array($meta) && !empty($meta['height']) ? (int) $meta['height'] : null,
        ), function($v) { return $v !== null && $v !== ''; });
    }

    private static function collect_payload_images($rooms) {
        $images = array();
        foreach ($rooms as $room) {
            if (empty($room['images']) || !is_array($room['images'])) { continue; }
            foreach ($room['images'] as $image) {
                if (!empty($image['url'])) { $images[$image['url']] = $image; }
            }
        }
        return array_values($images);
    }

    private static function prepare_linked_pages_for_payload($o) {
        $map = array(
            'wedding_page_id' => 'wedding',
            'contact_page_id' => 'contact',
            'gallery_page_id' => 'gallery',
            'prices_page_id' => 'prices',
            'overnight_page_id' => 'overnight',
            'directions_page_id' => 'directions',
            'terms_page_id' => 'terms',
            'privacy_page_id' => 'privacy',
            'imprint_page_id' => 'imprint',
        );
        $pages = array();
        foreach ($map as $option_key => $type) {
            if (empty($o[$option_key])) { continue; }
            $page = get_post((int) $o[$option_key]);
            $url = get_permalink((int) $o[$option_key]);
            if (!$url) { continue; }
            $pages[$type] = array(
                'type' => $type,
                'id' => (int) $o[$option_key],
                'title' => $page instanceof WP_Post ? get_the_title($page) : '',
                'url' => esc_url_raw($url),
            );
        }
        if (empty($pages['wedding']) && !empty($o['wedding_page_url'])) {
            $pages['wedding'] = array('type'=>'wedding','id'=>0,'title'=>'Hochzeitsseite','url'=>esc_url_raw($o['wedding_page_url']));
        }
        return $pages;
    }

    private static function prepare_social_profiles_for_payload($o) {
        $map = array(
            'instagram' => 'Instagram',
            'facebook' => 'Facebook',
            'pinterest' => 'Pinterest',
            'youtube' => 'YouTube',
            'tiktok' => 'TikTok',
            'linkedin' => 'LinkedIn',
            'xing' => 'Xing',
        );
        $profiles = array();
        foreach ($map as $key => $label) {
            if (empty($o[$key])) { continue; }
            $url = esc_url_raw($o[$key]);
            if (!$url) { continue; }
            $profiles[$key] = array(
                'platform' => $label,
                'url' => $url,
            );
        }
        return $profiles;
    }

    private static function social_profile_urls($profiles) {
        $urls = array();
        if (!is_array($profiles)) { return $urls; }
        foreach ($profiles as $profile) {
            if (is_array($profile) && !empty($profile['url'])) {
                $urls[] = esc_url_raw($profile['url']);
            }
        }
        return array_values(array_unique(array_filter($urls)));
    }

    private static function prepare_service_flags_for_payload($o) {
        $keys = array_merge(self::$tri_fields, array('appointments_only','viewings_by_appointment','evening_appointments'));
        $flags = array();
        foreach ($keys as $key) {
            if (array_key_exists($key, $o)) { $flags[$key] = $o[$key]; }
        }
        return $flags;
    }

    private static function scan_url($url) {
        $html = '';
        $ok = false;
        $response = wp_remote_get($url, array('timeout'=>8));
        if (!is_wp_error($response)) {
            $code = wp_remote_retrieve_response_code($response);
            $html = (string) wp_remote_retrieve_body($response);
            $ok = ($code >= 200 && $code < 400 && $html !== '');
        }
        $active = function_exists('get_option') ? (array)get_option('active_plugins', array()) : array();
        $plugins = array();
        foreach ($active as $plugin) {
            if (stripos($plugin, 'wordpress-seo') !== false) { $plugins[] = 'Yoast SEO'; }
            if (stripos($plugin, 'rank-math') !== false) { $plugins[] = 'Rank Math'; }
            if (stripos($plugin, 'all-in-one-seo') !== false) { $plugins[] = 'AIOSEO'; }
            if (stripos($plugin, 'schema-and-structured-data') !== false || stripos($plugin, 'schema') !== false) { $plugins[] = 'Schema-Plugin'; }
            if (stripos($plugin, 'wedding-ai-engine') !== false) { $plugins[] = 'Wedding AI Engine'; }
        }
        $types = array();
        if ($html) {
            preg_match_all('/"@type"\s*:\s*(?:\[)?\s*"([^"]+)"/i', $html, $m);
            $types = array_values(array_unique($m[1] ?? array()));
        }
        $sitemap_info = self::detect_sitemap();
        $checks = array(
            'reachable' => $ok,
            'title' => (bool)preg_match('/<title[^>]*>.+?<\/title>/is', $html),
            'description' => (bool)preg_match('/<meta[^>]+name=[\"\']description[\"\'][^>]*>/i', $html),
            'canonical' => (bool)preg_match('/rel=[\"\']canonical[\"\']/i', $html),
            'og' => (bool)preg_match('/property=[\"\']og:/i', $html),
            'faq' => in_array('FAQPage', $types, true),
            'venue' => in_array('EventVenue', $types, true),
            'local' => in_array('LocalBusiness', $types, true),
            'geo' => (stripos($html, 'GeoCoordinates') !== false),
            'sitemap' => !empty($sitemap_info['found']),
        );
        $score = 0; foreach ($checks as $v) { if ($v) { $score += 10; } }
        if (!empty($plugins)) { $score += 10; }
        $score = min(100, $score);
        return array(
            'score'=>$score,
            'sitemap_found'=>!empty($sitemap_info['found']),
            'summary'=>$score >= 80 ? 'Die Seite ist bereits gut vorbereitet. Einige Punkte kann Wedding AI Engine weiter verbessern.' : 'Die Seite hat eine solide Grundlage, aber wichtige KI- und Strukturdaten fehlen noch.',
            'groups'=>array(
                array('title'=>'Erreichbarkeit','items'=>array(array('state'=>$checks['reachable']?'ok':'warn','label'=>$checks['reachable']?'Seite erreichbar':'Seite konnte nicht zuverlässig geprüft werden'))),
                array('title'=>'Suchmaschinen-Grundlagen','items'=>array(
                    array('state'=>$checks['title']?'ok':'warn','label'=>$checks['title']?'Seitentitel vorhanden':'Seitentitel nicht erkannt'),
                    array('state'=>$checks['description']?'ok':'warn','label'=>$checks['description']?'Meta Description vorhanden':'Meta Description nicht erkannt'),
                    array('state'=>$checks['canonical']?'ok':'warn','label'=>$checks['canonical']?'Canonical vorhanden':'Canonical nicht erkannt'),
                    array('state'=>$checks['og']?'ok':'warn','label'=>$checks['og']?'OpenGraph-Daten vorhanden':'OpenGraph-Daten nicht erkannt'),
                    array('state'=>$checks['sitemap']?'ok':'warn','label'=>$checks['sitemap']?'XML-Sitemap gefunden: '.esc_html($sitemap_info['url'] ?? ''):'Keine XML-Sitemap erkannt'),
                )),
                array('title'=>'Strukturierte Daten','items'=>array(
                    array('state'=>!empty($types)?'ok':'warn','label'=>!empty($types)?'Erkannte Schema-Typen: '.esc_html(implode(', ', array_slice($types,0,8))):'Keine Schema-Typen erkannt'),
                    array('state'=>$checks['faq']?'ok':'warn','label'=>$checks['faq']?'FAQPage vorhanden':'FAQPage fehlt oder wurde nicht erkannt'),
                    array('state'=>$checks['venue']?'ok':'warn','label'=>$checks['venue']?'EventVenue vorhanden':'EventVenue fehlt noch'),
                    array('state'=>$checks['geo']?'ok':'warn','label'=>$checks['geo']?'GeoCoordinates vorhanden':'GPS-Koordinaten fehlen noch'),
                )),
                array('title'=>'Erkannte Plugins','items'=>array(array('state'=>!empty($plugins)?'ok':'warn','label'=>!empty($plugins)?esc_html(implode(', ', array_unique($plugins))):'Kein relevantes SEO-/Schema-Plugin erkannt'))),
            )
        );
    }

    private static function detect_sitemap() {
        $candidates = array(
            home_url('/wp-sitemap.xml'),
            home_url('/sitemap_index.xml'),
            home_url('/sitemap.xml'),
            home_url('/wae-sitemap.xml'),
        );
        foreach ($candidates as $candidate) {
            $res = wp_remote_get($candidate, array('timeout'=>6));
            if (!is_wp_error($res)) {
                $code = wp_remote_retrieve_response_code($res);
                $body = (string) wp_remote_retrieve_body($res);
                if ($code >= 200 && $code < 400 && (stripos($body, '<urlset') !== false || stripos($body, '<sitemapindex') !== false)) {
                    return array('found'=>true, 'url'=>$candidate);
                }
            }
        }
        return array('found'=>false, 'url'=>'');
    }

    public static function handle_enable_sitemap() {
        if (!current_user_can('manage_options')) { wp_die('Keine Berechtigung.'); }
        check_admin_referer('wae_enable_sitemap');
        $o = self::get_options();
        $o['simple_sitemap_enabled'] = '1';
        update_option('wae_options', $o, false);
        flush_rewrite_rules(false);
        wp_safe_redirect(add_query_arg(array('page'=>'wae-visibility-check','wae_run_check'=>'1','wae_sitemap_enabled'=>'1'), admin_url('admin.php')) . '#wae-step-0-result');
        exit;
    }

    public static function render_location() {
        $o = self::get_options();
        self::render_header('Schritt 1: Eventlocation einrichten');
        self::progress_card('1', self::$progress_steps[1], 'Eure Eventlocation vollständig erfassen', 'In diesem Schritt werden alle wichtigen Informationen zur Location gesammelt: Adresse, GPS, Öffnungszeiten, Räume, Ausstattung und verknüpfte Seiten.');
        if (!empty($_GET['wae_saved'])) { echo '<div id="wae-step-1-saved" class="notice notice-success inline"><p>Daten gespeichert. Die KI-Grundoptimierung wird auf der ausgewählten Hochzeitsseite im Hintergrund ausgegeben.</p></div>'; }
        echo '<div class="wae-intro"><h2>Warum ist dieser Schritt wichtig?</h2><p>Viele Eventlocations haben schöne Bilder und gute Texte, aber Suchmaschinen und KI-Systeme können wichtige Details oft nicht eindeutig erkennen: Gibt es eine freie Trauung? Ist die Location barrierefrei? Sind Hunde erlaubt? Gibt es eine Regenalternative? Genau diese Informationen werden hier strukturiert erfasst.</p><p>Je vollständiger Eure Angaben sind, desto besser können daraus später Schema, FAQ, Landingpage-Texte, Partnerverzeichnis-Einträge und Marktanalysen entstehen.</p></div>';
        echo '<form id="wae-step-1-form" method="post" action="'.esc_url(admin_url('admin-post.php')).'">'; wp_nonce_field('wae_step1_save'); echo '<input type="hidden" name="action" value="wae_step1_save">';
        echo '<div class="wae-accordion">';
        self::section_open('Allgemeine Angaben', 'Diese Daten identifizieren Eure Eventlocation und bilden die Grundlage für strukturierte Daten, Kontaktinformationen und spätere Partnerprofile. Die in Schritt 0 ausgewählte Hochzeitsseite ist hier bereits übernommen. Auf genau dieser Seite ergänzt Wedding AI Engine später unsichtbar die Schema-Daten.');
        echo '<table class="form-table">';
        self::text_row('Name der Location', 'location_name', $o);
        self::text_row('Straße und Hausnummer', 'street', $o);
        self::text_row('PLZ', 'zip', $o);
        self::text_row('Ort', 'city', $o);
        self::text_row('Land', 'country', $o);
        echo '</table>';
        echo '<div class="wae-gps-box"><h3>GPS-Koordinaten</h3><p>Exakte Koordinaten helfen Suchmaschinen, Karten und dem Matching dabei, Eure Eventlocation eindeutig zu erkennen. Nach dem Speichern nutzt Wedding AI Engine diese Angaben auch für Schema und Entfernungsmessung.</p><p><button type="button" class="button wae-geocode-button">📍 Adresse prüfen und GPS-Koordinaten übernehmen</button> <span class="wae-geocode-status"></span></p>';
        echo '<table class="form-table">';
        self::text_row('Breitengrad', 'latitude', $o);
        self::text_row('Längengrad', 'longitude', $o);
        echo '</table></div>';
        echo '<table class="form-table">';
        self::text_row('Telefon', 'phone', $o);
        self::text_row('E-Mail', 'email', $o);
        self::text_row('Website', 'website', $o);
        self::page_select_row('Bestehende Hochzeitsseite auswählen', 'wedding_page_id', $o);
        self::text_row('Fallback-URL der Hochzeitsseite (optional)', 'wedding_page_url', $o);
        self::text_row('Ansprechpartner', 'contact_name', $o);
        self::text_row('Rolle/Funktion', 'contact_role', $o);
        echo '</table>'; self::section_close();

        self::section_open('Social Media & öffentliche Profile', 'Diese Links helfen dabei, Eure Eventlocation im öffentlichen Datenbestand eindeutig zuzuordnen. Sie werden später als sameAs-Verknüpfungen in der öffentlichen Eventlocation-Datenbank genutzt. Tragt nur Profile ein, die wirklich zu Eurer Location gehören.');
        echo '<table class="form-table">';
        self::text_row('Instagram', 'instagram', $o, 'https://www.instagram.com/...');
        self::text_row('Facebook', 'facebook', $o, 'https://www.facebook.com/...');
        self::text_row('Pinterest', 'pinterest', $o, 'https://www.pinterest.de/...');
        self::text_row('YouTube', 'youtube', $o, 'https://www.youtube.com/...');
        self::text_row('TikTok', 'tiktok', $o, 'https://www.tiktok.com/@...');
        self::text_row('LinkedIn', 'linkedin', $o, 'https://www.linkedin.com/company/...');
        self::text_row('Xing', 'xing', $o, 'https://www.xing.com/...');
        echo '</table>'; self::section_close();

        self::section_open('Öffnungszeiten', 'Öffnungszeiten helfen Gästen bei der Orientierung und werden zusätzlich als OpeningHoursSpecification im Schema ausgegeben. Wenn Ihr ausschließlich nach Termin arbeitet, könnt Ihr das ebenfalls angeben.');
        self::opening_hours_editor($o);
        echo '<table class="form-table">';
        self::checkbox_row('Termine nach Vereinbarung', 'appointments_only', $o);
        self::checkbox_row('Besichtigungen nur nach Termin', 'viewings_by_appointment', $o);
        self::checkbox_row('Abendtermine möglich', 'evening_appointments', $o);
        echo '</table>'; self::section_close();

        self::section_open('Verknüpfte Seiten', 'Hier könnt Ihr wichtige vorhandene Seiten auswählen. Die Human Content Engine verlinkt sie später nur dort, wo es inhaltlich passt. So entstehen natürliche interne Links statt einer künstlichen Linkliste.');
        echo '<table class="form-table">';
        self::page_select_row('Kontaktseite', 'contact_page_id', $o);
        self::page_select_row('Galerie', 'gallery_page_id', $o);
        self::page_select_row('Preise', 'prices_page_id', $o);
        self::page_select_row('Übernachtung', 'overnight_page_id', $o);
        self::page_select_row('Anfahrt', 'directions_page_id', $o);
        self::page_select_row('AGB', 'terms_page_id', $o);
        self::page_select_row('Datenschutzerklärung', 'privacy_page_id', $o);
        self::page_select_row('Impressum', 'imprint_page_id', $o);
        echo '</table>'; self::section_close();

        self::section_open('Trauung', 'Diese Angaben helfen Brautpaaren und KI-Systemen zu verstehen, welche Arten von Trauungen bei Euch grundsätzlich möglich sind.');
        echo '<table class="form-table">';
        self::tri_row('Freie Trauung möglich', 'free_ceremony_possible', $o);
        self::tri_row('Standesamt vor Ort', 'registry_office_on_site', $o);
        self::tri_row('Kirchliche Trauung möglich', 'church_ceremony_possible', $o);
        self::tri_row('Indoor möglich', 'indoor_possible', $o);
        self::tri_row('Outdoor möglich', 'outdoor_possible', $o);
        self::tri_row('Regenalternative vorhanden', 'rain_backup', $o);
        echo '</table>'; self::section_close();

        self::render_rooms($o);

        self::section_open('Familie & Gäste', 'Diese Angaben sind für viele Paare sehr praktisch. Aus ihnen können später automatisch FAQs und Filter entstehen.');
        echo '<table class="form-table">';
        self::tri_row('Kinder willkommen', 'kids_welcome', $o);
        self::tri_row('Spielplatz vorhanden', 'playground', $o);
        self::tri_row('Kinderbetreuungsraum / Spielzimmer', 'childcare_room', $o);
        self::tri_row('Wickelraum', 'changing_room', $o);
        self::tri_row('Hunde erlaubt', 'dogs_allowed', $o);
        self::text_row('Hinweis zu Familien / Kindern', 'family_note', $o);
        echo '</table>'; self::section_close();

        self::section_open('Übernachtung & Anreise', 'Diese Informationen sind für Gästeplanung, KI-Verständlichkeit und spätere Partnerverzeichnisse sehr wertvoll.');
        echo '<table class="form-table">';
        self::tri_row('Hotel / Übernachtung möglich', 'hotel_available', $o);
        self::text_row('Anzahl Zimmer / Hinweis', 'hotel_rooms', $o);
        self::tri_row('Wohnmobilstellplätze', 'camper_parking', $o);
        self::tri_row('Shuttle-Service', 'shuttle_service', $o);
        self::text_row('Parkplätze Anzahl / Hinweis', 'parking_count', $o);
        echo '</table>'; self::section_close();

        self::section_open('Komfort & Ausstattung', 'Diese Merkmale helfen Brautpaaren bei der Auswahl und können später automatisch auf der Landingpage, in FAQs und als Filter genutzt werden.');
        echo '<table class="form-table">';
        self::tri_row('Klimaanlage / klimatisiert', 'air_conditioned', $o);
        self::tri_row('Barrierefrei', 'barrier_free', $o);
        self::tri_row('WLAN', 'wifi', $o);
        self::tri_row('Bühne', 'stage', $o);
        self::tri_row('Tanzfläche', 'dancefloor', $o);
        self::tri_row('Ladesäulen', 'charging_stations', $o);
        self::tri_row('Freie Dienstleister erlaubt', 'free_service_providers', $o);
        self::tri_row('Mitternachtssnack möglich', 'midnight_snack', $o);
        self::tri_row('Feuerwerk möglich', 'fireworks', $o);
        self::tri_row('Feste Cateringpartner', 'fixed_catering_partners', $o);
        self::text_row('Hinweis zu Ausstattung / Komfort', 'comfort_note', $o);
        echo '</table>'; self::section_close();

        self::section_open('Nachhaltigkeit', 'Nachhaltigkeit wird für viele Paare wichtiger. Diese Angaben können später in Partnerprofilen und Marktanalysen ausgewertet werden.');
        echo '<table class="form-table">';
        self::tri_row('Regionales Catering', 'regional_catering', $o);
        self::tri_row('Ökostrom', 'green_power', $o);
        self::tri_row('Nachhaltiges Konzept', 'sustainable_concept', $o);
        self::text_row('Hinweis zur Nachhaltigkeit', 'sustainability_note', $o);
        echo '</table>'; self::section_close();

        self::section_open('Preise', 'Preise sind optional. Wenn Ihr sie angebt, können sie später für eigene Hinweise, Marktanalysen oder Preisreports anonymisiert genutzt werden, sofern Ihr dem zustimmt.');
        echo '<table class="form-table">'; self::text_row('Allgemeiner Preis-/Miet-Hinweis', 'price_note', $o); echo '</table>'; self::section_close();
        echo '<div class="wae-save-info"><h3>Was passiert beim Speichern?</h3><p>Wedding AI Engine speichert Eure Angaben und ergänzt auf der ausgewählten Hochzeitsseite automatisch strukturierte Daten im Hintergrund. Die sichtbare Seite wird dabei nicht verändert: kein zusätzlicher Textblock, kein Shortcode und keine Layoutänderung. Auch FAQ-Informationen werden hier ausschließlich als Schema ausgegeben. Sichtbare FAQs erscheinen erst auf der optionalen Trauredner-Service-Seite.</p>'; self::schema_debug_box($o); echo '</div>'; echo '</div>'; submit_button('Speichern und KI-Grundoptimierung erstellen', 'primary', 'submit', false); echo ' <a class="button button-secondary" href="'.esc_url(admin_url('admin.php?page=wae-network')).'">Weiter zu Schritt 2</a>'; echo '</form></div>';
    }

    private static function render_rooms($o) {
        $rooms = !empty($o['rooms']) && is_array($o['rooms']) ? $o['rooms'] : array(array(), array(), array());
        self::section_open('Räume / Bereiche', 'Viele Locations haben mehrere Räume, Plätze oder Außenbereiche mit unterschiedlicher Kapazität. Diese Angaben sind besonders wertvoll, weil daraus später Landingpage-Texte, FAQs, Schema und Filter entstehen können.');
        for ($i=0; $i<3; $i++) {
            $r = isset($rooms[$i]) ? $rooms[$i] : array();
            echo '<fieldset class="wae-room"><legend><strong>Raum/Bereich ' . esc_html($i+1) . '</strong></legend>';
            echo '<p><label>Name<br><input class="regular-text" name="wae_options[rooms]['.$i.'][name]" value="'.esc_attr($r['name'] ?? '').'"></label></p>';
            echo '<p><label>Beschreibung<br><textarea class="large-text" rows="3" name="wae_options[rooms]['.$i.'][description]">'.esc_textarea($r['description'] ?? '').'</textarea></label></p>';
            echo '<p><label>Personen min. <input type="number" name="wae_options[rooms]['.$i.'][capacity_min]" value="'.esc_attr($r['capacity_min'] ?? '').'" style="width:100px"></label> ';
            echo '<label>max. <input type="number" name="wae_options[rooms]['.$i.'][capacity_max]" value="'.esc_attr($r['capacity_max'] ?? '').'" style="width:100px"></label></p>';
            echo '<div class="wae-room-grid">';
            self::tri_inline('Freie Trauung', 'rooms]['.$i.'][free_ceremony', $r['free_ceremony'] ?? 'unknown');
            self::tri_inline('Feier möglich', 'rooms]['.$i.'][party', $r['party'] ?? 'unknown');
            self::tri_inline('Indoor', 'rooms]['.$i.'][indoor', $r['indoor'] ?? 'unknown');
            self::tri_inline('Outdoor', 'rooms]['.$i.'][outdoor', $r['outdoor'] ?? 'unknown');
            self::tri_inline('Klimatisiert', 'rooms]['.$i.'][air_conditioned', $r['air_conditioned'] ?? 'unknown');
            self::tri_inline('Barrierefrei', 'rooms]['.$i.'][barrier_free', $r['barrier_free'] ?? 'unknown');
            self::tri_inline('Regenalternative', 'rooms]['.$i.'][rain_backup', $r['rain_backup'] ?? 'unknown');
            echo '</div>';
            echo '<p><label>Preis von <input name="wae_options[rooms]['.$i.'][price_from]" value="'.esc_attr($r['price_from'] ?? '').'" style="width:120px"></label> ';
            echo '<label>bis <input name="wae_options[rooms]['.$i.'][price_to]" value="'.esc_attr($r['price_to'] ?? '').'" style="width:120px"></label></p>';
            self::image_picker('Bild 1', 'wae_options[rooms]['.$i.'][image_1]', $r['image_1'] ?? 0);
            self::image_picker('Bild 2', 'wae_options[rooms]['.$i.'][image_2]', $r['image_2'] ?? 0);
            echo '</fieldset>';
        }
        self::section_close();
    }

    public static function render_landingpage() {
        $o = self::get_options(); self::render_header('Schritt 3: Kostenlosen Trauredner-Service aktivieren');
        self::progress_card('3', self::$progress_steps[3], 'Optionaler Zusatzservice für Brautpaare', 'Die KI-Basisoptimierung und das Eventlocation-Profil sind vorbereitet. Dieser Schritt erstellt zusätzlich eine Trauredner-Seite mit Matchingtool als Service für Eure Paare.');
        echo '<div class="wae-intro wae-landing-guidance"><h2>Kostenloser Service für Eure Brautpaare</h2>';
        echo '<p>Die Wahl des passenden Trauredners gehört zu den wichtigsten Entscheidungen einer freien Trauung. Viele Paare wissen aber nicht, wo sie mit der Suche beginnen sollen. Mit Wedding AI Engine könnt Ihr ihnen genau an dieser Stelle helfen.</p>';
        echo '<p>Das Plugin erstellt eine zusätzliche Trauredner-Seite für Eure Eventlocation. Eure Location bleibt dabei im Mittelpunkt. Die Seite ergänzt Eure bestehende Hochzeitsseite, erklärt den nächsten Planungsschritt und verlinkt selbstverständlich zurück auf Eure Hochzeitsseite. Das Matchingtool ist fester Bestandteil dieser Seite. Wenn Ihr diesen Service nicht anbieten möchtet, könnt Ihr Schritt 3 einfach überspringen.</p>';
        echo '<h3>Was wird automatisch erstellt?</h3><ul class="wae-checklist"><li>ein Trauredner-Matching als Service für Eure Brautpaare</li><li>Texte, die Eure Eventlocation als Ausgangspunkt der freien Trauung erklären</li><li>sichtbare FAQs aus den zuvor eingegebenen Locationdaten</li><li>zusätzliche Fragen und Antworten rund um Trauredner und freie Trauungen</li><li>FAQPage-Schema und weitere strukturierte Daten</li><li>eine klare Verlinkung zu Eurer bestehenden Hochzeitsseite</li></ul>';
        echo '<p>Nach der Veröffentlichung könnt Ihr die WordPress-Seite redaktionell und grafisch anpassen: eigene Bilder ergänzen, Texte erweitern, Videos einfügen oder das Layout verfeinern. Die Rednerprofile öffnen sich als externe Profilseiten auf rent-a-pastor.com.</p></div>';
        if (!empty($_GET['wae_generated'])) { echo '<div id="wae-step-3-status" class="notice notice-success inline"><p>Trauredner-Service wurde veröffentlicht oder aktualisiert.</p></div>'; }
        if (!empty($_GET['wae_error'])) { echo '<div id="wae-step-3-status" class="notice notice-error inline"><p>Die Trauredner-Service-Seite konnte nicht erstellt werden: '.esc_html(wp_unslash($_GET['wae_error'])).'</p></div>'; }
        echo '<form method="post" action="'.esc_url(admin_url('admin-post.php')).'">';
        wp_nonce_field('wae_step3_save_create');
        echo '<input type="hidden" name="action" value="wae_step3_save_create">';
        echo '<table class="form-table">';
        self::tone_row('Ansprache der Besucher', 'visitor_tone', $o);
        self::shape_row('Darstellung des Matchingtools', 'matching_shape', $o);
        self::text_row('Primärfarbe', 'primary_color', $o, '#681472');
        self::text_row('Buttonfarbe', 'button_color', $o, '#681472');
        self::text_row('Button-Textfarbe', 'button_text_color', $o, '#ffffff');
        echo '</table>';
        submit_button('Speichern & Veröffentlichen', 'primary', 'submit', false);
        if (!empty($o['generated_landingpage_id'])) {
            echo ' <a class="button button-secondary" href="'.esc_url(get_edit_post_link((int)$o['generated_landingpage_id'])).'">Seite bearbeiten</a> ';
            echo '<a class="button button-secondary" href="'.esc_url(get_permalink((int)$o['generated_landingpage_id'])).'">Seite öffnen</a>';
        }
        echo '</form></div>';
    }

    public static function render_network() {
        $o = self::get_options(); self::render_header('Schritt 2: Kostenloses Eventlocation-Profil aktivieren');
        self::progress_card('2', self::$progress_steps[2], 'Wedding AI Verzeichnis vorbereiten', 'Mit Eurer Zustimmung kann aus den bereits erfassten Daten ein kostenloses Eventlocation-Profil entstehen. Der Trauredner-Service kommt erst danach als optionaler Zusatz.');
        echo '<div class="wae-intro"><h2>Ein kostenloses Profil für Eure Eventlocation</h2><p>Wenn Ihr möchtet, kann aus den Angaben aus Schritt 1 nach einer redaktionellen Prüfung ein öffentliches Profil im Wedding AI Verzeichnis entstehen. Ihr müsst dafür keine Daten erneut eingeben. Die Informationen werden aus den bereits gepflegten Angaben übernommen.</p><p>Der Vorteil: Eure Location erhält zusätzliche Sichtbarkeit, eine thematisch passende Verlinkung zu Eurer Website und kann später in Marktberichten, Kartenansichten und Empfehlungen berücksichtigt werden. Der Link ist kein beliebiger Verzeichniseintrag, sondern entsteht in einem fachlich passenden Umfeld rund um Hochzeiten, freie Trauungen und Eventlocations.</p><p>Wenn Ihr das Profil aktiviert, werden die dafür notwendigen Eventlocation-Daten zur redaktionellen Prüfung übertragen. Eine öffentliche Anzeige erfolgt erst nach Freigabe.</p></div>';
        if (!empty($_GET['wae_synced'])) { echo '<div id="wae-step-2-status" class="notice notice-success inline"><p>Schritt 2 wurde gespeichert und die Datenübertragung wurde ausgeführt. Bitte prüfe den Status unten.</p></div>'; }
        echo '<form method="post" action="'.esc_url(admin_url('admin-post.php')).'">';
        wp_nonce_field('wae_step2_save_send');
        echo '<input type="hidden" name="action" value="wae_step2_save_send">';
        echo '<table class="form-table">';
        self::checkbox_row('Kostenloses Partnerprofil nach Prüfung veröffentlichen', 'network_directory_optin', $o);
        self::checkbox_row('Kontaktaufnahme zu Kooperationen erlauben', 'network_contact_optin', $o);
        self::checkbox_row('Anonymisierte Marktanalysen erlauben', 'market_report_optin', $o);
        self::checkbox_row('Pluginstatistiken erlauben', 'plugin_stats_optin', $o);
        self::checkbox_row('Frühzeitige Informationen zu neuen Funktionen erhalten', 'network_early_access_optin', $o);
        echo '</table>';
        echo '<div class="wae-sync-box"><h2>Eventlocation-Profil vorbereiten</h2><p>Ein Klick auf <strong>Speichern &amp; Senden</strong> speichert diese Angaben und überträgt die aktuell gespeicherten Eventlocation-Daten zur redaktionellen Prüfung. Bei der ersten Übertragung wird ein neuer Eintrag vorbereitet. Weitere Übertragungen aktualisieren denselben Eintrag.</p>';
        if (!empty($o['partner_sync_status'])) {
            echo '<p><strong>Status:</strong> '.esc_html($o['partner_sync_status']).' · '.esc_html($o['partner_sync_message'] ?? '').'</p>';
            if (!empty($o['partner_last_sync'])) { echo '<p><strong>Letzte Übertragung:</strong> '.esc_html($o['partner_last_sync']).'</p>'; }
            if (!empty($o['partner_uuid'])) { echo '<p><strong>Profil-ID:</strong> <code>'.esc_html($o['partner_uuid']).'</code></p>'; }
        }
        echo '</div>';
        submit_button('Speichern & Senden', 'primary', 'submit', false);
        echo ' <a class="button button-secondary" href="'.esc_url(admin_url('admin.php?page=wae-landingpage')).'">Weiter zu Schritt 3</a>';
        echo '</form></div>';
    }

    private static function schema_debug_box($o) {
        $page_id = !empty($o['wedding_page_id']) ? (int)$o['wedding_page_id'] : 0;
        $url = $page_id ? get_permalink($page_id) : (!empty($o['wedding_page_url']) ? esc_url_raw($o['wedding_page_url']) : '');
        echo '<div class="wae-schema-status"><h4>Schema-Status</h4>';
        if ($page_id) {
            echo '<p><strong>Erkannte WordPress-Seite:</strong> ID '.esc_html($page_id).' · <a href="'.esc_url($url).'" target="_blank" rel="noopener">'.esc_html($url).'</a></p>';
            echo '<p><strong>Ausgabe:</strong> Schema wird automatisch über <code>wp_head</code> auf dieser Seite ausgegeben. Es ist kein Shortcode nötig.</p>';
            echo '<p><strong>Cache:</strong> Beim Speichern versucht Wedding AI Engine, bekannte Seitencaches automatisch zu leeren. Falls im Quelltext noch eine alte Plugin-Version sichtbar ist, bitte zusätzlich den Seiten-Cache manuell leeren.</p>';
        } elseif ($url) {
            echo '<p><strong>Fallback-URL:</strong> <a href="'.esc_url($url).'" target="_blank" rel="noopener">'.esc_html($url).'</a></p>';
            echo '<p><strong>Hinweis:</strong> Die URL konnte keiner WordPress-Seite zugeordnet werden. Für zuverlässige Schema-Ausgabe bitte möglichst eine Seite aus dem Dropdown wählen.</p>';
        } else {
            echo '<p><strong>Status:</strong> Noch keine Hochzeitsseite ausgewählt.</p>';
        }
        echo '</div>';
    }

    private static function opening_hours_editor($o) {
        $days = array('monday'=>'Montag','tuesday'=>'Dienstag','wednesday'=>'Mittwoch','thursday'=>'Donnerstag','friday'=>'Freitag','saturday'=>'Samstag','sunday'=>'Sonntag');
        $hours = isset($o['opening_hours']) && is_array($o['opening_hours']) ? $o['opening_hours'] : array();
        echo '<table class="widefat striped wae-opening-hours"><thead><tr><th>Tag</th><th>geöffnet</th><th>von</th><th>bis</th></tr></thead><tbody>';
        foreach ($days as $key=>$label) {
            $row = isset($hours[$key]) && is_array($hours[$key]) ? $hours[$key] : array();
            echo '<tr><td>'.esc_html($label).'</td><td><input type="checkbox" name="wae_options[opening_hours]['.esc_attr($key).'][open]" value="1" '.checked(($row['open'] ?? '') === '1', true, false).'></td><td><input type="time" name="wae_options[opening_hours]['.esc_attr($key).'][from]" value="'.esc_attr($row['from'] ?? '').'"></td><td><input type="time" name="wae_options[opening_hours]['.esc_attr($key).'][to]" value="'.esc_attr($row['to'] ?? '').'"></td></tr>';
        }
        echo '</tbody></table>';
    }

    private static function section_open($title, $why) {
        echo '<details class="wae-section" open><summary><strong>'.esc_html($title).'</strong></summary><div class="wae-section-inner"><div class="wae-why"><strong>Warum fragen wir das?</strong><br>'.esc_html($why).'</div>';
    }
    private static function section_close() { echo '</div></details>'; }

    private static function text_row($label, $key, $o, $placeholder='') {
        echo '<tr><th scope="row"><label for="'.esc_attr($key).'">'.esc_html($label).'</label></th><td><input class="regular-text" id="'.esc_attr($key).'" name="wae_options['.esc_attr($key).']" value="'.esc_attr($o[$key] ?? '').'" placeholder="'.esc_attr($placeholder).'"></td></tr>';
    }
    private static function checkbox_row($label, $key, $o) {
        echo '<tr><th scope="row">'.esc_html($label).'</th><td><label><input type="checkbox" name="wae_options['.esc_attr($key).']" value="1" '.checked(($o[$key] ?? '') === '1', true, false).'> aktivieren</label></td></tr>';
    }
    private static function tone_row($label, $key, $o) {
        $value = isset($o[$key]) ? $o[$key] : 'du';
        echo '<tr><th scope="row">'.esc_html($label).'</th><td>';
        echo '<label><input type="radio" name="wae_options['.esc_attr($key).']" value="du" '.checked($value, 'du', false).'> Du / Ihr</label><br>';
        echo '<label><input type="radio" name="wae_options['.esc_attr($key).']" value="sie" '.checked($value, 'sie', false).'> Sie / Ihre Gäste</label>';
        echo '<p class="description">Diese Auswahl steuert automatisch die Ansprache in den Landingpage-Texten, FAQ-Fragen, FAQ-Antworten und Buttons.</p>';
        echo '</td></tr>';
    }
    private static function shape_row($label, $key, $o) {
        $value = isset($o[$key]) ? $o[$key] : 'rounded';
        echo '<tr><th scope="row">'.esc_html($label).'</th><td>';
        echo '<label><input type="radio" name="wae_options['.esc_attr($key).']" value="rounded" '.checked($value, 'rounded', false).'> Rund / weich</label><br>';
        echo '<label><input type="radio" name="wae_options['.esc_attr($key).']" value="square" '.checked($value, 'square', false).'> Eckig / klar</label>';
        echo '<p class="description">Diese Auswahl steuert die optische Anmutung des Matchingtools. Das Matchingtool selbst ist fester Bestandteil der Trauredner-Seite und wird nicht separat deaktiviert. Wer diesen Service nicht anbieten möchte, überspringt Schritt 3.</p>';
        echo '</td></tr>';
    }
    private static function tri_row($label, $key, $o) {
        echo '<tr><th scope="row">'.esc_html($label).'</th><td>'; self::tri_control('wae_options['.$key.']', $o[$key] ?? 'unknown'); echo '</td></tr>';
    }
    private static function tri_inline($label, $name_suffix, $value) {
        echo '<div class="wae-tri-inline"><strong>'.esc_html($label).'</strong>'; self::tri_control('wae_options['.$name_suffix.']', $value); echo '</div>';
    }
    private static function tri_control($name, $value) {
        $opts = array('unknown'=>'Nicht angegeben','yes'=>'✅ Ja','no'=>'❌ Nein','request'=>'➖ Auf Anfrage');
        echo '<select name="'.esc_attr($name).'">';
        foreach ($opts as $k=>$label) { echo '<option value="'.esc_attr($k).'" '.selected($value, $k, false).'>'.esc_html($label).'</option>'; }
        echo '</select>';
    }
    private static function select_row($label, $key, $o, $choices) {
        echo '<tr><th scope="row">'.esc_html($label).'</th><td><select name="wae_options['.esc_attr($key).']">';
        $current = $o[$key] ?? '';
        foreach ($choices as $value => $label_text) {
            echo '<option value="'.esc_attr($value).'" '.selected($current, $value, false).'>'.esc_html($label_text).'</option>';
        }
        echo '</select></td></tr>';
    }
    private static function page_select_row($label, $key, $o) {
        $pages = get_pages(array('sort_column'=>'post_title','sort_order'=>'ASC'));
        echo '<tr><th scope="row">'.esc_html($label).'</th><td><select name="wae_options['.esc_attr($key).']"><option value="0">Bitte auswählen</option>';
        foreach ($pages as $page) { echo '<option value="'.esc_attr($page->ID).'" '.selected((int)($o[$key] ?? 0), $page->ID, false).'>'.esc_html($page->post_title).'</option>'; }
        echo '</select><p class="description">Empfohlen: Seite auswählen statt nur URL eintragen. Dadurch kann das Plugin auf genau dieser Seite automatisch strukturierte Daten ausgeben.</p></td></tr>';
    }
    private static function image_picker($label, $name, $id) {
        $url = $id ? wp_get_attachment_image_url((int)$id, 'thumbnail') : '';
        echo '<div class="wae-image-picker"><strong>'.esc_html($label).'</strong><br><input type="hidden" class="wae-image-id" name="'.esc_attr($name).'" value="'.esc_attr($id).'">';
        echo '<span class="wae-image-preview">'.($url ? '<img src="'.esc_url($url).'" alt="" />' : '').'</span> ';
        echo '<button type="button" class="button wae-select-image">Bild auswählen</button> <button type="button" class="button wae-remove-image">Entfernen</button></div>';
    }
}
