<?php
/**
 * Doctor Model
 *
 * Handles doctor entity operations, schedules and clinic associations
 *
 * @package Care_API
 * @subpackage Models
 * @version    1.0.0
 * @author     Descomplicar® <dev@descomplicar.pt>
 * @link       https://descomplicar.pt
 * @since      1.0.0
 */

namespace Care_API\Models;

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

/**
 * Class Doctor
 *
 * Model for handling doctor data, schedules and clinic management
 *
 * @since 1.0.0
 */
class Doctor {

    /**
     * Doctor user ID (wp_users table)
     *
     * @var int
     */
    public $user_id;

    /**
     * Doctor data
     *
     * @var array
     */
    private $data = array();

    /**
     * Required fields for doctor registration
     *
     * @var array
     */
    private static $required_fields = array(
        'first_name',
        'last_name',
        'user_email',
        'specialization',
        'qualification'
    );

    /**
     * Constructor
     *
     * @param int|array $user_id_or_data Doctor user ID or data array
     * @since 1.0.0
     */
    public function __construct( $user_id_or_data = null ) {
        if ( is_numeric( $user_id_or_data ) ) {
            $this->user_id = (int) $user_id_or_data;
            $this->load_data();
        } elseif ( is_array( $user_id_or_data ) ) {
            $this->data = $user_id_or_data;
            $this->user_id = isset( $this->data['user_id'] ) ? (int) $this->data['user_id'] : null;
        }
    }

    /**
     * Load doctor data from database
     *
     * @return bool True on success, false on failure
     * @since 1.0.0
     */
    private function load_data() {
        if ( ! $this->user_id ) {
            return false;
        }

        $doctor_data = self::get_doctor_full_data( $this->user_id );
        
        if ( $doctor_data ) {
            $this->data = $doctor_data;
            return true;
        }

        return false;
    }

    /**
     * Create a new doctor
     *
     * @param array $doctor_data Doctor data
     * @return int|WP_Error Doctor user ID on success, WP_Error on failure
     * @since 1.0.0
     */
    public static function create( $doctor_data ) {
        // Validate required fields
        $validation = self::validate_doctor_data( $doctor_data );
        if ( is_wp_error( $validation ) ) {
            return $validation;
        }

        // Create WordPress user
        $user_data = array(
            'user_login' => self::generate_unique_username( $doctor_data ),
            'user_email' => sanitize_email( $doctor_data['user_email'] ),
            'first_name' => sanitize_text_field( $doctor_data['first_name'] ),
            'last_name' => sanitize_text_field( $doctor_data['last_name'] ),
            'role' => 'kivicare_doctor',
            'user_pass' => isset( $doctor_data['user_pass'] ) ? $doctor_data['user_pass'] : wp_generate_password()
        );

        $user_id = wp_insert_user( $user_data );

        if ( is_wp_error( $user_id ) ) {
            return new \WP_Error(
                'doctor_creation_failed',
                'Failed to create doctor user: ' . $user_id->get_error_message(),
                array( 'status' => 500 )
            );
        }

        // Add doctor meta data
        $meta_fields = array(
            'specialization' => sanitize_text_field( $doctor_data['specialization'] ),
            'qualification' => sanitize_text_field( $doctor_data['qualification'] ),
            'experience_years' => isset( $doctor_data['experience_years'] ) ? (int) $doctor_data['experience_years'] : 0,
            'mobile_number' => isset( $doctor_data['mobile_number'] ) ? sanitize_text_field( $doctor_data['mobile_number'] ) : '',
            'address' => isset( $doctor_data['address'] ) ? sanitize_textarea_field( $doctor_data['address'] ) : '',
            'city' => isset( $doctor_data['city'] ) ? sanitize_text_field( $doctor_data['city'] ) : '',
            'state' => isset( $doctor_data['state'] ) ? sanitize_text_field( $doctor_data['state'] ) : '',
            'country' => isset( $doctor_data['country'] ) ? sanitize_text_field( $doctor_data['country'] ) : '',
            'postal_code' => isset( $doctor_data['postal_code'] ) ? sanitize_text_field( $doctor_data['postal_code'] ) : '',
            'license_number' => isset( $doctor_data['license_number'] ) ? sanitize_text_field( $doctor_data['license_number'] ) : '',
            'consultation_fee' => isset( $doctor_data['consultation_fee'] ) ? (float) $doctor_data['consultation_fee'] : 0,
            'biography' => isset( $doctor_data['biography'] ) ? sanitize_textarea_field( $doctor_data['biography'] ) : '',
            'languages' => isset( $doctor_data['languages'] ) ? $doctor_data['languages'] : array(),
            'working_hours' => isset( $doctor_data['working_hours'] ) ? $doctor_data['working_hours'] : array(),
            'doctor_registration_date' => current_time( 'mysql' ),
            'doctor_status' => 'active'
        );

        foreach ( $meta_fields as $meta_key => $meta_value ) {
            if ( is_array( $meta_value ) ) {
                $meta_value = wp_json_encode( $meta_value );
            }
            update_user_meta( $user_id, $meta_key, $meta_value );
        }

        // Create clinic mapping if clinic_id provided
        if ( ! empty( $doctor_data['clinic_id'] ) ) {
            self::assign_to_clinic( $user_id, $doctor_data['clinic_id'] );
        }

        return $user_id;
    }

    /**
     * Update doctor data
     *
     * @param int   $user_id Doctor user ID
     * @param array $doctor_data Updated doctor data
     * @return bool|WP_Error True on success, WP_Error on failure
     * @since 1.0.0
     */
    public static function update( $user_id, $doctor_data ) {
        if ( ! self::exists( $user_id ) ) {
            return new \WP_Error(
                'doctor_not_found',
                'Doctor not found',
                array( 'status' => 404 )
            );
        }

        // Update user data
        $user_update_data = array( 'ID' => $user_id );
        $user_fields = array( 'first_name', 'last_name', 'user_email' );

        foreach ( $user_fields as $field ) {
            if ( isset( $doctor_data[ $field ] ) ) {
                $user_update_data[ $field ] = sanitize_text_field( $doctor_data[ $field ] );
            }
        }

        if ( count( $user_update_data ) > 1 ) {
            $result = wp_update_user( $user_update_data );
            if ( is_wp_error( $result ) ) {
                return new \WP_Error(
                    'doctor_update_failed',
                    'Failed to update doctor: ' . $result->get_error_message(),
                    array( 'status' => 500 )
                );
            }
        }

        // Update meta fields
        $meta_fields = array(
            'specialization', 'qualification', 'experience_years', 'mobile_number',
            'address', 'city', 'state', 'country', 'postal_code', 'license_number',
            'consultation_fee', 'biography', 'languages', 'working_hours', 'doctor_status'
        );

        foreach ( $meta_fields as $meta_key ) {
            if ( isset( $doctor_data[ $meta_key ] ) ) {
                $value = $doctor_data[ $meta_key ];
                
                if ( in_array( $meta_key, array( 'address', 'biography' ) ) ) {
                    $value = sanitize_textarea_field( $value );
                } elseif ( $meta_key === 'experience_years' ) {
                    $value = (int) $value;
                } elseif ( $meta_key === 'consultation_fee' ) {
                    $value = (float) $value;
                } elseif ( in_array( $meta_key, array( 'languages', 'working_hours' ) ) ) {
                    $value = is_array( $value ) ? wp_json_encode( $value ) : $value;
                } else {
                    $value = sanitize_text_field( $value );
                }
                
                update_user_meta( $user_id, $meta_key, $value );
            }
        }

        return true;
    }

    /**
     * Delete a doctor (soft delete - deactivate user)
     *
     * @param int $user_id Doctor user ID
     * @return bool|WP_Error True on success, WP_Error on failure
     * @since 1.0.0
     */
    public static function delete( $user_id ) {
        if ( ! self::exists( $user_id ) ) {
            return new \WP_Error(
                'doctor_not_found',
                'Doctor not found',
                array( 'status' => 404 )
            );
        }

        // Check for dependencies
        if ( self::has_dependencies( $user_id ) ) {
            return new \WP_Error(
                'doctor_has_dependencies',
                'Cannot delete doctor with existing appointments or patient encounters',
                array( 'status' => 409 )
            );
        }

        // Soft delete - set user status to inactive
        update_user_meta( $user_id, 'doctor_status', 'inactive' );

        return true;
    }

    /**
     * Get doctor by ID
     *
     * @param int $user_id Doctor user ID
     * @return array|null Doctor data or null if not found
     * @since 1.0.0
     */
    public static function get_by_id( $user_id ) {
        if ( ! self::exists( $user_id ) ) {
            return null;
        }

        return self::get_doctor_full_data( $user_id );
    }

    /**
     * Get all doctors with optional filtering
     *
     * @param array $args Query arguments
     * @return array Array of doctor data
     * @since 1.0.0
     */
    public static function get_all( $args = array() ) {
        $defaults = array(
            'clinic_id' => null,
            'specialization' => null,
            'status' => 'active',
            'search' => '',
            'limit' => 50,
            'offset' => 0,
            'orderby' => 'display_name',
            'order' => 'ASC'
        );

        $args = wp_parse_args( $args, $defaults );

        $user_query_args = array(
            'role' => 'kivicare_doctor',
            'number' => $args['limit'],
            'offset' => $args['offset'],
            'orderby' => $args['orderby'],
            'order' => $args['order'],
            'fields' => 'ID',
            'meta_query' => array()
        );

        // Add search
        if ( ! empty( $args['search'] ) ) {
            $user_query_args['search'] = '*' . $args['search'] . '*';
            $user_query_args['search_columns'] = array( 'user_login', 'user_email', 'display_name' );
        }

        // Add status filter
        if ( ! empty( $args['status'] ) ) {
            $user_query_args['meta_query'][] = array(
                'relation' => 'OR',
                array(
                    'key' => 'doctor_status',
                    'value' => $args['status'],
                    'compare' => '='
                ),
                array(
                    'key' => 'doctor_status',
                    'compare' => 'NOT EXISTS'
                )
            );
        }

        // Add specialization filter
        if ( ! empty( $args['specialization'] ) ) {
            $user_query_args['meta_query'][] = array(
                'key' => 'specialization',
                'value' => $args['specialization'],
                'compare' => 'LIKE'
            );
        }

        $user_query = new \WP_User_Query( $user_query_args );
        $user_ids = $user_query->get_results();

        $doctors = array();
        foreach ( $user_ids as $user_id ) {
            $doctor_data = self::get_doctor_full_data( $user_id );
            
            // Filter by clinic if specified
            if ( ! is_null( $args['clinic_id'] ) && 
                 ! in_array( (int) $args['clinic_id'], $doctor_data['clinic_ids'] ) ) {
                continue;
            }
            
            if ( $doctor_data ) {
                $doctors[] = $doctor_data;
            }
        }

        return $doctors;
    }

    /**
     * Get doctor full data with clinic information
     *
     * @param int $user_id Doctor user ID
     * @return array|null Full doctor data or null if not found
     * @since 1.0.0
     */
    public static function get_doctor_full_data( $user_id ) {
        global $wpdb;

        $user = get_user_by( 'id', $user_id );
        if ( ! $user || ! in_array( 'kivicare_doctor', $user->roles ) ) {
            return null;
        }

        // Get clinic mappings
        $clinic_mappings = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT dcm.clinic_id, c.name as clinic_name 
                 FROM {$wpdb->prefix}kc_doctor_clinic_mappings dcm
                 LEFT JOIN {$wpdb->prefix}kc_clinics c ON dcm.clinic_id = c.id
                 WHERE dcm.doctor_id = %d",
                $user_id
            ),
            ARRAY_A
        );

        $clinic_ids = array();
        $clinic_names = array();
        foreach ( $clinic_mappings as $mapping ) {
            $clinic_ids[] = (int) $mapping['clinic_id'];
            $clinic_names[] = $mapping['clinic_name'];
        }

        // Get doctor meta data
        $languages = get_user_meta( $user_id, 'languages', true );
        $working_hours = get_user_meta( $user_id, 'working_hours', true );

        if ( is_string( $languages ) ) {
            $languages = json_decode( $languages, true ) ?: array();
        }

        if ( is_string( $working_hours ) ) {
            $working_hours = json_decode( $working_hours, true ) ?: array();
        }

        $doctor_data = array(
            'user_id' => $user_id,
            'username' => $user->user_login,
            'email' => $user->user_email,
            'first_name' => $user->first_name,
            'last_name' => $user->last_name,
            'display_name' => $user->display_name,
            'specialization' => get_user_meta( $user_id, 'specialization', true ),
            'qualification' => get_user_meta( $user_id, 'qualification', true ),
            'experience_years' => (int) get_user_meta( $user_id, 'experience_years', true ),
            'mobile_number' => get_user_meta( $user_id, 'mobile_number', true ),
            'address' => get_user_meta( $user_id, 'address', true ),
            'city' => get_user_meta( $user_id, 'city', true ),
            'state' => get_user_meta( $user_id, 'state', true ),
            'country' => get_user_meta( $user_id, 'country', true ),
            'postal_code' => get_user_meta( $user_id, 'postal_code', true ),
            'license_number' => get_user_meta( $user_id, 'license_number', true ),
            'consultation_fee' => (float) get_user_meta( $user_id, 'consultation_fee', true ),
            'biography' => get_user_meta( $user_id, 'biography', true ),
            'languages' => $languages,
            'working_hours' => $working_hours,
            'status' => get_user_meta( $user_id, 'doctor_status', true ) ?: 'active',
            'registration_date' => get_user_meta( $user_id, 'doctor_registration_date', true ),
            'clinic_ids' => $clinic_ids,
            'clinic_names' => $clinic_names,
            'total_appointments' => self::get_appointment_count( $user_id ),
            'total_patients' => self::get_patient_count( $user_id ),
            'rating' => self::get_doctor_rating( $user_id )
        );

        return $doctor_data;
    }

    /**
     * Get doctor schedule
     *
     * @param int   $user_id Doctor user ID
     * @param array $args    Query arguments
     * @return array Doctor schedule
     * @since 1.0.0
     */
    public static function get_schedule( $user_id, $args = array() ) {
        global $wpdb;

        $defaults = array(
            'date_from' => date( 'Y-m-d' ),
            'date_to' => date( 'Y-m-d', strtotime( '+30 days' ) ),
            'clinic_id' => null
        );

        $args = wp_parse_args( $args, $defaults );

        // Get appointments in date range
        $where_clauses = array( 
            'doctor_id = %d',
            'appointment_start_date BETWEEN %s AND %s'
        );
        $where_values = array( $user_id, $args['date_from'], $args['date_to'] );

        if ( ! is_null( $args['clinic_id'] ) ) {
            $where_clauses[] = 'clinic_id = %d';
            $where_values[] = $args['clinic_id'];
        }

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

        $appointments = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT a.*, 
                        CONCAT(p.first_name, ' ', p.last_name) as patient_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}kc_clinics c ON a.clinic_id = c.id
                 WHERE {$where_sql}
                 ORDER BY appointment_start_date, appointment_start_time",
                $where_values
            ),
            ARRAY_A
        );

        // Get working hours
        $working_hours = get_user_meta( $user_id, 'working_hours', true );
        if ( is_string( $working_hours ) ) {
            $working_hours = json_decode( $working_hours, true ) ?: array();
        }

        $schedule = array(
            'working_hours' => $working_hours,
            'appointments' => array()
        );

        foreach ( $appointments as $appointment ) {
            $schedule['appointments'][] = array(
                'id' => (int) $appointment['id'],
                'date' => $appointment['appointment_start_date'],
                'start_time' => $appointment['appointment_start_time'],
                'end_time' => $appointment['appointment_end_time'],
                'patient' => array(
                    'id' => (int) $appointment['patient_id'],
                    'name' => $appointment['patient_name']
                ),
                'clinic' => array(
                    'id' => (int) $appointment['clinic_id'],
                    'name' => $appointment['clinic_name']
                ),
                'visit_type' => $appointment['visit_type'],
                'status' => (int) $appointment['status'],
                'description' => $appointment['description']
            );
        }

        return $schedule;
    }

    /**
     * Update doctor schedule/working hours
     *
     * @param int   $user_id       Doctor user ID
     * @param array $working_hours Working hours data
     * @return bool|WP_Error True on success, WP_Error on failure
     * @since 1.0.0
     */
    public static function update_schedule( $user_id, $working_hours ) {
        if ( ! self::exists( $user_id ) ) {
            return new \WP_Error(
                'doctor_not_found',
                'Doctor not found',
                array( 'status' => 404 )
            );
        }

        // Validate working hours format
        $validation = self::validate_working_hours( $working_hours );
        if ( is_wp_error( $validation ) ) {
            return $validation;
        }

        update_user_meta( $user_id, 'working_hours', wp_json_encode( $working_hours ) );

        return true;
    }

    /**
     * Get doctor appointments
     *
     * @param int   $user_id Doctor user ID
     * @param array $args    Query arguments
     * @return array Doctor appointments
     * @since 1.0.0
     */
    public static function get_appointments( $user_id, $args = array() ) {
        global $wpdb;

        $defaults = array(
            'status' => null,
            'date_from' => null,
            'date_to' => null,
            'clinic_id' => null,
            'limit' => 50,
            'offset' => 0,
            'orderby' => 'appointment_start_date',
            'order' => 'ASC'
        );

        $args = wp_parse_args( $args, $defaults );

        $where_clauses = array( 'doctor_id = %d' );
        $where_values = array( $user_id );

        if ( ! is_null( $args['status'] ) ) {
            $where_clauses[] = 'status = %d';
            $where_values[] = $args['status'];
        }

        if ( ! is_null( $args['date_from'] ) ) {
            $where_clauses[] = 'appointment_start_date >= %s';
            $where_values[] = $args['date_from'];
        }

        if ( ! is_null( $args['date_to'] ) ) {
            $where_clauses[] = 'appointment_start_date <= %s';
            $where_values[] = $args['date_to'];
        }

        if ( ! is_null( $args['clinic_id'] ) ) {
            $where_clauses[] = 'clinic_id = %d';
            $where_values[] = $args['clinic_id'];
        }

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

        // Whitelist for orderby
        $allowed_orderby = array( 'appointment_start_date', 'status', 'patient_name', 'clinic_name' );
        $orderby = in_array( $args['orderby'], $allowed_orderby, true ) ? $args['orderby'] : 'appointment_start_date';

        // Whitelist for order
        $order = in_array( strtoupper( $args['order'] ), array( 'ASC', 'DESC' ), true ) ? strtoupper( $args['order'] ) : 'ASC';

        $query = $wpdb->prepare(
            "SELECT a.*, 
                    CONCAT(p.first_name, ' ', p.last_name) as patient_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}kc_clinics c ON a.clinic_id = c.id
             WHERE {$where_sql}
             ORDER BY {$orderby} {$order}
             LIMIT %d OFFSET %d",
            array_merge( $where_values, array( $args['limit'], $args['offset'] ) )
        );

        $appointments = $wpdb->get_results( $query, ARRAY_A );

        return array_map( function( $appointment ) {
            return array(
                'id' => (int) $appointment['id'],
                'start_date' => $appointment['appointment_start_date'],
                'start_time' => $appointment['appointment_start_time'],
                'end_date' => $appointment['appointment_end_date'],
                'end_time' => $appointment['appointment_end_time'],
                'visit_type' => $appointment['visit_type'],
                'status' => (int) $appointment['status'],
                'patient' => array(
                    'id' => (int) $appointment['patient_id'],
                    'name' => $appointment['patient_name']
                ),
                'clinic' => array(
                    'id' => (int) $appointment['clinic_id'],
                    'name' => $appointment['clinic_name']
                ),
                'description' => $appointment['description'],
                'appointment_report' => $appointment['appointment_report'],
                'created_at' => $appointment['created_at']
            );
        }, $appointments );
    }

    /**
     * Assign doctor to clinic
     *
     * @param int $user_id   Doctor user ID
     * @param int $clinic_id Clinic ID
     * @return bool|WP_Error True on success, WP_Error on failure
     * @since 1.0.0
     */
    public static function assign_to_clinic( $user_id, $clinic_id ) {
        global $wpdb;

        // Check if clinic exists
        if ( ! Clinic::exists( $clinic_id ) ) {
            return new \WP_Error(
                'clinic_not_found',
                'Clinic not found',
                array( 'status' => 404 )
            );
        }

        // Check if mapping already exists
        $existing_mapping = $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->prefix}kc_doctor_clinic_mappings 
                 WHERE doctor_id = %d AND clinic_id = %d",
                $user_id, $clinic_id
            )
        );

        if ( (int) $existing_mapping > 0 ) {
            return true; // Already assigned
        }

        // Create new mapping
        $result = $wpdb->insert(
            "{$wpdb->prefix}kc_doctor_clinic_mappings",
            array(
                'doctor_id' => $user_id,
                'clinic_id' => $clinic_id,
                'created_at' => current_time( 'mysql' )
            ),
            array( '%d', '%d', '%s' )
        );

        if ( $result === false ) {
            return new \WP_Error(
                'clinic_assignment_failed',
                'Failed to assign doctor to clinic: ' . $wpdb->last_error,
                array( 'status' => 500 )
            );
        }

        return true;
    }

    /**
     * Check if doctor exists
     *
     * @param int $user_id Doctor user ID
     * @return bool True if exists, false otherwise
     * @since 1.0.0
     */
    public static function exists( $user_id ) {
        $user = get_user_by( 'id', $user_id );
        return $user && in_array( 'kivicare_doctor', $user->roles );
    }

    /**
     * Check if doctor has dependencies (appointments, encounters, etc.)
     *
     * @param int $user_id Doctor user ID
     * @return bool True if has dependencies, false otherwise
     * @since 1.0.0
     */
    private static function has_dependencies( $user_id ) {
        global $wpdb;

        // Check appointments
        $appointments_count = $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->prefix}kc_appointments WHERE doctor_id = %d",
                $user_id
            )
        );

        if ( (int) $appointments_count > 0 ) {
            return true;
        }

        // Check encounters
        $encounters_count = $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->prefix}kc_patient_encounters WHERE doctor_id = %d",
                $user_id
            )
        );

        return (int) $encounters_count > 0;
    }

    /**
     * Validate doctor data
     *
     * @param array $doctor_data Doctor data to validate
     * @return bool|WP_Error True if valid, WP_Error if invalid
     * @since 1.0.0
     */
    private static function validate_doctor_data( $doctor_data ) {
        $errors = array();

        // Check required fields
        foreach ( self::$required_fields as $field ) {
            if ( empty( $doctor_data[ $field ] ) ) {
                $errors[] = "Field '{$field}' is required";
            }
        }

        // Validate email format
        if ( ! empty( $doctor_data['user_email'] ) && ! is_email( $doctor_data['user_email'] ) ) {
            $errors[] = 'Invalid email format';
        }

        // Check for duplicate email
        if ( ! empty( $doctor_data['user_email'] ) ) {
            $existing_user = get_user_by( 'email', $doctor_data['user_email'] );
            if ( $existing_user ) {
                $errors[] = 'A user with this email already exists';
            }
        }

        // Validate consultation fee
        if ( isset( $doctor_data['consultation_fee'] ) && 
             ! is_numeric( $doctor_data['consultation_fee'] ) ) {
            $errors[] = 'Invalid consultation fee. Must be a number';
        }

        // Validate experience years
        if ( isset( $doctor_data['experience_years'] ) && 
             ( ! is_numeric( $doctor_data['experience_years'] ) || 
               (int) $doctor_data['experience_years'] < 0 ) ) {
            $errors[] = 'Invalid experience years. Must be a positive number';
        }

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

        return true;
    }

    /**
     * Validate working hours format
     *
     * @param array $working_hours Working hours data
     * @return bool|WP_Error True if valid, WP_Error if invalid
     * @since 1.0.0
     */
    private static function validate_working_hours( $working_hours ) {
        if ( ! is_array( $working_hours ) ) {
            return new \WP_Error(
                'invalid_working_hours',
                'Working hours must be an array',
                array( 'status' => 400 )
            );
        }

        $valid_days = array( 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' );

        foreach ( $working_hours as $day => $hours ) {
            if ( ! in_array( strtolower( $day ), $valid_days ) ) {
                return new \WP_Error(
                    'invalid_day',
                    "Invalid day: {$day}",
                    array( 'status' => 400 )
                );
            }

            if ( isset( $hours['start_time'] ) && isset( $hours['end_time'] ) ) {
                // Validate time format (HH:MM)
                if ( ! preg_match( '/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/', $hours['start_time'] ) ||
                     ! preg_match( '/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/', $hours['end_time'] ) ) {
                    return new \WP_Error(
                        'invalid_time_format',
                        'Time must be in HH:MM format',
                        array( 'status' => 400 )
                    );
                }
            }
        }

        return true;
    }

    /**
     * Generate unique username for doctor
     *
     * @param array $doctor_data Doctor data
     * @return string Unique username
     * @since 1.0.0
     */
    private static function generate_unique_username( $doctor_data ) {
        $base_username = 'dr.' . strtolower( 
            $doctor_data['first_name'] . '.' . $doctor_data['last_name'] 
        );
        $base_username = sanitize_user( $base_username );
        
        $username = $base_username;
        $counter = 1;
        
        while ( username_exists( $username ) ) {
            $username = $base_username . $counter;
            $counter++;
        }
        
        return $username;
    }

    /**
     * Get doctor appointment count
     *
     * @param int $user_id Doctor user ID
     * @return int Total appointments
     * @since 1.0.0
     */
    private static function get_appointment_count( $user_id ) {
        global $wpdb;

        return (int) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->prefix}kc_appointments WHERE doctor_id = %d",
                $user_id
            )
        );
    }

    /**
     * Get doctor patient count
     *
     * @param int $user_id Doctor user ID
     * @return int Unique patients treated
     * @since 1.0.0
     */
    private static function get_patient_count( $user_id ) {
        global $wpdb;

        return (int) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(DISTINCT patient_id) FROM {$wpdb->prefix}kc_appointments WHERE doctor_id = %d",
                $user_id
            )
        );
    }

    /**
     * Get doctor rating (placeholder for future implementation)
     *
     * @param int $user_id Doctor user ID
     * @return float Doctor rating
     * @since 1.0.0
     */
    private static function get_doctor_rating( $user_id ) {
        // Placeholder for future rating system
        return 0.0;
    }

    /**
     * Get doctor statistics
     *
     * @param int $user_id Doctor user ID
     * @return array Doctor statistics
     * @since 1.0.0
     */
    public static function get_statistics( $user_id ) {
        global $wpdb;

        $stats = array(
            'total_appointments' => self::get_appointment_count( $user_id ),
            'total_patients' => self::get_patient_count( $user_id ),
            'appointments_today' => 0,
            'appointments_this_week' => 0,
            'appointments_this_month' => 0,
            'completed_encounters' => 0,
            'revenue_this_month' => 0
        );

        // Appointments today
        $stats['appointments_today'] = (int) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->prefix}kc_appointments 
                 WHERE doctor_id = %d AND appointment_start_date = CURDATE()",
                $user_id
            )
        );

        // Appointments this week
        $stats['appointments_this_week'] = (int) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->prefix}kc_appointments 
                 WHERE doctor_id = %d AND WEEK(appointment_start_date) = WEEK(CURDATE()) 
                 AND YEAR(appointment_start_date) = YEAR(CURDATE())",
                $user_id
            )
        );

        // Appointments this month
        $stats['appointments_this_month'] = (int) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->prefix}kc_appointments 
                 WHERE doctor_id = %d AND MONTH(appointment_start_date) = MONTH(CURDATE()) 
                 AND YEAR(appointment_start_date) = YEAR(CURDATE())",
                $user_id
            )
        );

        // Completed encounters
        $stats['completed_encounters'] = (int) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->prefix}kc_patient_encounters 
                 WHERE doctor_id = %d AND status = 1",
                $user_id
            )
        );

        // Revenue this month (if bills have doctor association)
        $consultation_fee = (float) get_user_meta( $user_id, 'consultation_fee', true );
        if ( $consultation_fee > 0 ) {
            $stats['revenue_this_month'] = $stats['appointments_this_month'] * $consultation_fee;
        }

        return $stats;
    }
}