/home/edulekha/crm.edulekha.com/modules/appointly/helpers/appointly_google_helper.php
<?php

if (! function_exists('checkGoogleTwoWaySyncResults')) {
    /**
     * @param  array  $filters
     * @param $rResult
     * @param $output
     * @param  array  $result
     * @return array
     * @throws Exception
     */
    function checkGoogleTwoWaySyncResults(array $filters, $rResult, $output, array $result): array
    {
        $CI = get_instance();
        $googleData = [];
        $filteredResults = [];

        // Check if we're filtering for Google Calendar synced events
        $isGoogleCalendarFilter = !empty($CI->input->post('google_calendar_synced')) ||
            ($CI->input->post('custom_view') === 'google_calendar_synced');

        // Store the filter state in session for client-side access
        $CI->session->set_userdata('appointly_is_google_filter', $isGoogleCalendarFilter);

        // Get Google Calendar data regardless of filter
        if (appointlyGoogleAuth() && get_option('appointments_googlesync_show_in_table')) {
            $googleData = appointlyGetGoogleCalendarData();
        }

        if ($isGoogleCalendarFilter) {
            // For Google Calendar filter, we need to apply the same deduplication logic
            // Extract Google event IDs from database appointments to avoid duplicates
            $dbGoogleEventIds = [];
            foreach ($rResult as $appointment) {
                if (!empty($appointment['google_event_id'])) {
                    $dbGoogleEventIds[] = $appointment['google_event_id'];
                }
            }

            // Filter Google Calendar events to exclude those already in database
            $filteredGoogleData = array_filter($googleData, static function ($event) use ($dbGoogleEventIds) {
                // Keep only events that don't have matching google_event_id in database
                return !isset($event['id']) || ! in_array($event['id'], $dbGoogleEventIds);
            });
            $rResult = array_values($filteredGoogleData);

            // Apply search filtering
            $searchTerm = strtolower($CI->input->post('search')['value'] ?? '');
            if (trim($searchTerm) !== '') {
                $rResult = array_filter($rResult, static function ($row) use ($searchTerm) {
                    return stripos((string) $row['subject'], $searchTerm) !== false
                           || stripos((string) $row['description'], $searchTerm) !== false
                           || stripos((string) $row['creator_firstname'], $searchTerm) !== false;
                });
            }

            // Apply sorting
            $sortColumnIndex = $CI->input->post('order')[0]['column'] ?? -1;
            $sortDirection = $CI->input->post('order')[0]['dir'] ?? 'asc';

            $columnMap = [
                1 => 'subject',
                2 => 'date',
                3 => 'created_by',
                4 => 'description',
            ];

            $sortColumn = $columnMap[$sortColumnIndex] ?? 'date';

            usort($rResult, static function ($a, $b) use ($sortColumn, $sortDirection) {
                $dateA = isset($a['date']) ? strtotime($a['date']) : 0;
                $dateB = isset($b['date']) ? strtotime($b['date']) : 0;

                if ($sortColumn === 'date') {
                    $compareResult = $dateA - $dateB;
                } else {
                    $compareResult = strcasecmp(
                        (string)($a[$sortColumn] ?? ''),
                        (string)($b[$sortColumn] ?? '')
                    );
                    if ($compareResult === 0) {
                        $compareResult = $dateA - $dateB;
                    }
                }

                return ($sortDirection === 'asc') ? $compareResult : -$compareResult;
            });

            // Apply pagination
            $start = (int) $CI->input->post('start');
            $length = (int) $CI->input->post('length');

            $totalRecords = count($rResult);
            $rResult = array_slice($rResult, $start, $length);

            // Ensure proper DataTables format for AJAX response
            $output = [
                'draw' => (int) $CI->input->post('draw'),
                'recordsTotal' => $totalRecords,
                'recordsFiltered' => $totalRecords,
                'data' => array_values($rResult)
            ];

            return [$CI, $googleData, $rResult, $output, $rResult];
        }

        // Normal merge behavior for non-Google-filter view
        // If appointments_googlesync_show_in_table option is enabled, merge Google Calendar appointments
        if (!empty($googleData)) {
            // Extract Google event IDs from database appointments
            $dbGoogleEventIds = [];
            foreach ($rResult as $appointment) {
                if (!empty($appointment['google_event_id'])) {
                    $dbGoogleEventIds[] = $appointment['google_event_id'];
                }
            }
            // Filter out Google events that already exist in the database
            $filteredGoogleData = array_filter($googleData, function ($event) use ($dbGoogleEventIds) {
                // Keep only events that don't have matching google_event_id in database
                return !isset($event['id']) || ! in_array($event['id'], $dbGoogleEventIds);
            });

            $mergedData = array_merge($rResult, $filteredGoogleData);

            $uniqueMeetings = [];
            foreach ($mergedData as $meeting) {
                if (!isset($meeting['date'])) continue;

                // Create a more robust unique key that includes google_event_id if available
                if (!empty($meeting['google_event_id'])) {
                    $uniqueKey = 'google_' . $meeting['google_event_id'];
                } elseif (!empty($meeting['id']) && isset($meeting['source']) && $meeting['source'] === 'google') {
                    $uniqueKey = 'google_' . $meeting['id'];
                } else {
                    $uniqueKey = md5($meeting['subject'] . $meeting['date']);
                }

                if (!isset($uniqueMeetings[$uniqueKey])) {
                    $uniqueMeetings[$uniqueKey] = $meeting;
                }
            }

            $filteredResults = array_values($uniqueMeetings);
        }

        return [$CI, $googleData, $filteredResults, $output, $rResult];
    }
}


if (! function_exists('appointlyGetGoogleCalendarData')) {
    /**
     * Fetch Google Calendar Two-way Sync data
     *
     * @return array
     */
    function appointlyGetGoogleCalendarData()
    {
        $data = [];
        $CI = &get_instance();

        try {
            $CI->load->model('appointly/googlecalendar');
            $events = $CI->googlecalendar->getEvents();

            if (!$events) {
                log_message('error', 'Google Calendar: No events found or not authenticated');
                return [];
            }

            foreach ($events as $item) {
                // Get event ID without instance suffix for recurring events
                $eventId = explode('_', $item['id'])[0];

                // Format Google Calendar link
                $calendarLink = $item['htmlLink'];
                if (empty($calendarLink)) {
                    $calendarLink = 'https://calendar.google.com/calendar/u/0/r/eventedit/' . $eventId;
                }

                $data[] = [
                    'id' => $eventId,
                    'subject' => $item['summary'],
                    'description' => $item['description'],
                    'status' => $item['status'] ?? 'in-progress',
                    'creator_firstname' => $item['creator']->email ?? null,
                    'creator_lastname' => null,
                    'phone' => '',
                    'contact_email' => '',
                    'google_calendar_link' => $calendarLink,
                    'google_added_by_id' => null,
                    'outlook_calendar_link' => null,
                    'outlook_added_by_id' => null,
                    'feedback' => '',
                    'contact_id' => 0,
                    'created_by' => null,
                    'custom_status' => null,
                    'name' => null,
                    'from_2way_sync' => true,
                    'date' => !empty($item['start'])
                        ? date('Y-m-d H:i:s', strtotime($item['start']))
                        : null,
                    'start_hour' => !empty($item['start'])
                        ? date('H:i', strtotime($item['start']))
                        : '',
                    'source' => 'google',
                    'eventType' => $item['eventType'] ?? null,
                    'location' => $item['location'] ?? null,
                    'recurringEventId' => $item['recurringEventId'] ?? null
                ];
            }
        } catch (Exception $e) {
            log_message('error', 'Google Calendar Data Error: ' . $e->getMessage());
            return [];
        }

        return $data;
    }
}