<?php
defined('ABSPATH') || exit;

class Termin_Kalender_REST_API
{
    private $namespace = 'termin-kalender/v1';

    public function __construct()
    {
        add_action('rest_api_init', [$this, 'register_routes']);
    }

    public function register_routes()
    {
        // ---------------- Events ----------------

        // GET /events
        register_rest_route($this->namespace, '/events', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_calendar_events'],
            'permission_callback' => '__return_true', // Lesender Zugriff
        ]);

        // POST /events
        register_rest_route($this->namespace, '/events', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'save_calendar_event'],
            'permission_callback' => [$this, 'check_edit_permission'],
        ]);

        // DELETE /events/{id}
        register_rest_route($this->namespace, '/events/(?P<id>[\w-]+)', [
            'methods' => WP_REST_Server::DELETABLE,
            'callback' => [$this, 'delete_calendar_event'],
            'permission_callback' => [$this, 'check_delete_permission'],
        ]);

        // ---------------- Categories ----------------

        // GET /categories
        register_rest_route($this->namespace, '/categories', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_categories'],
            'permission_callback' => '__return_true', // Lesender Zugriff
        ]);

        // POST /categories
        register_rest_route($this->namespace, '/categories', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'save_category'],
            'permission_callback' => [$this, 'check_edit_permission'],
        ]);

        // DELETE /categories/{id}
        register_rest_route($this->namespace, '/categories/(?P<id>[\w-]+)', [
            'methods' => WP_REST_Server::DELETABLE,
            'callback' => [$this, 'delete_category'],
            'permission_callback' => [$this, 'check_delete_permission'],
        ]);
    }

    // --- Permission Callbacks ---

    public function check_edit_permission()
    {
        return current_user_can('termin_kalender_edit');
    }

    public function check_delete_permission()
    {
        return current_user_can('termin_kalender_delete');
    }

    // --- Helpers ---

    private function get_events($include_archive = 0)
    {
        if (class_exists('Termin_Kalender_Event_Repository')) {
            return Termin_Kalender_Event_Repository::get_events($include_archive);
        }
        return [];
    }

    // --- Endpoints ---

    public function get_calendar_events(WP_REST_Request $request)
    {
        $include_archive = (int) $request->get_param('archive');
        $events = $this->get_events($include_archive);

        $can_edit = current_user_can('termin_kalender_edit') || current_user_can('manage_options');
        $can_view_team = $can_edit || current_user_can('termin_kalender_team');

        $filtered_events = [];
        foreach ($events as $event) {
            $event_id = $event['id'] ?? '';

            // Protect internal ticket events
            if (is_string($event_id)) {
                if (str_starts_with($event_id, 'todo-') || str_starts_with($event_id, 'teammessage-')) {
                    if (!$can_view_team) {
                        continue; // Hide from public
                    }
                }
            }

            // Protect private admin notes
            if (!$can_edit && isset($event['extendedProps']['notes'])) {
                unset($event['extendedProps']['notes']);
            }

            $filtered_events[] = $event;
        }

        return rest_ensure_response($filtered_events);
    }

    public function save_calendar_event(WP_REST_Request $request)
    {
        $id = $request->get_param('id') ? sanitize_text_field(wp_unslash($request->get_param('id'))) : null;
        $title = $request->get_param('title') ? sanitize_text_field(wp_unslash($request->get_param('title'))) : null;
        //--------------------------
        $start = $request->get_param('start') ? sanitize_text_field(wp_unslash($request->get_param('start'))) : null;
        $end = $request->get_param('end') ? sanitize_text_field(wp_unslash($request->get_param('end'))) : null;
        $until = $request->get_param('until') ? sanitize_text_field(wp_unslash($request->get_param('until'))) : null;
        $allday = $request->get_param('allDay') && sanitize_text_field(wp_unslash($request->get_param('allDay'))) === 'true'; // allDay nur setzen wenn checkbox gesetzt (true)
        //--------------------------
        $freq = $request->get_param('freq') ? sanitize_text_field(wp_unslash($request->get_param('freq'))) : '';
        $byweekday = $request->get_param('byweekday') ? sanitize_text_field(wp_unslash($request->get_param('byweekday'))) : '';  // als liste einlesen
        $exdate = $request->get_param('exdate') ? sanitize_text_field(wp_unslash($request->get_param('exdate'))) : '';
        $interval = $request->get_param('interval') ? max(1, absint(wp_unslash($request->get_param('interval')))) : 1;
        $bysetpos = $request->get_param('bysetpos') ? (int) sanitize_text_field(wp_unslash($request->get_param('bysetpos'))) : null;
        //--------------------------
        $details = $request->get_param('details') ? wp_kses_post(wp_unslash($request->get_param('details'))) : '';
        $notes = $request->get_param('notes') ? sanitize_text_field(wp_unslash($request->get_param('notes'))) : '';
        $location = $request->get_param('location') ? sanitize_text_field(wp_unslash($request->get_param('location'))) : '';
        $category = $request->get_param('category') ? sanitize_text_field(wp_unslash($request->get_param('category'))) : '';
        $textColor = $request->get_param('textColor') ? sanitize_text_field(wp_unslash($request->get_param('textColor'))) : '';
        $backgroundColor = $request->get_param('backgroundColor') ? sanitize_text_field(wp_unslash($request->get_param('backgroundColor'))) : '';
        //--------------------------
        $create_post = $request->get_param('create_post') ? sanitize_text_field(wp_unslash($request->get_param('create_post'))) : '';
        $post_link = $request->get_param('post_link') ? sanitize_text_field(wp_unslash($request->get_param('post_link'))) : '';
        //----------------------------------------------------------------------------------
        $events = $this->get_events();
        $categories = json_decode(get_option('termin_kalender_kategorien', '[]'), true);

        $category_data = [
            'backgroundColor' => '#3b82f6',
            'textColor' => '#ffffff',
            'icon' => 'dashicons-calendar-alt',
            'label' => (string) $category
        ];

        if (is_array($categories)) {
            foreach ($categories as $cat) {
                if (isset($cat['label']) && $cat['label'] === $category) {
                    $category_data = $cat;
                    break;
                }
            }
        }
        $id_group_id = $id ?: (string) uniqid();

        //---------------------------------------------------------------------------------------------------------
        try {
            if (class_exists('Termin_Kalender_Event_Posts_Main')) {
                $manager = new Termin_Kalender_Event_Posts_Main();
                $existing_post_id = $manager->get_post_by_uid($id_group_id);
                //---------------------------------------------------------------------------------------------------------
                $post_event_data = [
                    'title' => $title,
                    'description' => $details,
                    'start' => $start,
                    'end' => $end,
                    'until' => $until,
                    'allDay' => $allday,
                    'location' => $location,
                    'category' => $category,
                    'uid' => $id_group_id,
                    'freq' => $freq,
                    'byweekday' => $byweekday,
                    'exdate' => $exdate,
                    'interval' => $interval,
                    'bysetpos' => $bysetpos,
                    'textColor' => $category_data['textColor'],
                    'backgroundColor' => $category_data['backgroundColor'],
                    'icon' => $category_data['icon'],
                    'category_data' => $category_data,
                ];
                //--------------------------------------------------------
                if ($create_post === 'yes' && empty($existing_post_id)) {
                    $result = $manager->sync_event_to_post($post_event_data, 'new');
                    if (is_wp_error($result)) {
                        $notes .= ' -Fehler beim erstellen des Posts- ';
                        TK_Error_Handler::log(['level' => 'error', 'module' => 'Event Posts', 'message' => $result->get_error_message()]);
                    } else {
                        $post_link = $result['permalink'];
                        $notes .= ' -- Post erstellt: ' . $post_link . ' -- ';
                    }
                } elseif ($create_post === 'yes' && !empty($existing_post_id)) {
                    $result = $manager->sync_event_to_post($post_event_data, 'update');
                } elseif ($create_post !== 'yes' && !empty($post_link) && empty($existing_post_id)) {
                    $post_link = '';
                    $notes .= ' -- Post nicht gefunden – Link entfernt -- ';
                }
            }
        } catch (Throwable $e) {
            TK_Error_Handler::log(['level' => 'error', 'module' => 'Event Posts', 'message' => $e->getMessage()]);
        }
        //---------------------------------------------------------------------------

        $eventData = [
            'id' => $id_group_id,
            'groupId' => $id_group_id,
            'title' => $title,
            'start' => $start,
            'end' => $end,
            'textColor' => $textColor ?: $category_data['textColor'],
            'backgroundColor' => $backgroundColor ?: $category_data['backgroundColor'],
            'extendedProps' => [
                'details' => $details,
                'notes' => $notes,
                'category' => $category_data,
                'location' => $location,
                'post_link' => $post_link,
            ]
        ];

        if (!empty($freq)) {
            $eventData['extendedProps']['freq'] = $freq;
            $eventData['extendedProps']['until'] = $until;
            $eventData['extendedProps']['dtstart'] = $start;
            $eventData['extendedProps']['interval'] = $interval;
            $rrule = [
                'freq' => $freq,
                'until' => $until,
                'dtstart' => $start,
                'interval' => $interval,
            ];

            if (!empty($exdate)) {
                $exdate_array = explode(',', $exdate);
                if ($start && strpos($start, 'T') !== false) {
                    $timePart = substr($start, strpos($start, 'T'));
                    foreach ($exdate_array as &$d) {
                        if (strpos($d, 'T') === false) {
                            $d .= $timePart;
                        }
                    }
                    unset($d);
                }
                $eventData['exdate'] = $exdate_array;
                $eventData['extendedProps']['exdate'] = $exdate;
            }

            if ($freq === 'WEEKLY' || $freq === 'MONTHLY') {
                if (!empty($byweekday)) {
                    $eventData['extendedProps']['byweekday'] = $byweekday;
                    $rrule['byweekday'] = explode(',', $byweekday);
                }
                if (!empty($bysetpos)) {
                    $eventData['extendedProps']['bysetpos'] = $bysetpos;
                    $rrule['bysetpos'] = intval($bysetpos);
                    $weekdays = !empty($byweekday) ? explode(',', $byweekday) : [];
                    if (!empty($weekdays)) {
                        if (count($weekdays) > 1) {
                            $weekdays = [reset($weekdays)];
                        }
                        $eventData['extendedProps']['byweekday'] = $weekdays[0];
                        $rrule['byweekday'] = $weekdays;
                    }
                    unset($eventData['extendedProps']['interval'], $rrule['interval']);
                }
            }
            $eventData['rrule'] = $rrule;
        }

        if ($allday) {
            $eventData['allDay'] = $allday;
        }

        if ($id) {
            $existing_event = null;
            if (class_exists('Termin_Kalender_Event_Repository')) {
                $existing_event = Termin_Kalender_Event_Repository::get_event($id);
            }
            if ($existing_event) {
                if (!empty($freq)) {
                    if (!empty($existing_event['extendedProps']['dtstart'])) {
                        $dtstart = $existing_event['extendedProps']['dtstart'];
                        $existing_event['start'] = $dtstart;
                        $existing_event['extendedProps']['dtstart'] = $dtstart;
                        $existing_event['rrule']['dtstart'] = $dtstart;
                    }
                } else {
                    unset(
                        $existing_event['rrule'],
                        $existing_event['exdate'],
                        $existing_event['extendedProps']['rrule'],
                        $existing_event['extendedProps']['freq'],
                        $existing_event['extendedProps']['exdate'],
                        $existing_event['extendedProps']['dtstart'],
                        $existing_event['extendedProps']['bysetpos'],
                        $existing_event['extendedProps']['until'],
                        $existing_event['extendedProps']['byweekday'],
                        $existing_event['extendedProps']['interval']
                    );
                }
                if (!$allday) {
                    unset($existing_event['allDay']);
                }
                $existing_event = array_merge($existing_event, $eventData);
                if (class_exists('Termin_Kalender_Event_Repository')) {
                    Termin_Kalender_Event_Repository::save_event($existing_event);
                }
            } else {
                if (class_exists('Termin_Kalender_Event_Repository')) {
                    Termin_Kalender_Event_Repository::save_event($eventData);
                }
            }
        } else {
            if (class_exists('Termin_Kalender_Event_Repository')) {
                Termin_Kalender_Event_Repository::save_event($eventData);
            }
        }

        // Auto-resolve any linked To-Dos (e.g. from reservations) since the event was processed
        if (class_exists('Termin_Kalender_Todo_Data')) {
            $todos = Termin_Kalender_Todo_Data::get_all();
            foreach ($todos as $t) {
                if (!empty($t['linked_event_id']) && $t['linked_event_id'] === $id_group_id) {
                    if ($t['priority'] !== 'done') {
                        Termin_Kalender_Todo_Data::update($t['id'], ['priority' => 'done']);
                    }
                }
            }
        }

        return rest_ensure_response(['id' => $id_group_id, 'message' => esc_html__('New event saved successfully', 'termin-kalender')]);
    }

    public function delete_calendar_event(WP_REST_Request $request)
    {
        $event_id = $request->get_param('id') ? sanitize_text_field(wp_unslash($request->get_param('id'))) : '';

        if (!empty($event_id)) {
            if (class_exists('Termin_Kalender_Event_Repository')) {
                Termin_Kalender_Event_Repository::delete_event($event_id);
            }
            return rest_ensure_response(['success' => true]);
        }
        return new WP_Error('invalid_id', 'Invalid event ID.', ['status' => 400]);
    }

    public function get_categories(WP_REST_Request $request)
    {
        $categories = json_decode(get_option('termin_kalender_kategorien', '[]'), true);
        if (empty($categories)) {
            $categories = [
                [
                    'categoryID' => (string) uniqid(),
                    'backgroundColor' => '#0000FF',
                    'textColor' => '#FFFFFF',
                    'label' => 'Neue Kategorie',
                    'icon' => 'dashicons-plus'
                ]
            ];
            update_option('termin_kalender_kategorien', json_encode($categories), false);
        }
        return rest_ensure_response($categories);
    }

    public function save_category(WP_REST_Request $request)
    {
        // Überprüfung auf reservierte Kategorie-Namen (verhindert Konflikte mit To-Do & Teammessage Modulen)
        $label = $request->get_param('label') ? sanitize_text_field(wp_unslash($request->get_param('label'))) : '';
        $normalized_label = strtolower(str_replace([' ', '-', '_', '\''], '', $label));

        if (in_array($normalized_label, ['todo', 'todos', 'teammessage', 'teammessages'])) {
            return new WP_Error(
                'reserved_category_name',
                __('The names "To-Do" and "Team Message" are reserved for system modules. Please choose a different name.', 'termin-kalender'),
                ['status' => 400]
            );
        }

        $categories = json_decode(get_option('termin_kalender_kategorien', '[]'), true);
        $category = [
            'categoryID' => $request->get_param('categoryID') ? sanitize_text_field(wp_unslash($request->get_param('categoryID'))) : '',
            'backgroundColor' => $request->get_param('backgroundColor') ? sanitize_text_field(wp_unslash($request->get_param('backgroundColor'))) : '',
            'textColor' => $request->get_param('textColor') ? sanitize_text_field(wp_unslash($request->get_param('textColor'))) : '',
            'label' => $label,
            'icon' => $request->get_param('icon') ? sanitize_text_field(wp_unslash($request->get_param('icon'))) : ''
        ];

        if (empty($category['categoryID'])) {
            $category['categoryID'] = (string) uniqid();
        }

        $index = array_search($category['categoryID'], array_column($categories, 'categoryID'));
        if ($index !== false) {
            $categories[$index] = $category;
        } else {
            $categories[] = $category;
        }
        update_option('termin_kalender_kategorien', json_encode($categories), false);

        // ============================================================
        // ✅ Änderung: Events mit gleicher categoryID synchronisieren
        // ============================================================
        // Kommentar: Wir matchen über extendedProps.category.categoryID
        // Kommentar: und updaten extendedProps.category komplett + event textColor/backgroundColor.
        try {
            if (class_exists('TK_Error_Handler') && TK_Error_Handler::is_module_disabled('category-updater')) {
                return rest_ensure_response(['success' => true]);
            }

            $all_events = $this->get_events();

            if (!is_array($all_events)) {
                $all_events = [];
            }

            $changed_events = 0;
            $target_category_id = (string) $category['categoryID'];

            foreach ($all_events as &$event) {
                if (!is_array($event)) {
                    continue;
                }

                $event_id = $event['id'] ?? ($event['uid'] ?? '');
                $extendedProps = $event['extendedProps'] ?? [];

                if (!is_array($extendedProps)) {
                    continue;
                }

                $event_category = $extendedProps['category'] ?? null;
                $event_category_id = '';

                if (is_array($event_category) && isset($event_category['categoryID'])) {
                    $event_category_id = (string) $event_category['categoryID'];
                }

                if ($event_category_id !== $target_category_id) {
                    continue;
                }

                // ✅ 1) entire category array ersetzen
                $extendedProps['category'] = $category;

                // ✅ 2) oberste Ebene syncen
                $event['textColor'] = sanitize_text_field($category['textColor'] ?? '');
                $event['backgroundColor'] = sanitize_text_field($category['backgroundColor'] ?? '');

                // ✅ zurückschreiben
                $event['extendedProps'] = $extendedProps;

                // ✅ speichern
                if (!empty($event_id) && class_exists('Termin_Kalender_Event_Repository')) {
                    Termin_Kalender_Event_Repository::save_event($event);
                    $changed_events++;
                }
            }
            unset($event);

            if (class_exists('TK_Error_Handler') && $changed_events > 0) {
                TK_Error_Handler::log([
                    'level' => 'notice',
                    'module' => 'category-updater',
                    'message' => 'Resynced events after category update: ' . (string) $changed_events,
                    'file' => __FILE__,
                    'line' => __LINE__,
                ]);
            }
        } catch (Throwable $e) {
            if (class_exists('TK_Error_Handler')) {
                TK_Error_Handler::log([
                    'level' => 'error',
                    'module' => 'category-updater',
                    'message' => $e->getMessage(),
                    'file' => $e->getFile(),
                    'line' => $e->getLine(),
                ]);
            }
            // Kommentar: keine throw -> Plugin läuft weiter
        }
        //----------------------------------------------------------

        return rest_ensure_response(['success' => true]);
    }

    public function delete_category(WP_REST_Request $request)
    {
        $categoryID = $request->get_param('id') ? sanitize_text_field(wp_unslash($request->get_param('id'))) : '';
        if (empty($categoryID)) {
            return new WP_Error('invalid_id', 'Invalid category ID.', ['status' => 400]);
        }

        $categories = json_decode(get_option('termin_kalender_kategorien', '[]'), true);
        $categories = array_filter($categories, function ($cat) use ($categoryID) {
            return $cat['categoryID'] !== $categoryID;
        });
        update_option('termin_kalender_kategorien', json_encode(array_values($categories)), false);

        // ter_kal_: Count events that were referencing this now-deleted category.
        // We count BEFORE deletion is visible to any cache, but AFTER saving the new list,
        // so the count accurately reflects newly-orphaned events.
        $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 === $categoryID) {
                    $orphaned_count++;
                }
            }
        }

        return rest_ensure_response([
            'success'        => true,
            'orphaned_count' => $orphaned_count,
        ]);
    }

}
