/home/edulekha/crm.edulekha.com/modules/appointly/views/tables/index.php
<?php

defined('BASEPATH') or exit('No direct script access allowed');

$aColumns = [
  // db_prefix() . 'appointly_appointments.id as id',
  db_prefix() . 'appointly_appointments.subject as subject',
  'CAST(CONCAT(' . db_prefix() . 'appointly_appointments.date, \' \', '
    . db_prefix() . 'appointly_appointments.start_hour) AS DATETIME) as date',
  'firstname as creator_firstname',
  db_prefix() . 'appointly_appointments.service_id as service_id',
  db_prefix() . 'appointly_appointments.provider_id as provider_id',
  db_prefix() . 'appointly_appointments.status as status',
  db_prefix() . 'appointly_appointments.date_created as date_created',
  db_prefix() . 'appointly_appointments.id as id',
];

$sIndexColumn = 'subject';
$sTable       = db_prefix() . 'appointly_appointments';

$join = [
  'LEFT JOIN ' . db_prefix() . 'staff ON ' . db_prefix() . 'staff.staffid = '
    . db_prefix() . 'appointly_appointments.created_by',
  'LEFT JOIN ' . db_prefix() . 'appointly_services ON ' . db_prefix()
    . 'appointly_services.id = ' . db_prefix() . 'appointly_appointments.service_id',
  'LEFT JOIN ' . db_prefix() . 'clients ON ' . db_prefix() . 'clients.userid = ' . db_prefix() . 'appointly_appointments.contact_id',
  'LEFT JOIN ' . db_prefix() . 'leads ON ' . db_prefix() . 'leads.id = ' . db_prefix() . 'appointly_appointments.contact_id',
];

$additionalSelect = [
  db_prefix() . 'appointly_appointments.source as source',
  db_prefix() . 'appointly_appointments.date as appointment_date',
  db_prefix() . 'appointly_appointments.created_by as created_by',
  'lastname as creator_lastname',
  db_prefix() . 'appointly_appointments.name as name',
  db_prefix() . 'appointly_services.name as service_name',
  db_prefix() . 'appointly_services.color as service_color',
  db_prefix() . 'appointly_services.price as service_price',
  db_prefix() . 'appointly_appointments.contact_id as contact_id',
  db_prefix() . 'appointly_appointments.google_calendar_link',
  db_prefix() . 'appointly_appointments.outlook_calendar_link',
  db_prefix() . 'appointly_appointments.feedback',
  db_prefix() . 'appointly_appointments.email as contact_email',
  db_prefix() . 'appointly_appointments.phone as phone',
  db_prefix() . 'appointly_appointments.google_event_id',
  db_prefix() . 'appointly_appointments.outlook_event_id',
  db_prefix() . 'appointly_appointments.outlook_added_by_id',
  db_prefix() . 'appointly_appointments.description',
  db_prefix() . 'appointly_appointments.start_hour',
  db_prefix() . 'appointly_appointments.recurring',
  db_prefix() . 'appointly_appointments.recurring_type',
  db_prefix() . 'appointly_appointments.repeat_every',
  db_prefix() . 'appointly_appointments.cycles',
  db_prefix() . 'appointly_appointments.total_cycles'
];

$where = [];

// Check if user has any appointments permissions at all
if (!staff_can('view', 'appointments')) {
  $where[] = 'AND 1=0'; // No permissions = no results
} elseif (! is_admin()) {
  // Non-admin staff can only see appointments they're connected to:
  // 1. Created by them, 2. Assigned as provider, 3. Listed as attendee
  $where[] = 'AND (' . db_prefix() . 'appointly_appointments.created_by='
    . get_staff_user_id() . '
    OR ' . db_prefix() . 'appointly_appointments.provider_id=' . get_staff_user_id() . '
    OR ' . db_prefix() . 'appointly_appointments.id
    IN (SELECT appointment_id FROM ' . db_prefix()
    . 'appointly_attendees WHERE staff_id=' . get_staff_user_id() . '))';
}

$filters = createFilters();

if (count($filters) > 0) {
  $where[] = 'AND (' . prepare_dt_filter($filters) . ')';
}

$result  = data_tables_init(
  $aColumns,
  $sIndexColumn,
  $sTable,
  $join,
  $where,
  $additionalSelect
);

$output  = $result['output'];
$rResult = $result['rResult'];

[
  $CI,
  $googleData,
  $filteredResults,
  $output,
  $rResult,
]
  = checkGoogleTwoWaySyncResults(
    $filters,
    $rResult,
    $output,
    $result
  );
foreach ($rResult as $aRow) {

  $row = [];

  $googleLink = $aRow['google_calendar_link'] ?? '';

  $subjectHtml = '<div class="tw-flex tw-flex-col tw-group">';

  $subjectHtml .= '<div class="tw-flex tw-items-center tw-gap-2">';

  // Calendar badges with links 
  if (isset($aRow['google_event_id']) && $aRow['google_event_id']    || !empty($aRow['from_2way_sync'])) {
    $subjectHtml .= '<a href="' . $aRow['google_calendar_link'] . '"
        target="_blank" 
        class="tw-text-[#4285f4] hover:tw-opacity-80" 
        data-toggle="tooltip" 
        title="' . _l('appointment_view_in_calendar') . '">
        <i class="fa-brands fa-google" style="color:#4285F4"></i>
    </a>';
  }

  if (isset($aRow['outlook_event_id'])    && $aRow['outlook_added_by_id'] == get_staff_user_id()) {
    $subjectHtml .= '<a href="' . $aRow['outlook_calendar_link'] . '"
                        target="_blank" 
                        class="tw-text-[#00a1f1] hover:tw-opacity-80" 
                        data-toggle="tooltip" 
                        title="' . _l('appointments_outlook_view_in_calendar') . '">
                        <i class="fa fa-envelope tw-text-primary-500"></i>
                    </a>';
  }

  // Recurring badge
  if (isset($aRow['recurring']) && $aRow['recurring'] == 1) {
    $recurring_text = '';
    if (!empty($aRow['recurring_type']) && !empty($aRow['repeat_every'])) {
      $recurring_text = _l('recurring_every') . ' ' . $aRow['repeat_every'] . ' ' . _l('recurring_' . $aRow['recurring_type']);
      if (!empty($aRow['cycles']) && $aRow['cycles'] > 0) {
        $recurring_text .= ' (' . $aRow['total_cycles'] . '/' . $aRow['cycles'] . ')';
      } else {
        $recurring_text .= ' (' . _l('cycles_infinity') . ')';
      }
    } else {
      $recurring_text = _l('recurring_appointment');
    }
    $subjectHtml .= '<span class="tw-inline-flex tw-items-center tw-py-0.5 tw-rounded tw-text-xs tw-font-medium tw-bg-purple-100 tw-text-purple-800" data-toggle="tooltip" title="' . e($recurring_text) . '">
      <i class="fa fa-repeat tw-mr-1"></i>' . _l('recurring') . '
    </span>';
  }

  // Subject text (clickable link to view appointment)
  if (staff_can('view', 'appointments')) {
    $subjectHtml .= '<a href="' . admin_url('appointly/appointments/view?appointment_id=' . (int)$aRow['id']) . '" class="tw-font-medium hover:tw-text-primary-600 tw-transition-colors">' . e($aRow['subject']) . '</a>';
  } else {
    $subjectHtml .= '<span class="tw-font-medium">' . e($aRow['subject']) . '</span>';
  }
  $subjectHtml .= '</div>';

  $subjectHtml .= '<div class="row-options tw-mt-1 tw-text-xs">';

  // Check if it's a Google synced appointment
  if (!empty($aRow['from_2way_sync'])) {
    // For Google synced appointments, show View in Google Calendar and Delete options
    $subjectHtml .= '<a href="' . $aRow['google_calendar_link'] . '" target="_blank" class="tw-text-blue-600 hover:tw-text-blue-800 tw-no-underline">' . _l('appointment_open_google_calendar') . '</a>';

    // Add delete button for Google synced appointments
    if (staff_can('delete', 'appointments')) {
      // Extract Google event ID from calendar link if needed
      $googleEventId = $aRow['google_event_id'] ?? '';

      // If no direct event ID, extract from google_calendar_link
      if (empty($googleEventId) && !empty($aRow['google_calendar_link'])) {
        // Extract event ID from eid parameter in Google Calendar URL
        if (preg_match('/[?&]eid=([^&]+)/', $aRow['google_calendar_link'], $matches)) {
          $decodedEid = base64_decode($matches[1]);
          // Extract the event ID (before the first space and underscore)
          if (strpos($decodedEid, ' ') !== false) {
            $googleEventId = explode(' ', $decodedEid)[0];
          } elseif (strpos($decodedEid, '_') !== false) {
            $googleEventId = explode('_', $decodedEid)[0];
          } else {
            $googleEventId = $decodedEid;
          }
        }
        // Alternative: try to extract from cid parameter
        elseif (preg_match('/[?&]cid=([^&]+)/', $aRow['google_calendar_link'], $matches)) {
          $googleEventId = urldecode($matches[1]);
        }
        // Fallback: use appointment ID if no Google event ID found
        if (empty($googleEventId)) {
          $googleEventId = $aRow['id'];
        }
      }

      // Use appointment ID as fallback if still empty
      if (empty($googleEventId)) {
        $googleEventId = $aRow['id'];
      }

      $subjectHtml .= ' <span class="tw-text-gray-300">|</span> <a href="javascript:void(0);" class="tw-text-red-600 hover:tw-text-red-800 tw-no-underline" data-google-event-id="' . e($googleEventId) . '" onclick="deleteGoogleSyncedAppointment(this)">
          <i class="fa fa-trash tw-mr-1"></i>' . _l('delete') . '</a>';
    }
  } else {
    // Regular appointment options
    if (staff_can('view', 'appointments')) {
      $subjectHtml .= '<a href="' . admin_url('appointly/appointments/view?appointment_id=' . (int)$aRow['id']) . '" class="tw-text-gray-600 hover:tw-text-gray-800 tw-no-underline">
          <i class="fa fa-eye tw-mr-1"></i>' . _l('view') . '</a>';
    }
    if (staff_can('edit', 'appointments')) {
      $subjectHtml .= ' <span class="tw-text-gray-300">|</span> <a href="' . admin_url('appointly/appointments/update_page/' . (int)$aRow['id']) . '" class="tw-text-indigo-600 hover:tw-text-indigo-800 tw-no-underline">
          <i class="fa fa-edit tw-mr-1"></i>' . _l('edit') . '</a>';
    }

    $task_data = [
      'id'           => (int)$aRow['id'],
      'name'         => e($aRow['name']),
      'subject'      => e($aRow['subject']),
      'description'  => e($aRow['description'] ?? ''),
      'date'         => _dt($aRow['date']),
      'contact_id'   => (int)$aRow['contact_id'],
      'email'        => e($aRow['contact_email']),
      'phone'        => e($aRow['phone']),
      'created_by'   => (int)$aRow['created_by'],
      'service_name' => e($aRow['service_name'] ?? ''),
      'service_price' => (float)($aRow['service_price'] ?? 0),
    ];

    $subjectHtml .= ' <span class="tw-text-gray-300">|</span> <a href="#" onclick="new_task_from_relation_appointment(' . html_escape(json_encode($task_data)) . '); return false;" class="tw-text-green-600 hover:tw-text-green-800 tw-no-underline">
        <i class="fa fa-tasks tw-mr-1"></i>' . _l('new_task') . '
    </a>';

    // Only show "Convert to Lead" for external appointments (not internal contacts)
    if ($aRow['source'] === 'external') {
      $lead_data = [
        'id'          => (int)$aRow['id'],
        'name'        => e($aRow['name']),
        'email'       => e($aRow['contact_email']),
        'phone'       => e($aRow['phone']),
        'description' => e($aRow['description'] ?? ''),
        'subject'     => e($aRow['subject']),
        'address'     => e($aRow['address'] ?? ''),
        'city'        => e($aRow['city'] ?? ''),
        'state'       => e($aRow['state'] ?? ''),
        'country'     => e($aRow['country'] ?? ''),
        'zip'         => e($aRow['zip'] ?? ''),
        'source'      => e($aRow['source']),
        'contact_id'  => (int)$aRow['contact_id'],
        'service_name' => e($aRow['service_name'] ?? ''),
        'date'        => _dt($aRow['date']),
      ];

      $subjectHtml .= ' <span class="tw-text-gray-300">|</span> <a href="#" 
              class="tw-text-purple-600 hover:tw-text-purple-800 tw-no-underline" 
              onclick="init_appointment_lead(' . html_escape(json_encode($lead_data)) . '); return false;">
              <i class="fa fa-user-plus tw-mr-1"></i>' . _l('appointments_convert_to_lead_label') . '
          </a>';
    }

    if (staff_can('delete', 'appointments')) {
      $subjectHtml .= ' <span class="tw-text-gray-300">|</span> <a href="javascript:void(0);" class="tw-text-red-600 hover:tw-text-red-800 tw-no-underline" onclick="deleteAppointment(\'' . (int)$aRow['id'] . '\', this)">
          <i class="fa fa-trash tw-mr-1"></i>' . _l('delete') . '</a>';
    }
  }

  $subjectHtml .= '</div>';
  $subjectHtml .= '</div>';
  $row[]       = $subjectHtml;

  $dateClass = getDateStatusClass($aRow['date'], $aRow['status']);
  $dateHtml = '<div class="tw-flex tw-items-center tw-gap-2">
      <span class="tw-w-2 tw-h-2 tw-rounded-md ' . $dateClass . ' tw-mr-2"></span>
      <div class="tw-flex tw-flex-col">
          <span class="tw-text-sm">' . _dt($aRow['date']) . '</span>';

  // Add "Upcoming" badge for future in-progress appointments
  if (isAppointmentUpcoming($aRow)) {
    $dateHtml .= '<span class="tw-inline-flex tw-items-center tw-px-2 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-blue-100 tw-text-blue-800 tw-mt-1">
          <i class="fa fa-clock tw-mr-1"></i>' . _l('appointment_upcoming') . '
      </span>';
  }

  $dateHtml .= '</div>
  </div>';
  $row[] = $dateHtml;

  $initiatedBy = $aRow['creator_firstname'] . ' ' . $aRow['creator_lastname'];

  if ($aRow['source'] == 'external' && empty($aRow['created_by'])) {
    $initiatedBy .= '<span class="tw-text-xs tw-font-medium tw-text-neutral-500">' . e($aRow['name']) . '</span>';
    $row[] = '<div class="tw-flex tw-items-center">
      <span class="tw-text-sm">' . $initiatedBy . '</span>
    </div>';
  } else {
    $row[] = '<div class="tw-flex tw-items-center">
      <a target="_blank" href="' . admin_url('staff/profile/' . (int)$aRow['created_by']) . '">
        <img src="' . staff_profile_image_url($aRow['created_by'], 'small') . '"
             class="tw-w-8 tw-h-8 tw-rounded-md tw-mr-2" alt="' . e($initiatedBy) . '"/>
        <span class="tw-text-sm tw-font-medium">' . e($initiatedBy) . '</span>
      </a>
    </div>';
  }

  // Service with clean badge
  if (isset($aRow['service_id'])) {
    $serviceClass = e($aRow['service_color'] ?? 'tw-bg-neutral-50');
    $row[] = '<a target="_blank" href="' . admin_url(APPOINTLY_MODULE_NAME . '/services/service/' . (int)$aRow['service_id']) . '">
        <span class="tw-px-2 tw-py-1 tw-text-xs tw-rounded-md tw-text-white" style="background-color: ' . $serviceClass . ';">' . e($aRow['service_name'] ?? 'N/A') . '</span>
    </a>';
  } else {
    $row[] = '<span class="tw-px-2 tw-py-1 tw-text-xs tw-font-medium tw-rounded-md tw-bg-neutral-50 tw-text-neutral-700">N/A</span>';
  }

  // Provider with avatar
  $provider_id   = $aRow['provider_id'] ?? '';
  $provider_name = '';
  if (empty($provider_id)) {
    $row[] = '<span class="tw-px-2 tw-py-1 tw-text-xs tw-font-medium tw-rounded-md tw-bg-neutral-50 tw-text-neutral-700">N/A</span>';
  } else {
    $provider      = get_staff($provider_id);
    $provider_name = $provider ? $provider->firstname . ' ' . $provider->lastname : '';
    $row[]         = '<div class="tw-flex tw-items-center">
        <a target="_blank" href="' . admin_url('staff/profile/' . (int)$provider_id) . '">
            <img src="' . staff_profile_image_url($provider_id) . '"
                 class="tw-w-8 tw-h-8 tw-rounded-md tw-mr-2" alt="' . e($provider_name) . '" />
            <span class="tw-text-sm tw-font-medium">' . e($provider_name) . '</span>
        </a>
    </div>';
  }

  // Source with badge
  $sourceLabels = [
    'internal'        => '<span class="tw-px-2 tw-py-1 tw-text-xs tw-font-medium tw-rounded-md tw-bg-info-50 tw-text-primary-500">' . _l('appointment_source_internal_client') . '</span>',
    'internal_staff'  => '<span class="tw-px-2 tw-py-1 tw-text-xs tw-font-medium tw-rounded-md tw-bg-info-50 tw-text-neutral-700">' . _l('appointment_internal_staff') . '</span>',
    'lead_related'    => '<span class="tw-px-2 tw-py-1 tw-text-xs tw-font-medium tw-rounded-md tw-bg-info-50 tw-text-info-700">' . _l('appointment_source_lead') . '</span>',
    'external'        => '<span class="tw-px-2 tw-py-1 tw-text-xs tw-font-medium tw-rounded-md tw-bg-info-50 tw-text-neutral-700">' . _l('appointment_source_external_text') . '</span>',
    'google_calendar' => '<span class="tw-px-2 tw-py-1 tw-text-xs tw-font-medium tw-rounded-md tw-bg-info-50 tw-text-info-700">' . _l('appointly_google_synced_title') . '</span>',
  ];

  // Determine the source label with client/lead info
  $sourceHtml = '';

  if (!empty($aRow['from_2way_sync'])) {
    $sourceHtml = $sourceLabels['google_calendar'];
  } elseif ($aRow['source'] == 'external' && empty($aRow['created_by'])) {
    $sourceHtml = '<span class="tw-px-2 tw-py-1 tw-text-xs tw-font-medium tw-rounded-md tw-bg-info-50 tw-text-neutral-700">' . _l('appointment_booked_from_external_booking_form') . '</span>';
  } else {
    $sourceHtml = $sourceLabels[$aRow['source']] ?? $sourceLabels['internal'];
  }

  // Add client/lead name if available
  if (!empty($aRow['name']) && in_array($aRow['source'], ['internal', 'lead_related', 'external'])) {
    if ($aRow['source'] == 'internal' && !empty($aRow['contact_id'])) {
      // Add link to client's contact profile
      $sourceHtml .= '<div class="tw-mt-1 tw-text-xs tw-font-medium">
        <a href="' . admin_url('clients/client/' . get_user_id_by_contact_id($aRow['contact_id']) . '?contactid=' . (int)$aRow['contact_id']) . '" target="_blank" class="tw-text-primary-700 hover:tw-underline" title="' . _l('view') . '" data-toggle="tooltip">
          ' . e($aRow['name']) . '
        </a>
      </div>';
    } else if ($aRow['source'] == 'lead_related' && !empty($aRow['contact_id'])) {
      // Add link to lead profile
      $sourceHtml .= '<div class="tw-mt-1 tw-text-xs tw-font-medium">
        <a href="' . admin_url('leads/index/' . (int)$aRow['contact_id']) . '" target="_blank" class="tw-text-primary-700 hover:tw-underline" title="' . _l('view') . '" data-toggle="tooltip">
          ' . e($aRow['name']) . '
        </a>
      </div>';
    } else {
      // Default display for external sources or when no contact_id is available
      $sourceHtml .= '<div class="tw-mt-1 tw-text-xs tw-font-medium">' . e($aRow['name']) . '</div>';
    }
  }

  // For "Booking From" external sources
  if ($aRow['source'] == 'external' && !empty($aRow['email'])) {
    if (!empty($aRow['name'])) {
      $sourceHtml .= '<div class="tw-mt-1 tw-text-xs tw-text-muted">(' . e($aRow['email']) . ')</div>';
    } else {
      $sourceHtml .= '<div class="tw-mt-1 tw-text-xs tw-font-medium">' . e($aRow['email']) . '</div>';
    }
  }

  $row[] = '<div class="tw-flex tw-flex-col">' . $sourceHtml . '</div>';

  $row[] = getStatusHtml($aRow);
  $row[] = '<span class="tw-text-sm">' . _dt($aRow['date_created'] ??
    $aRow['date']) . '</span>';

  // Add row class for past appointments and negative statuses
  $row['DT_RowClass'] = 'has-row-options';

  // Check if appointment is in the past or has negative status
  $is_past = false;
  if (!empty($aRow['date'])) {
    $timestamp = strtotime($aRow['date']);
    if ($timestamp !== false && $timestamp < time()) {
      $is_past = true;
    }
  }

  $is_negative_status = in_array($aRow['status'], ['cancelled', 'no-show']);

  if ($is_past || $is_negative_status) {
    $row['DT_RowClass'] .= ' past-appointment-row';
  }

  $output['aaData'][] = $row;
}


// Helper functions
function getDateStatusClass($date, $status = null)
{
  if (empty($date)) {
    return 'tw-bg-neutral-50';
  }

  // Check for status-based coloring first (no-show, cancelled, missed)
  if (!empty($status) && in_array($status, ['no-show', 'cancelled'])) {
    return 'tw-bg-red-500';
  }

  // Safely convert to string and handle null/empty values
  $timestamp = is_string($date) || is_numeric($date) ? strtotime((string) $date) : false;
  if ($timestamp === false) {
    return 'tw-bg-neutral-50';
  }

  $now  = time();
  $diff = $timestamp - $now;

  if ($diff < 0) {
    return 'tw-bg-red-500'; // Past/missed appointments
  } elseif ($diff < 24 * 3600) {
    return 'tw-bg-amber-500';
  } elseif ($diff < 7 * 24 * 3600) {
    return 'tw-bg-blue-500';
  } else {
    return 'tw-bg-green-500';
  }
}


function getStatusHtml($aRow)
{
  // Check if this is a Google synced appointment
  $isGoogleSynced = !empty($aRow['from_2way_sync']);

  if ($isGoogleSynced) {
    // For Google synced appointments, determine status based on date
    $timestamp = !empty($aRow['date']) ? strtotime((string) $aRow['date']) : false;
    $now = time();

    if ($timestamp === false || $timestamp > $now) {
      $statusClass = 'tw-bg-info-50 tw-text-info-700';
      $statusText = _l('appointment_upcoming');
    } else {
      $statusClass = 'tw-bg-danger-200';
      $statusText = _l('appointment_missed_label');
    }

    // Return a read-only badge for Google synced appointments
    return '<div class="tw-inline-block">
              <span class="tw-p-3 tw-py-1 tw-text-sm tw-rounded-md ' . $statusClass . '">
                ' . $statusText . '
              </span>
            </div>';
  }

  // For regular appointments
  if (staff_can('edit', 'appointments')) {
    // Get status text and HTML version for display
    $currentStatus = checkAppointlyStatus($aRow); // Text version for dropdown label
    $statusHtml = checkAppointlyStatus($aRow, 'html'); // HTML version for read-only display

    // Get status color class
    $statusClass = '';

    // Get status color class based on appointment status
    switch ($aRow['status']) {
      case 'cancelled':
        $statusClass = 'tw-bg-danger-200 tw-text-danger-700';
        break;
      case 'completed':
      case 'finished':
        $statusClass = 'tw-bg-success-50 tw-text-success-700';
        break;
      case 'in-progress':
        $statusClass = 'tw-bg-primary-50 tw-text-primary-700';
        break;
      case 'pending':
        $statusClass = 'tw-bg-warning-50 tw-text-warning-700';
        break;
      case 'approved':
        $statusClass = 'tw-bg-success-50 tw-text-success-700';
        break;
      case 'no-show':
        $statusClass = 'tw-bg-danger-200 tw-text-danger-700';
        break;
      default:
        $statusClass = 'tw-bg-neutral-50 tw-text-neutral-700';
    }

    // Is the appointment completed? If so, don't create a dropdown
    $isCompleted = $aRow['status'] == 'completed';

    if ($isCompleted) {
      // For completed appointments, just show a badge - no dropdown
      return '<div class="tw-inline-block">
                <span class="tw-px-3 tw-py-1 tw-text-sm tw-font-medium tw-rounded-md ' . $statusClass . '">
                  ' . $currentStatus . '
                </span>
              </div>';
    }

    // For other statuses, create a dropdown
    $outputStatus = '<div class="dropdown tw-inline-block ' . (!empty($aRow['from_2way_sync']) ? 'google-synced-disabled' : '') . '">';

    $outputStatus .= '<a href="#" class="tw-px-3 tw-py-1 tw-text-sm tw-font-medium tw-rounded-md '
      . $statusClass . ' hover:tw-opacity-80 tw-inline-flex tw-items-center"
                            id="appointmentStatusesDropdown' . $aRow['id'] . '"
                            data-toggle="dropdown"
                            aria-haspopup="true"
                            aria-expanded="false">';
    $outputStatus .= $currentStatus;
    $outputStatus .= '<i class="fa fa-caret-down tw-ml-2"></i>';
    $outputStatus .= '</a>';

    // Show dropdown menu with available actions
    $outputStatus .= '<ul class="dropdown-menu tw-py-2 tw-min-w-[160px] tw-mt-1 tw-bg-white tw-shadow-lg tw-rounded-lg tw-border tw-border-neutral-200"
                                aria-labelledby="appointmentStatusesDropdown'
      . $aRow['id'] . '">';

    // Use universal status to determine available actions
    $currentStatusValue = $aRow['status'];

    // Needs approval
    if ($currentStatusValue == 'pending' && staff_can('approve', 'appointments')) {
      $outputStatus .= '<li>
      <a href="#" class="tw-px-4 tw-py-2 tw-text-sm tw-text-neutral-700 hover:tw-bg-neutral-50 tw-block"
        onclick="markAppointmentAsApproved(' . $aRow['id'] . '); return false;">' . _l('appointment_approve') . '</a></li>';
    }

    // Can be cancelled
    if (
      $currentStatusValue != 'cancelled' && $currentStatusValue != 'completed'
      && (staff_can('edit', 'appointments') || $aRow['created_by'] == get_staff_user_id() || in_array(get_staff_user_id(), explode(',', $aRow['attendees'])))
    ) {
      $outputStatus .= '<li>
      <a href="#" class="tw-px-4 tw-py-2 tw-text-sm tw-text-neutral-700 hover:tw-bg-neutral-50 tw-block"
       onclick="markAppointmentAsCancelled(' . $aRow['id'] . '); return false;">' . _l('task_mark_as', _l('appointment_status_cancelled')) . '</a></li>';
    }

    // Can be finished
    if (
      $currentStatusValue != 'completed' && $currentStatusValue != 'cancelled' &&
      $currentStatusValue == 'in-progress' &&
      (staff_can('edit', 'appointments') || $aRow['created_by'] == get_staff_user_id() || in_array(get_staff_user_id(), explode(',', $aRow['attendees'])))
    ) {
      $outputStatus .= '<li>
      <a href="#" class="tw-px-4 tw-py-2 tw-text-sm tw-text-neutral-700 hover:tw-bg-neutral-50 tw-block" 
       onclick="markAppointmentAsFinished(' . $aRow['id'] . '); return false;"> ' . _l('task_mark_as', _l('appointment_status_completed')) . '</a></li>';
    }

    // Can be marked as no-show
    if (
      $currentStatusValue != 'no-show' && $currentStatusValue != 'completed' &&
      (staff_can('edit', 'appointments') || $aRow['created_by'] == get_staff_user_id() || in_array(get_staff_user_id(), explode(',', $aRow['attendees'])))
    ) {
      $outputStatus .= '<li>
      <a href="#" class="tw-px-4 tw-py-2 tw-text-sm tw-text-neutral-700 hover:tw-bg-neutral-50 tw-block" 
      onclick="markAppointmentAsNoShow(' . $aRow['id'] . '); return false;">' . _l('task_mark_as', _l('appointment_status_no-show')) . '</a></li>';
    }

    // Can be marked as ongoing
    if (
      ($currentStatusValue == 'cancelled' || $currentStatusValue == 'no-show') &&
      (staff_can('edit', 'appointments') || $aRow['created_by'] == get_staff_user_id() || in_array(get_staff_user_id(), explode(',', $aRow['attendees'])))
    ) {
      $outputStatus .= '<li>
      <a href="#" class="tw-px-4 tw-py-2 tw-text-sm tw-text-neutral-700 hover:tw-bg-neutral-50 tw-block" 
       onclick="markAppointmentAsOngoing(' . $aRow['id'] . '); return false;">' . _l('task_mark_as', _l('appointment_status_in-progress')) . '</a></li>';
    }

    $outputStatus .= '</ul>';
    $outputStatus .= '</div>';

    return $outputStatus;
  } else {
    // For read-only status (no edit permissions)
    $currentStatus = checkAppointlyStatus($aRow);
    $statusClass = '';

    // Get status color class based on appointment status
    switch ($aRow['status']) {
      case 'cancelled':
        $statusClass = 'tw-bg-danger-200 tw-text-danger-700';
        break;
      case 'completed':
      case 'finished':
        $statusClass = 'tw-bg-success-50 tw-text-success-700';
        break;
      case 'in-progress':
        $statusClass = 'tw-bg-primary-50 tw-text-primary-700';
        break;
      case 'pending':
        $statusClass = 'tw-bg-warning-50 tw-text-warning-700';
        break;
      case 'approved':
        $statusClass = 'tw-bg-success-50 tw-text-success-700';
        break;
      case 'no-show':
        $statusClass = 'tw-bg-danger-200 tw-text-danger-700';
        break;
      default:
        $statusClass = 'tw-bg-neutral-50 tw-text-neutral-700';
    }

    $outputStatus  = '<div class="tw-inline-block">';
    $outputStatus  .= '<span class="tw-px-3 tw-py-1 tw-text-sm tw-font-medium tw-rounded-md '
      . $statusClass . '">';
    $outputStatus  .= $currentStatus;
    $outputStatus  .= '</span>';
    $outputStatus  .= '</div>';
  }

  return $outputStatus;
}