<?php
/**
 * Patient REST API Endpoints
 *
 * Handles all patient-related REST API endpoints
 *
 * @package Care_API
 * @subpackage Endpoints
 * @version    1.0.0
 * @author     Descomplicar® <dev@descomplicar.pt>
 * @link       https://descomplicar.pt
 * @since      1.0.0
 */

namespace Care_API\Endpoints;

use Care_API\Services\Database\Patient_Service;
use Care_API\Services\Auth_Service;
use Care_API\Utils\Input_Validator;
use Care_API\Utils\Error_Handler;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

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

/**
 * Class Patient_Endpoints
 *
 * REST API endpoints for patient management
 *
 * @since 1.0.0
 */
class Patient_Endpoints {

    /**
     * API namespace
     *
     * @var string
     */
    private const NAMESPACE = 'care/v1';

    /**
     * Register all patient endpoints
     *
     * @since 1.0.0
     */
    public static function register_routes() {
        // Create patient
        register_rest_route( self::NAMESPACE, '/patients', array(
            'methods' => 'POST',
            'callback' => array( self::class, 'create_patient' ),
            'permission_callback' => array( Auth_Service::class, 'check_authentication' ),
            'args' => self::get_create_patient_args()
        ) );

        // Get single patient
        register_rest_route( self::NAMESPACE, '/patients/(?P<id>\d+)', array(
            'methods' => 'GET',
            'callback' => array( self::class, 'get_patient' ),
            'permission_callback' => array( Auth_Service::class, 'check_authentication' ),
            'args' => array(
                'id' => array(
                    'required' => true,
                    'validate_callback' => function( $param ) {
                        return is_numeric( $param );
                    },
                    'sanitize_callback' => 'absint'
                )
            )
        ) );

        // Update patient
        register_rest_route( self::NAMESPACE, '/patients/(?P<id>\d+)', array(
            'methods' => 'PUT',
            'callback' => array( self::class, 'update_patient' ),
            'permission_callback' => array( Auth_Service::class, 'check_authentication' ),
            'args' => self::get_update_patient_args()
        ) );

        // Search patients
        register_rest_route( self::NAMESPACE, '/patients/search', array(
            'methods' => 'GET',
            'callback' => array( self::class, 'search_patients' ),
            'permission_callback' => array( Auth_Service::class, 'check_authentication' ),
            'args' => self::get_search_args()
        ) );

        // Get patient dashboard
        register_rest_route( self::NAMESPACE, '/patients/(?P<id>\d+)/dashboard', array(
            'methods' => 'GET',
            'callback' => array( self::class, 'get_patient_dashboard' ),
            'permission_callback' => array( Auth_Service::class, 'check_authentication' ),
            'args' => array(
                'id' => array(
                    'required' => true,
                    'validate_callback' => function( $param ) {
                        return is_numeric( $param );
                    },
                    'sanitize_callback' => 'absint'
                )
            )
        ) );

        // Get patient medical history
        register_rest_route( self::NAMESPACE, '/patients/(?P<id>\d+)/history', array(
            'methods' => 'GET',
            'callback' => array( self::class, 'get_patient_history' ),
            'permission_callback' => array( Auth_Service::class, 'check_authentication' ),
            'args' => array(
                'id' => array(
                    'required' => true,
                    'validate_callback' => function( $param ) {
                        return is_numeric( $param );
                    },
                    'sanitize_callback' => 'absint'
                ),
                'type' => array(
                    'validate_callback' => function( $param ) {
                        return in_array( $param, array( 'encounters', 'appointments', 'prescriptions', 'bills', 'all' ) );
                    },
                    'sanitize_callback' => 'sanitize_text_field',
                    'default' => 'all'
                )
            )
        ) );

        // Bulk operations
        register_rest_route( self::NAMESPACE, '/patients/bulk', array(
            'methods' => 'POST',
            'callback' => array( self::class, 'bulk_operations' ),
            'permission_callback' => array( Auth_Service::class, 'check_authentication' ),
            'args' => self::get_bulk_operation_args()
        ) );
    }

    /**
     * Create a new patient
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     * @since 1.0.0
     */
    public static function create_patient( WP_REST_Request $request ) {
        try {
            $data = $request->get_json_params();
            
            // Validate required fields
            $validation = Input_Validator::validate_patient_data( $data, 'create' );
            if ( is_wp_error( $validation ) ) {
                return $validation;
            }

            // Sanitize input data
            $patient_data = Input_Validator::sanitize_patient_data( $data );
            
            $result = Patient_Service::create_patient( $patient_data, $patient_data['clinic_id'] );
            
            if ( is_wp_error( $result ) ) {
                return Error_Handler::handle_service_error( $result );
            }

            return new WP_REST_Response( array(
                'success' => true,
                'message' => 'Patient created successfully',
                'data' => $result
            ), 201 );

        } catch ( Exception $e ) {
            return Error_Handler::handle_exception( $e );
        }
    }

    /**
     * Get single patient
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     * @since 1.0.0
     */
    public static function get_patient( WP_REST_Request $request ) {
        try {
            $patient_id = $request['id'];
            
            $result = Patient_Service::get_patient_with_metadata( $patient_id );
            
            if ( is_wp_error( $result ) ) {
                return Error_Handler::handle_service_error( $result );
            }

            return new WP_REST_Response( array(
                'success' => true,
                'data' => $result
            ), 200 );

        } catch ( Exception $e ) {
            return Error_Handler::handle_exception( $e );
        }
    }

    /**
     * Update patient
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     * @since 1.0.0
     */
    public static function update_patient( WP_REST_Request $request ) {
        try {
            $patient_id = $request['id'];
            $data = $request->get_json_params();
            
            // Validate input data
            $validation = Input_Validator::validate_patient_data( $data, 'update' );
            if ( is_wp_error( $validation ) ) {
                return $validation;
            }

            // Sanitize input data
            $patient_data = Input_Validator::sanitize_patient_data( $data );
            
            $result = Patient_Service::update_patient( $patient_id, $patient_data );
            
            if ( is_wp_error( $result ) ) {
                return Error_Handler::handle_service_error( $result );
            }

            return new WP_REST_Response( array(
                'success' => true,
                'message' => 'Patient updated successfully',
                'data' => $result
            ), 200 );

        } catch ( Exception $e ) {
            return Error_Handler::handle_exception( $e );
        }
    }

    /**
     * Search patients
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     * @since 1.0.0
     */
    public static function search_patients( WP_REST_Request $request ) {
        try {
            $params = $request->get_params();
            $search_term = sanitize_text_field( $params['q'] ?? '' );
            $clinic_id = absint( $params['clinic_id'] ?? 0 );
            
            if ( empty( $search_term ) ) {
                return new WP_Error(
                    'missing_search_term',
                    'Search term is required',
                    array( 'status' => 400 )
                );
            }

            if ( empty( $clinic_id ) ) {
                return new WP_Error(
                    'missing_clinic_id',
                    'Clinic ID is required',
                    array( 'status' => 400 )
                );
            }

            $filters = array();
            if ( ! empty( $params['age_min'] ) ) {
                $filters['age_min'] = absint( $params['age_min'] );
            }
            if ( ! empty( $params['age_max'] ) ) {
                $filters['age_max'] = absint( $params['age_max'] );
            }
            if ( ! empty( $params['gender'] ) ) {
                $filters['gender'] = sanitize_text_field( $params['gender'] );
            }
            if ( isset( $params['status'] ) ) {
                $filters['status'] = absint( $params['status'] );
            }
            
            $result = Patient_Service::search_patients( $search_term, $clinic_id, $filters );
            
            return new WP_REST_Response( array(
                'success' => true,
                'data' => $result
            ), 200 );

        } catch ( Exception $e ) {
            return Error_Handler::handle_exception( $e );
        }
    }

    /**
     * Get patient dashboard
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     * @since 1.0.0
     */
    public static function get_patient_dashboard( WP_REST_Request $request ) {
        try {
            $patient_id = $request['id'];
            
            $result = Patient_Service::get_patient_dashboard( $patient_id );
            
            if ( is_wp_error( $result ) ) {
                return Error_Handler::handle_service_error( $result );
            }

            return new WP_REST_Response( array(
                'success' => true,
                'data' => $result
            ), 200 );

        } catch ( Exception $e ) {
            return Error_Handler::handle_exception( $e );
        }
    }

    /**
     * Get patient medical history
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     * @since 1.0.0
     */
    public static function get_patient_history( WP_REST_Request $request ) {
        try {
            $patient_id = $request['id'];
            $type = $request['type'] ?? 'all';
            
            $result = array();
            
            switch ( $type ) {
                case 'encounters':
                    // Would call Encounter_Service::get_patient_encounter_history
                    $result = array( 'encounters' => array() ); // Placeholder
                    break;
                    
                case 'appointments':
                    // Would call Appointment_Service::get_patient_appointments
                    $result = array( 'appointments' => array() ); // Placeholder
                    break;
                    
                case 'prescriptions':
                    // Would call Prescription_Service::get_patient_prescription_history
                    $result = array( 'prescriptions' => array() ); // Placeholder
                    break;
                    
                case 'bills':
                    // Would call Bill_Service::get_patient_bills
                    $result = array( 'bills' => array() ); // Placeholder
                    break;
                    
                case 'all':
                default:
                    $patient = Patient_Service::get_patient_with_metadata( $patient_id );
                    if ( is_wp_error( $patient ) ) {
                        return Error_Handler::handle_service_error( $patient );
                    }
                    
                    $result = array(
                        'encounters' => $patient['encounters'] ?? array(),
                        'appointments' => $patient['appointments'] ?? array(),
                        'prescriptions' => $patient['prescriptions'] ?? array(),
                        'bills' => $patient['bills'] ?? array(),
                        'medical_history' => $patient['medical_history'] ?? array()
                    );
                    break;
            }

            return new WP_REST_Response( array(
                'success' => true,
                'data' => $result
            ), 200 );

        } catch ( Exception $e ) {
            return Error_Handler::handle_exception( $e );
        }
    }

    /**
     * Bulk operations on patients
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     * @since 1.0.0
     */
    public static function bulk_operations( WP_REST_Request $request ) {
        try {
            $data = $request->get_json_params();
            $action = sanitize_text_field( $data['action'] ?? '' );
            $patient_ids = array_map( 'absint', $data['patient_ids'] ?? array() );
            
            if ( empty( $action ) || empty( $patient_ids ) ) {
                return new WP_Error(
                    'invalid_bulk_data',
                    'Action and patient IDs are required',
                    array( 'status' => 400 )
                );
            }

            $results = array();
            $errors = array();

            switch ( $action ) {
                case 'activate':
                    foreach ( $patient_ids as $patient_id ) {
                        $result = Patient_Service::update_patient( $patient_id, array( 'status' => 1 ) );
                        if ( is_wp_error( $result ) ) {
                            $errors[] = array( 'id' => $patient_id, 'error' => $result->get_error_message() );
                        } else {
                            $results[] = array( 'id' => $patient_id, 'status' => 'activated' );
                        }
                    }
                    break;

                case 'deactivate':
                    foreach ( $patient_ids as $patient_id ) {
                        $result = Patient_Service::update_patient( $patient_id, array( 'status' => 0 ) );
                        if ( is_wp_error( $result ) ) {
                            $errors[] = array( 'id' => $patient_id, 'error' => $result->get_error_message() );
                        } else {
                            $results[] = array( 'id' => $patient_id, 'status' => 'deactivated' );
                        }
                    }
                    break;

                default:
                    return new WP_Error(
                        'invalid_bulk_action',
                        'Invalid bulk action',
                        array( 'status' => 400 )
                    );
            }

            return new WP_REST_Response( array(
                'success' => true,
                'message' => 'Bulk operation completed',
                'results' => $results,
                'errors' => $errors
            ), 200 );

        } catch ( Exception $e ) {
            return Error_Handler::handle_exception( $e );
        }
    }

    /**
     * Get arguments for create patient endpoint
     *
     * @return array
     * @since 1.0.0
     */
    private static function get_create_patient_args() {
        return array(
            'first_name' => array(
                'required' => true,
                'validate_callback' => function( $param ) {
                    return ! empty( $param ) && is_string( $param );
                },
                'sanitize_callback' => 'sanitize_text_field'
            ),
            'last_name' => array(
                'required' => true,
                'validate_callback' => function( $param ) {
                    return ! empty( $param ) && is_string( $param );
                },
                'sanitize_callback' => 'sanitize_text_field'
            ),
            'clinic_id' => array(
                'required' => true,
                'validate_callback' => function( $param ) {
                    return is_numeric( $param ) && $param > 0;
                },
                'sanitize_callback' => 'absint'
            ),
            'user_email' => array(
                'validate_callback' => function( $param ) {
                    return empty( $param ) || is_email( $param );
                },
                'sanitize_callback' => 'sanitize_email'
            ),
            'contact_no' => array(
                'validate_callback' => 'rest_validate_request_arg',
                'sanitize_callback' => 'sanitize_text_field'
            ),
            'dob' => array(
                'validate_callback' => 'rest_validate_request_arg',
                'sanitize_callback' => 'sanitize_text_field'
            ),
            'gender' => array(
                'validate_callback' => function( $param ) {
                    return empty( $param ) || in_array( strtolower( $param ), array( 'male', 'female', 'other' ) );
                },
                'sanitize_callback' => 'sanitize_text_field'
            ),
            'blood_group' => array(
                'validate_callback' => 'rest_validate_request_arg',
                'sanitize_callback' => 'sanitize_text_field'
            ),
            'address' => array(
                'validate_callback' => 'rest_validate_request_arg',
                'sanitize_callback' => 'sanitize_textarea_field'
            )
        );
    }

    /**
     * Get arguments for update patient endpoint
     *
     * @return array
     * @since 1.0.0
     */
    private static function get_update_patient_args() {
        $args = self::get_create_patient_args();
        // Make all fields optional for update
        foreach ( $args as &$arg ) {
            $arg['required'] = false;
        }
        return $args;
    }

    /**
     * Get arguments for search endpoint
     *
     * @return array
     * @since 1.0.0
     */
    private static function get_search_args() {
        return array(
            'q' => array(
                'required' => true,
                'validate_callback' => function( $param ) {
                    return ! empty( $param ) && is_string( $param );
                },
                'sanitize_callback' => 'sanitize_text_field'
            ),
            'clinic_id' => array(
                'required' => true,
                'validate_callback' => function( $param ) {
                    return is_numeric( $param ) && $param > 0;
                },
                'sanitize_callback' => 'absint'
            ),
            'age_min' => array(
                'validate_callback' => function( $param ) {
                    return is_numeric( $param ) && $param >= 0;
                },
                'sanitize_callback' => 'absint'
            ),
            'age_max' => array(
                'validate_callback' => function( $param ) {
                    return is_numeric( $param ) && $param >= 0;
                },
                'sanitize_callback' => 'absint'
            ),
            'gender' => array(
                'validate_callback' => function( $param ) {
                    return in_array( strtolower( $param ), array( 'male', 'female', 'other' ) );
                },
                'sanitize_callback' => 'sanitize_text_field'
            ),
            'status' => array(
                'validate_callback' => function( $param ) {
                    return in_array( $param, array( 0, 1, '0', '1' ) );
                },
                'sanitize_callback' => 'absint'
            )
        );
    }

    /**
     * Get arguments for bulk operations endpoint
     *
     * @return array
     * @since 1.0.0
     */
    private static function get_bulk_operation_args() {
        return array(
            'action' => array(
                'required' => true,
                'validate_callback' => function( $param ) {
                    return in_array( $param, array( 'activate', 'deactivate' ) );
                },
                'sanitize_callback' => 'sanitize_text_field'
            ),
            'patient_ids' => array(
                'required' => true,
                'validate_callback' => function( $param ) {
                    return is_array( $param ) && ! empty( $param );
                },
                'sanitize_callback' => function( $param ) {
                    return array_map( 'absint', $param );
                }
            )
        );
    }
}