<?php
/**
 * Appointment Database Service
 *
 * Handles advanced appointment data operations and business logic
 *
 * @package Care_API
 * @subpackage Services\Database
 * @version    1.0.0
 * @author     Descomplicar® <dev@descomplicar.pt>
 * @link       https://descomplicar.pt
 * @since      1.0.0
 */

namespace Care_API\Services\Database;

use Care_API\Models\Appointment;
use Care_API\Services\Permission_Service;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Class Appointment_Service
 *
 * Advanced database service for appointment management with business logic
 *
 * @since 1.0.0
 */
class Appointment_Service {

    /**
     * Appointment status constants
     */
    const STATUS_BOOKED = 1;
    const STATUS_COMPLETED = 2;
    const STATUS_CANCELLED = 3;
    const STATUS_NO_SHOW = 4;
    const STATUS_RESCHEDULED = 5;

    /**
     * Initialize the service
     *
     * @since 1.0.0
     */
    public static function init() {
        // Hook into WordPress actions
        add_action( 'kivicare_appointment_created', array( self::class, 'on_appointment_created' ), 10, 2 );
        add_action( 'kivicare_appointment_updated', array( self::class, 'on_appointment_updated' ), 10, 2 );
        add_action( 'kivicare_appointment_cancelled', array( self::class, 'on_appointment_cancelled' ), 10, 1 );
        add_action( 'kivicare_appointment_completed', array( self::class, 'on_appointment_completed' ), 10, 1 );
    }

    /**
     * Create appointment with advanced business logic
     *
     * @param array $appointment_data Appointment data
     * @param int   $user_id          Creating user ID
     * @return array|WP_Error Appointment data or error
     * @since 1.0.0
     */
    public static function create_appointment( $appointment_data, $user_id = null ) {
        // Permission check
        if ( ! Permission_Service::can_manage_appointments( get_current_user_id(), $appointment_data['clinic_id'] ?? 0 ) ) {
            return new \WP_Error(
                'insufficient_permissions',
                'You do not have permission to create appointments',
                array( 'status' => 403 )
            );
        }

        // Enhanced validation
        $validation = self::validate_appointment_business_rules( $appointment_data );
        if ( is_wp_error( $validation ) ) {
            return $validation;
        }

        // Check doctor availability
        $availability_check = self::check_doctor_availability( $appointment_data );
        if ( is_wp_error( $availability_check ) ) {
            return $availability_check;
        }

        // Add metadata
        $appointment_data['created_by'] = $user_id ?: get_current_user_id();
        $appointment_data['created_at'] = current_time( 'mysql' );
        $appointment_data['status'] = self::STATUS_BOOKED;

        // Generate appointment number if not provided
        if ( empty( $appointment_data['appointment_number'] ) ) {
            $appointment_data['appointment_number'] = self::generate_appointment_number();
        }

        // Calculate end time if not provided
        if ( empty( $appointment_data['appointment_end_time'] ) ) {
            $appointment_data['appointment_end_time'] = self::calculate_end_time( 
                $appointment_data['appointment_start_time'], 
                $appointment_data['duration'] ?? 30 
            );
        }

        // Create appointment
        $appointment_id = Appointment::create( $appointment_data );
        
        if ( is_wp_error( $appointment_id ) ) {
            return $appointment_id;
        }

        // Post-creation tasks
        self::setup_appointment_defaults( $appointment_id, $appointment_data );
        
        // Send notifications
        self::send_appointment_notifications( $appointment_id, 'created' );
        
        // Trigger action
        do_action( 'kivicare_appointment_created', $appointment_id, $appointment_data );

        // Return full appointment data
        return self::get_appointment_with_metadata( $appointment_id );
    }

    /**
     * Update appointment with business logic
     *
     * @param int   $appointment_id   Appointment ID
     * @param array $appointment_data Updated data
     * @return array|WP_Error Updated appointment data or error
     * @since 1.0.0
     */
    public static function update_appointment( $appointment_id, $appointment_data ) {
        // Get current appointment data
        $current_appointment = Appointment::get_by_id( $appointment_id );
        if ( ! $current_appointment ) {
            return new \WP_Error(
                'appointment_not_found',
                'Appointment not found',
                array( 'status' => 404 )
            );
        }

        // Permission check
        if ( ! Permission_Service::can_manage_appointments( get_current_user_id(), $current_appointment['clinic_id'] ) ) {
            return new \WP_Error(
                'insufficient_permissions',
                'You do not have permission to update this appointment',
                array( 'status' => 403 )
            );
        }

        // Enhanced validation
        $validation = self::validate_appointment_business_rules( $appointment_data, $appointment_id );
        if ( is_wp_error( $validation ) ) {
            return $validation;
        }

        // Check if this is a rescheduling
        $is_rescheduling = self::is_appointment_rescheduling( $current_appointment, $appointment_data );
        if ( $is_rescheduling ) {
            $availability_check = self::check_doctor_availability( $appointment_data, $appointment_id );
            if ( is_wp_error( $availability_check ) ) {
                return $availability_check;
            }
        }

        // Add update metadata
        $appointment_data['updated_by'] = get_current_user_id();
        $appointment_data['updated_at'] = current_time( 'mysql' );

        // Update appointment
        $result = Appointment::update( $appointment_id, $appointment_data );
        
        if ( is_wp_error( $result ) ) {
            return $result;
        }

        // Handle status changes
        self::handle_status_changes( $appointment_id, $current_appointment, $appointment_data );

        // Send notifications if needed
        if ( $is_rescheduling ) {
            self::send_appointment_notifications( $appointment_id, 'rescheduled' );
        }

        // Trigger action
        do_action( 'kivicare_appointment_updated', $appointment_id, $appointment_data );

        // Return updated appointment data
        return self::get_appointment_with_metadata( $appointment_id );
    }

    /**
     * Cancel appointment
     *
     * @param int    $appointment_id Appointment ID
     * @param string $reason         Cancellation reason
     * @return array|WP_Error Updated appointment data or error
     * @since 1.0.0
     */
    public static function cancel_appointment( $appointment_id, $reason = '' ) {
        $appointment = Appointment::get_by_id( $appointment_id );
        if ( ! $appointment ) {
            return new \WP_Error(
                'appointment_not_found',
                'Appointment not found',
                array( 'status' => 404 )
            );
        }

        // Permission check
        if ( ! Permission_Service::can_manage_appointments( get_current_user_id(), $appointment['clinic_id'] ) ) {
            return new \WP_Error(
                'insufficient_permissions',
                'You do not have permission to cancel this appointment',
                array( 'status' => 403 )
            );
        }

        // Check if appointment can be cancelled
        if ( $appointment['status'] == self::STATUS_COMPLETED ) {
            return new \WP_Error(
                'cannot_cancel_completed',
                'Cannot cancel a completed appointment',
                array( 'status' => 400 )
            );
        }

        if ( $appointment['status'] == self::STATUS_CANCELLED ) {
            return new \WP_Error(
                'already_cancelled',
                'Appointment is already cancelled',
                array( 'status' => 400 )
            );
        }

        // Update appointment status
        $update_data = array(
            'status' => self::STATUS_CANCELLED,
            'cancellation_reason' => $reason,
            'cancelled_by' => get_current_user_id(),
            'cancelled_at' => current_time( 'mysql' ),
            'updated_at' => current_time( 'mysql' )
        );

        $result = Appointment::update( $appointment_id, $update_data );
        
        if ( is_wp_error( $result ) ) {
            return $result;
        }

        // Send cancellation notifications
        self::send_appointment_notifications( $appointment_id, 'cancelled' );

        // Trigger action
        do_action( 'kivicare_appointment_cancelled', $appointment_id );

        return self::get_appointment_with_metadata( $appointment_id );
    }

    /**
     * Complete appointment
     *
     * @param int   $appointment_id Appointment ID
     * @param array $completion_data Completion data
     * @return array|WP_Error Updated appointment data or error
     * @since 1.0.0
     */
    public static function complete_appointment( $appointment_id, $completion_data = array() ) {
        $appointment = Appointment::get_by_id( $appointment_id );
        if ( ! $appointment ) {
            return new \WP_Error(
                'appointment_not_found',
                'Appointment not found',
                array( 'status' => 404 )
            );
        }

        // Permission check
        if ( ! Permission_Service::can_manage_appointments( get_current_user_id(), $appointment['clinic_id'] ) ) {
            return new \WP_Error(
                'insufficient_permissions',
                'You do not have permission to complete this appointment',
                array( 'status' => 403 )
            );
        }

        // Check if appointment can be completed
        if ( $appointment['status'] == self::STATUS_CANCELLED ) {
            return new \WP_Error(
                'cannot_complete_cancelled',
                'Cannot complete a cancelled appointment',
                array( 'status' => 400 )
            );
        }

        if ( $appointment['status'] == self::STATUS_COMPLETED ) {
            return new \WP_Error(
                'already_completed',
                'Appointment is already completed',
                array( 'status' => 400 )
            );
        }

        // Update appointment status
        $update_data = array_merge( $completion_data, array(
            'status' => self::STATUS_COMPLETED,
            'completed_by' => get_current_user_id(),
            'completed_at' => current_time( 'mysql' ),
            'updated_at' => current_time( 'mysql' )
        ));

        $result = Appointment::update( $appointment_id, $update_data );
        
        if ( is_wp_error( $result ) ) {
            return $result;
        }

        // Auto-generate bill if configured
        if ( get_option( 'kivicare_auto_generate_bills', true ) ) {
            self::auto_generate_bill( $appointment_id );
        }

        // Send completion notifications
        self::send_appointment_notifications( $appointment_id, 'completed' );

        // Trigger action
        do_action( 'kivicare_appointment_completed', $appointment_id );

        return self::get_appointment_with_metadata( $appointment_id );
    }

    /**
     * Get appointment with enhanced metadata
     *
     * @param int $appointment_id Appointment ID
     * @return array|WP_Error Appointment data with metadata or error
     * @since 1.0.0
     */
    public static function get_appointment_with_metadata( $appointment_id ) {
        $appointment = Appointment::get_by_id( $appointment_id );
        
        if ( ! $appointment ) {
            return new \WP_Error(
                'appointment_not_found',
                'Appointment not found',
                array( 'status' => 404 )
            );
        }

        // Permission check
        if ( ! Permission_Service::can_view_appointment( get_current_user_id(), $appointment_id ) ) {
            return new \WP_Error(
                'access_denied',
                'You do not have access to this appointment',
                array( 'status' => 403 )
            );
        }

        // Add enhanced metadata
        $appointment['patient'] = self::get_appointment_patient( $appointment['patient_id'] );
        $appointment['doctor'] = self::get_appointment_doctor( $appointment['doctor_id'] );
        $appointment['clinic'] = self::get_appointment_clinic( $appointment['clinic_id'] );
        $appointment['service'] = self::get_appointment_service( $appointment['service_id'] ?? null );
        $appointment['encounters'] = self::get_appointment_encounters( $appointment_id );
        $appointment['bills'] = self::get_appointment_bills( $appointment_id );
        $appointment['status_label'] = self::get_status_label( $appointment['status'] );

        return $appointment;
    }

    /**
     * Search appointments with advanced criteria
     *
     * @param array $filters Search filters
     * @return array Search results
     * @since 1.0.0
     */
    public static function search_appointments( $filters = array() ) {
        global $wpdb;

        $user_id = get_current_user_id();
        $accessible_clinic_ids = Permission_Service::get_accessible_clinic_ids( $user_id );

        if ( empty( $accessible_clinic_ids ) ) {
            return array();
        }

        // Build search query
        $where_clauses = array( "a.clinic_id IN (" . implode( ',', $accessible_clinic_ids ) . ")" );
        $where_values = array();

        // Date range filter
        if ( ! empty( $filters['start_date'] ) ) {
            $where_clauses[] = "DATE(a.appointment_start_date) >= %s";
            $where_values[] = $filters['start_date'];
        }

        if ( ! empty( $filters['end_date'] ) ) {
            $where_clauses[] = "DATE(a.appointment_start_date) <= %s";
            $where_values[] = $filters['end_date'];
        }

        // Doctor filter
        if ( ! empty( $filters['doctor_id'] ) ) {
            $where_clauses[] = "a.doctor_id = %d";
            $where_values[] = $filters['doctor_id'];
        }

        // Patient filter
        if ( ! empty( $filters['patient_id'] ) ) {
            $where_clauses[] = "a.patient_id = %d";
            $where_values[] = $filters['patient_id'];
        }

        // Clinic filter
        if ( ! empty( $filters['clinic_id'] ) && in_array( $filters['clinic_id'], $accessible_clinic_ids ) ) {
            $where_clauses[] = "a.clinic_id = %d";
            $where_values[] = $filters['clinic_id'];
        }

        // Status filter
        if ( ! empty( $filters['status'] ) ) {
            if ( is_array( $filters['status'] ) ) {
                $status_placeholders = implode( ',', array_fill( 0, count( $filters['status'] ), '%d' ) );
                $where_clauses[] = "a.status IN ({$status_placeholders})";
                $where_values = array_merge( $where_values, $filters['status'] );
            } else {
                $where_clauses[] = "a.status = %d";
                $where_values[] = $filters['status'];
            }
        }

        // Search term
        if ( ! empty( $filters['search'] ) ) {
            $where_clauses[] = "(p.first_name LIKE %s OR p.last_name LIKE %s OR d.first_name LIKE %s OR d.last_name LIKE %s OR a.appointment_number LIKE %s)";
            $search_term = '%' . $wpdb->esc_like( $filters['search'] ) . '%';
            $where_values = array_merge( $where_values, array_fill( 0, 5, $search_term ) );
        }

        $where_sql = implode( ' AND ', $where_clauses );

        // Pagination
        $limit = isset( $filters['limit'] ) ? (int) $filters['limit'] : 20;
        $offset = isset( $filters['offset'] ) ? (int) $filters['offset'] : 0;

        $query = "SELECT a.*, 
                         p.first_name as patient_first_name, p.last_name as patient_last_name,
                         d.first_name as doctor_first_name, d.last_name as doctor_last_name,
                         c.name as clinic_name
                  FROM {$wpdb->prefix}kc_appointments a
                  LEFT JOIN {$wpdb->prefix}users p ON a.patient_id = p.ID
                  LEFT JOIN {$wpdb->prefix}users d ON a.doctor_id = d.ID
                  LEFT JOIN {$wpdb->prefix}kc_clinics c ON a.clinic_id = c.id
                  WHERE {$where_sql}
                  ORDER BY a.appointment_start_date DESC, a.appointment_start_time DESC
                  LIMIT %d OFFSET %d";

        $where_values[] = $limit;
        $where_values[] = $offset;

        $results = $wpdb->get_results( $wpdb->prepare( $query, $where_values ), ARRAY_A );

        // Get total count for pagination
        $count_query = "SELECT COUNT(*) FROM {$wpdb->prefix}kc_appointments a
                        LEFT JOIN {$wpdb->prefix}users p ON a.patient_id = p.ID
                        LEFT JOIN {$wpdb->prefix}users d ON a.doctor_id = d.ID
                        WHERE {$where_sql}";

        // Remove limit and offset from where_values for count query
        $count_where_values = $where_values;
        array_pop( $count_where_values );
        array_pop( $count_where_values );

        $total = (int) $wpdb->get_var( $wpdb->prepare( $count_query, $count_where_values ) );

        return array(
            'appointments' => array_map( function( $appointment ) {
                $appointment['id'] = (int) $appointment['id'];
                $appointment['status_label'] = self::get_status_label( $appointment['status'] );
                return $appointment;
            }, $results ),
            'total' => $total,
            'has_more' => ( $offset + $limit ) < $total
        );
    }

    /**
     * Get doctor availability for date range
     *
     * @param int    $doctor_id   Doctor ID
     * @param string $start_date  Start date
     * @param string $end_date    End date
     * @return array Available slots
     * @since 1.0.0
     */
    public static function get_doctor_availability( $doctor_id, $start_date, $end_date ) {
        global $wpdb;

        // Get doctor schedule
        $doctor_schedule = get_option( "kivicare_doctor_{$doctor_id}_schedule", array() );
        
        if ( empty( $doctor_schedule ) ) {
            return array();
        }

        // Get existing appointments in date range
        $existing_appointments = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT appointment_start_date, appointment_start_time, appointment_end_time, duration
                 FROM {$wpdb->prefix}kc_appointments 
                 WHERE doctor_id = %d 
                 AND appointment_start_date BETWEEN %s AND %s 
                 AND status NOT IN (%d, %d)",
                $doctor_id, $start_date, $end_date, 
                self::STATUS_CANCELLED, self::STATUS_NO_SHOW
            ),
            ARRAY_A
        );

        // Calculate available slots
        $available_slots = array();
        $current_date = new \DateTime( $start_date );
        $end_date_obj = new \DateTime( $end_date );

        while ( $current_date <= $end_date_obj ) {
            $day_name = strtolower( $current_date->format( 'l' ) );
            
            if ( isset( $doctor_schedule[$day_name] ) && ! isset( $doctor_schedule[$day_name]['closed'] ) ) {
                $day_slots = self::calculate_day_slots( 
                    $current_date->format( 'Y-m-d' ),
                    $doctor_schedule[$day_name],
                    $existing_appointments
                );
                
                if ( ! empty( $day_slots ) ) {
                    $available_slots[$current_date->format( 'Y-m-d' )] = $day_slots;
                }
            }

            $current_date->add( new \DateInterval( 'P1D' ) );
        }

        return $available_slots;
    }

    /**
     * Generate unique appointment number
     *
     * @return string Appointment number
     * @since 1.0.0
     */
    private static function generate_appointment_number() {
        global $wpdb;

        $date_prefix = current_time( 'Ymd' );
        
        // Get the highest existing appointment number for today
        $max_number = $wpdb->get_var(
            $wpdb->prepare(
                "SELECT MAX(CAST(SUBSTRING(appointment_number, 9) AS UNSIGNED)) 
                 FROM {$wpdb->prefix}kc_appointments 
                 WHERE appointment_number LIKE %s",
                $date_prefix . '%'
            )
        );

        $next_number = ( $max_number ? $max_number + 1 : 1 );
        
        return $date_prefix . str_pad( $next_number, 4, '0', STR_PAD_LEFT );
    }

    /**
     * Calculate appointment end time
     *
     * @param string $start_time Start time
     * @param int    $duration   Duration in minutes
     * @return string End time
     * @since 1.0.0
     */
    private static function calculate_end_time( $start_time, $duration ) {
        $start_datetime = new \DateTime( $start_time );
        $start_datetime->add( new \DateInterval( "PT{$duration}M" ) );
        return $start_datetime->format( 'H:i:s' );
    }

    /**
     * Validate appointment business rules
     *
     * @param array $appointment_data Appointment data
     * @param int   $appointment_id   Appointment ID (for updates)
     * @return bool|WP_Error True if valid, WP_Error otherwise
     * @since 1.0.0
     */
    private static function validate_appointment_business_rules( $appointment_data, $appointment_id = null ) {
        $errors = array();

        // Validate required fields
        $required_fields = array( 'patient_id', 'doctor_id', 'clinic_id', 'appointment_start_date', 'appointment_start_time' );
        
        foreach ( $required_fields as $field ) {
            if ( empty( $appointment_data[$field] ) ) {
                $errors[] = "Field {$field} is required";
            }
        }

        // Validate appointment date is not in the past
        if ( ! empty( $appointment_data['appointment_start_date'] ) ) {
            $appointment_date = new \DateTime( $appointment_data['appointment_start_date'] );
            $today = new \DateTime();
            $today->setTime( 0, 0, 0 );

            if ( $appointment_date < $today ) {
                $errors[] = 'Appointment date cannot be in the past';
            }
        }

        // Validate patient exists
        if ( ! empty( $appointment_data['patient_id'] ) ) {
            global $wpdb;
            $patient_exists = $wpdb->get_var(
                $wpdb->prepare(
                    "SELECT id FROM {$wpdb->prefix}kc_patients WHERE id = %d",
                    $appointment_data['patient_id']
                )
            );
            
            if ( ! $patient_exists ) {
                $errors[] = 'Invalid patient ID';
            }
        }

        // Validate doctor exists
        if ( ! empty( $appointment_data['doctor_id'] ) ) {
            global $wpdb;
            $doctor_exists = $wpdb->get_var(
                $wpdb->prepare(
                    "SELECT id FROM {$wpdb->prefix}kc_doctors WHERE id = %d",
                    $appointment_data['doctor_id']
                )
            );
            
            if ( ! $doctor_exists ) {
                $errors[] = 'Invalid doctor ID';
            }
        }

        // Validate clinic exists
        if ( ! empty( $appointment_data['clinic_id'] ) ) {
            global $wpdb;
            $clinic_exists = $wpdb->get_var(
                $wpdb->prepare(
                    "SELECT id FROM {$wpdb->prefix}kc_clinics WHERE id = %d",
                    $appointment_data['clinic_id']
                )
            );
            
            if ( ! $clinic_exists ) {
                $errors[] = 'Invalid clinic ID';
            }
        }

        if ( ! empty( $errors ) ) {
            return new \WP_Error(
                'appointment_business_validation_failed',
                'Appointment business validation failed',
                array( 
                    'status' => 400,
                    'errors' => $errors 
                )
            );
        }

        return true;
    }

    /**
     * Check doctor availability for appointment slot
     *
     * @param array $appointment_data Appointment data
     * @param int   $exclude_id       Appointment ID to exclude (for updates)
     * @return bool|WP_Error True if available, WP_Error otherwise
     * @since 1.0.0
     */
    private static function check_doctor_availability( $appointment_data, $exclude_id = null ) {
        global $wpdb;

        $doctor_id = $appointment_data['doctor_id'];
        $start_date = $appointment_data['appointment_start_date'];
        $start_time = $appointment_data['appointment_start_time'];
        $duration = $appointment_data['duration'] ?? 30;
        $end_time = self::calculate_end_time( $start_time, $duration );

        // Check for conflicting appointments
        $conflict_query = "SELECT id FROM {$wpdb->prefix}kc_appointments 
                          WHERE doctor_id = %d 
                          AND appointment_start_date = %s 
                          AND status NOT IN (%d, %d)
                          AND (
                              (appointment_start_time <= %s AND appointment_end_time > %s) OR
                              (appointment_start_time < %s AND appointment_end_time >= %s) OR
                              (appointment_start_time >= %s AND appointment_end_time <= %s)
                          )";

        $conflict_params = array(
            $doctor_id, $start_date, 
            self::STATUS_CANCELLED, self::STATUS_NO_SHOW,
            $start_time, $start_time,
            $end_time, $end_time,
            $start_time, $end_time
        );

        if ( $exclude_id ) {
            $conflict_query .= " AND id != %d";
            $conflict_params[] = $exclude_id;
        }

        $conflict = $wpdb->get_var( $wpdb->prepare( $conflict_query, $conflict_params ) );

        if ( $conflict ) {
            return new \WP_Error(
                'doctor_not_available',
                'Doctor is not available at the selected time slot',
                array( 'status' => 400 )
            );
        }

        // Check doctor working hours
        $doctor_schedule = get_option( "kivicare_doctor_{$doctor_id}_schedule", array() );
        $day_name = strtolower( date( 'l', strtotime( $start_date ) ) );

        if ( empty( $doctor_schedule[$day_name] ) || isset( $doctor_schedule[$day_name]['closed'] ) ) {
            return new \WP_Error(
                'doctor_not_working',
                'Doctor is not working on this day',
                array( 'status' => 400 )
            );
        }

        $working_hours = $doctor_schedule[$day_name];
        if ( $start_time < $working_hours['start_time'] || $end_time > $working_hours['end_time'] ) {
            return new \WP_Error(
                'outside_working_hours',
                'Appointment time is outside doctor working hours',
                array( 'status' => 400 )
            );
        }

        // Check break time if exists
        if ( isset( $working_hours['break_start'] ) && isset( $working_hours['break_end'] ) ) {
            $break_start = $working_hours['break_start'];
            $break_end = $working_hours['break_end'];

            if ( ( $start_time >= $break_start && $start_time < $break_end ) ||
                 ( $end_time > $break_start && $end_time <= $break_end ) ||
                 ( $start_time <= $break_start && $end_time >= $break_end ) ) {
                return new \WP_Error(
                    'during_break_time',
                    'Appointment time conflicts with doctor break time',
                    array( 'status' => 400 )
                );
            }
        }

        return true;
    }

    /**
     * Additional helper methods for appointment management
     */

    private static function is_appointment_rescheduling( $current_appointment, $new_data ) {
        return ( isset( $new_data['appointment_start_date'] ) && $new_data['appointment_start_date'] != $current_appointment['appointment_start_date'] ) ||
               ( isset( $new_data['appointment_start_time'] ) && $new_data['appointment_start_time'] != $current_appointment['appointment_start_time'] ) ||
               ( isset( $new_data['doctor_id'] ) && $new_data['doctor_id'] != $current_appointment['doctor_id'] );
    }

    private static function handle_status_changes( $appointment_id, $current_appointment, $new_data ) {
        if ( isset( $new_data['status'] ) && $new_data['status'] != $current_appointment['status'] ) {
            $status_change = array(
                'appointment_id' => $appointment_id,
                'from_status' => $current_appointment['status'],
                'to_status' => $new_data['status'],
                'changed_by' => get_current_user_id(),
                'changed_at' => current_time( 'mysql' )
            );

            do_action( 'kivicare_appointment_status_changed', $status_change );
        }
    }

    private static function setup_appointment_defaults( $appointment_id, $appointment_data ) {
        // Setup any default values or related data
        update_option( "kivicare_appointment_{$appointment_id}_created", current_time( 'mysql' ) );
    }

    private static function send_appointment_notifications( $appointment_id, $type ) {
        // Send notifications to patient, doctor, etc.
        do_action( "kivicare_send_appointment_{$type}_notification", $appointment_id );
    }

    private static function auto_generate_bill( $appointment_id ) {
        // Auto-generate bill for completed appointment
        do_action( 'kivicare_auto_generate_bill', $appointment_id );
    }

    private static function get_appointment_patient( $patient_id ) {
        global $wpdb;
        return $wpdb->get_row(
            $wpdb->prepare(
                "SELECT id, first_name, last_name, user_email, contact_no FROM {$wpdb->prefix}kc_patients WHERE id = %d",
                $patient_id
            ),
            ARRAY_A
        );
    }

    private static function get_appointment_doctor( $doctor_id ) {
        global $wpdb;
        return $wpdb->get_row(
            $wpdb->prepare(
                "SELECT id, first_name, last_name, user_email, mobile_number, specialties FROM {$wpdb->prefix}kc_doctors WHERE id = %d",
                $doctor_id
            ),
            ARRAY_A
        );
    }

    private static function get_appointment_clinic( $clinic_id ) {
        global $wpdb;
        return $wpdb->get_row(
            $wpdb->prepare(
                "SELECT id, name, address, city, telephone_no FROM {$wpdb->prefix}kc_clinics WHERE id = %d",
                $clinic_id
            ),
            ARRAY_A
        );
    }

    private static function get_appointment_service( $service_id ) {
        if ( ! $service_id ) return null;
        
        global $wpdb;
        return $wpdb->get_row(
            $wpdb->prepare(
                "SELECT id, name, price, duration FROM {$wpdb->prefix}kc_services WHERE id = %d",
                $service_id
            ),
            ARRAY_A
        );
    }

    private static function get_appointment_encounters( $appointment_id ) {
        global $wpdb;
        return $wpdb->get_results(
            $wpdb->prepare(
                "SELECT * FROM {$wpdb->prefix}kc_encounters WHERE appointment_id = %d ORDER BY encounter_date DESC",
                $appointment_id
            ),
            ARRAY_A
        );
    }

    private static function get_appointment_bills( $appointment_id ) {
        global $wpdb;
        return $wpdb->get_results(
            $wpdb->prepare(
                "SELECT * FROM {$wpdb->prefix}kc_bills WHERE appointment_id = %d ORDER BY created_at DESC",
                $appointment_id
            ),
            ARRAY_A
        );
    }

    private static function get_status_label( $status ) {
        $labels = array(
            self::STATUS_BOOKED => 'Booked',
            self::STATUS_COMPLETED => 'Completed',
            self::STATUS_CANCELLED => 'Cancelled',
            self::STATUS_NO_SHOW => 'No Show',
            self::STATUS_RESCHEDULED => 'Rescheduled'
        );

        return $labels[$status] ?? 'Unknown';
    }

    private static function calculate_day_slots( $date, $schedule, $existing_appointments ) {
        $slots = array();
        $slot_duration = 30; // minutes
        
        $start_time = new \DateTime( $date . ' ' . $schedule['start_time'] );
        $end_time = new \DateTime( $date . ' ' . $schedule['end_time'] );
        
        // Handle break time
        $break_start = isset( $schedule['break_start'] ) ? new \DateTime( $date . ' ' . $schedule['break_start'] ) : null;
        $break_end = isset( $schedule['break_end'] ) ? new \DateTime( $date . ' ' . $schedule['break_end'] ) : null;

        $current_time = clone $start_time;
        
        while ( $current_time < $end_time ) {
            $slot_end = clone $current_time;
            $slot_end->add( new \DateInterval( "PT{$slot_duration}M" ) );
            
            // Skip if in break time
            if ( $break_start && $break_end && 
                 ( $current_time >= $break_start && $current_time < $break_end ) ) {
                $current_time = clone $break_end;
                continue;
            }
            
            // Check if slot is available
            $is_available = true;
            foreach ( $existing_appointments as $appointment ) {
                if ( $appointment['appointment_start_date'] == $date ) {
                    $app_start = new \DateTime( $date . ' ' . $appointment['appointment_start_time'] );
                    $app_end = new \DateTime( $date . ' ' . $appointment['appointment_end_time'] );
                    
                    if ( ( $current_time >= $app_start && $current_time < $app_end ) ||
                         ( $slot_end > $app_start && $slot_end <= $app_end ) ||
                         ( $current_time <= $app_start && $slot_end >= $app_end ) ) {
                        $is_available = false;
                        break;
                    }
                }
            }
            
            if ( $is_available ) {
                $slots[] = array(
                    'start_time' => $current_time->format( 'H:i:s' ),
                    'end_time' => $slot_end->format( 'H:i:s' ),
                    'duration' => $slot_duration
                );
            }
            
            $current_time->add( new \DateInterval( "PT{$slot_duration}M" ) );
        }
        
        return $slots;
    }

    /**
     * Event handlers
     */
    public static function on_appointment_created( $appointment_id, $appointment_data ) {
        error_log( "Care: New appointment created - ID: {$appointment_id}, Patient: " . ( $appointment_data['patient_id'] ?? 'Unknown' ) );
    }

    public static function on_appointment_updated( $appointment_id, $appointment_data ) {
        error_log( "Care: Appointment updated - ID: {$appointment_id}" );
        wp_cache_delete( "appointment_{$appointment_id}", 'kivicare' );
    }

    public static function on_appointment_cancelled( $appointment_id ) {
        error_log( "Care: Appointment cancelled - ID: {$appointment_id}" );
        wp_cache_delete( "appointment_{$appointment_id}", 'kivicare' );
    }

    public static function on_appointment_completed( $appointment_id ) {
        error_log( "Care: Appointment completed - ID: {$appointment_id}" );
        wp_cache_delete( "appointment_{$appointment_id}", 'kivicare' );
    }
}