<?php
/**
 * Apply categories created with ai service call in Termin-Kalender Plugin
 * 
 */

defined('ABSPATH') || exit;

// ter_kal_: Add REST route for updating calendar categories
add_action('rest_api_init', function () {
    // Apply categories to Termin-Kalender (requires edit permission)
    register_rest_route('termin-kalender-ai/v1', '/apply-categories', array(
        'methods' => 'POST',
        'callback' => 'termin_kalender_apply_categories_to_calendar',
        'permission_callback' => function () {
            return current_user_can('termin_kalender_edit');
        },
        'args' => array(
            'categories' => array(
                'required' => true,
                'type' => 'array',
                'validate_callback' => function ($param) {
                    return is_array($param) && count($param) > 0;
                },
            ),
        ),
    ));

    // ter_kal_: Added route for sending data to AI service
    register_rest_route('termin-kalender-ai/v1', '/send-to-service', array(
        'methods' => 'POST',
        'callback' => 'termin_kalender_send_to_ai_service',
        'permission_callback' => function () {
            return current_user_can('termin_kalender_edit');
        },
        'args' => array(
            'description' => array(
                'required' => true,
                'type' => 'string',
                'sanitize_callback' => 'sanitize_textarea_field',
            ),
        ),
    ));
});

// ter_kal_: Apply AI-generated categories to Termin-Kalender
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- 'ter_kal_' is the official project prefix for new code.
function termin_kalender_apply_categories_to_calendar(WP_REST_Request $request)
{

    $categories = $request->get_param('categories');
    $mode = isset($request['mode']) ? sanitize_text_field($request['mode']) : 'replace';
    $existing_categories = json_decode(get_option('termin_kalender_kategorien', '[]'), true);
    if (!is_array($existing_categories)) {
        $existing_categories = [];
    }

    if (!is_array($categories) || count($categories) < 1) {
        return new WP_REST_Response(array('message' => 'No categories provided.'), 400);
    }

    if (count($categories) > 40) {
        return new WP_REST_Response(array('message' => 'Too many categories (max 20).'), 400);
    }
    // ter_kal_: Convert AI categories to Termin-Kalender format
    $tk_categories = array_map(function ($cat) {
        // Whitelist icon to dashicons format only (dashicons-[a-z0-9-])
        $raw_icon = (string) ($cat['icon'] ?? '');
        $icon = preg_match('/^dashicons-[a-z0-9\-]+$/', $raw_icon) ? $raw_icon : 'dashicons-calendar';

        // Safe hex color fallback
        $bg = sanitize_hex_color((string) ($cat['backgroundColor'] ?? '')) ?: '#2271b1';
        $tc = sanitize_hex_color((string) ($cat['textColor'] ?? '')) ?: '#ffffff';

        return array(
            'categoryID' => sanitize_key((string) ($cat['categoryID'] ?? '')),
            'label' => sanitize_text_field((string) ($cat['label'] ?? '')),
            'backgroundColor' => $bg,
            'textColor' => $tc,
            'icon' => $icon,
        );
    }, $categories);


    if ($mode === 'append') {
        // Label-aware merge: existing categories are always kept as-is (ID preserved).
        // AI categories are only appended when their label doesn't already exist.
        // This prevents creating duplicate labels with new IDs, which would orphan
        // existing events that reference the original categoryID.
        $existing_labels = array_map(
            fn($c) => strtolower(trim($c['label'] ?? '')),
            $existing_categories
        );
        $merged = $existing_categories;
        foreach ($tk_categories as $new_cat) {
            $new_label = strtolower(trim($new_cat['label'] ?? ''));
            if ($new_label !== '' && !in_array($new_label, $existing_labels, true)) {
                $merged[] = $new_cat;
                $existing_labels[] = $new_label; // prevent duplicates within the AI batch itself
            }
        }
    } else {
        // ter_kal_: Replace mode (original behavior)
        $merged = $tk_categories;
    }

    // ter_kal_: Calculate how many events will become orphaned after this save.
    // An event is orphaned if its embedded categoryID is no longer in the $merged list.
    $merged_ids = array_column($merged, 'categoryID');
    $orphaned_count = 0;
    if (class_exists('Termin_Kalender_Event_Repository')) {
        $events = Termin_Kalender_Event_Repository::get_events();
    } else {
        $events = json_decode(get_option('termin_kalender_events', '[]'), true) ?: [];
    }
    if (is_array($events)) {
        foreach ($events as $event) {
            $ev_cat_id = $event['extendedProps']['category']['categoryID'] ?? '';
            if ($ev_cat_id !== '' && !in_array($ev_cat_id, $merged_ids, true)) {
                $orphaned_count++;
            }
        }
    }

    $updated = update_option('termin_kalender_kategorien', wp_json_encode($merged), false);

    if ($updated) {
        return new WP_REST_Response(array(
            'message'        => 'Categories successfully applied to Termin-Kalender.',
            'count'          => count($tk_categories),
            'orphaned_count' => $orphaned_count,
        ), 200);
    } else {
        return new WP_REST_Response(array('message' => 'Failed to update categories.'), 500);
    }

}

// ter_kal_: Send data to external AI service
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- 'ter_kal_' is the official project prefix for new code.
function termin_kalender_send_to_ai_service(WP_REST_Request $request)
{
    $description = $request->get_param('description');

    $is_pro = defined('TERMIN_KALENDER_PRO_ON');
    // ter_kal_: Get version from options
    $options = get_option('termin_kalender_options', array());
    $plugin_version = isset($options['termin_kalender_version']) ? $options['termin_kalender_version'] : '1.0.0';


    // ter_kal_: Prepare data payload
    $payload = array(
        'description' => $description,
        'license' => $is_pro,
        'version' => $plugin_version,
    );




    // ter_kal_: Get per-site shared secret from termin_kalender_options (simple setting)
    $options = get_option('termin_kalender_options', array());
    $service_secret = isset($options['ai_service_secret']) ? (string) $options['ai_service_secret'] : '';
    $service_secret = trim($service_secret);

    if ($service_secret === '') {
        // ter_kal_: ADDED - auto-generate and persist per-site secret (client-side)
        $service_secret = termin_kalender_generate_service_secret();

        $options['ai_service_secret'] = $service_secret;

        // ter_kal_: ADDED - persist back into existing options array
        $updated = update_option('termin_kalender_options', $options, false);

        // ter_kal_: ADDED - if we can't save, do not proceed with a transient secret
        if (!$updated) {
            if (defined('WP_DEBUG') && WP_DEBUG) {
                // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Intentional logging for AI API failures
                error_log('Termin-Kalender: Failed to persist ai_service_secret in termin_kalender_options');
            }
        }
    }

    // ter_kal_: Build signed request headers (HMAC)
    $timestamp = time();
    $nonce = wp_generate_password(16, false, false);

    $body_json = wp_json_encode($payload);
    $body_hash = hash('sha256', (string) $body_json);
    $site = rtrim(home_url(), '/');
    $canonical = $timestamp . "\n" . $nonce . "\n" . $site . "\n" . $body_hash;

    $response = wp_remote_post('https://termin-kalender.pro/wp-json/termin-kalender-ai/v1/calendar-categories', [
        'timeout' => 45,
        'headers' => [
            'Content-Type' => 'application/json',
            'User-Agent' => 'Termin-Kalender/' . $plugin_version . '; ' . home_url(),
            // ter_kal_: ADDED - signed service authentication headers
            'X-TK-Site' => $site,
            'X-TK-Timestamp' => (string) $timestamp,
            'X-TK-Nonce' => $nonce,
            'X-TK-Signature' => $service_secret,
        ],
        'body' => $body_json,
    ]);


    // ter_kal_: Handle response
    if (is_wp_error($response)) {
        return new WP_REST_Response(array(
            'message' => 'Failed to connect to AI service.',
            'error' => $response->get_error_message(),
        ), 500);
    }

    $body = wp_remote_retrieve_body($response);
    $data = json_decode($body, true);

    return new WP_REST_Response($data, wp_remote_retrieve_response_code($response));
}

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- 'ter_kal_' is the official project prefix for new code.
function termin_kalender_generate_service_secret()
{
    // ter_kal_: ADDED - prefer random_bytes when available
    if (function_exists('random_bytes')) {
        try {
            // 32 bytes => 64 hex chars
            return bin2hex(random_bytes(32));
        } catch (Exception $e) {
            // fall through to wp_generate_password
        }
    }

    // ter_kal_: ADDED - fallback (WP-native)
    return wp_generate_password(64, true, true);
}
