<?php

namespace RxConnexionBundle\Controller;

use Firebase\JWT\JWT;
use function GuzzleHttp\Psr7\str;
use RxConnexionBundle\Entity\AccountUserEntity;
use RxConnexionBundle\Entity\AccountUserOtherAccessEntity;
use RxConnexionBundle\Entity\PatientChartNoteEntity;
use RxConnexionBundle\Entity\PatientNoteEntity;
use RxConnexionBundle\Entity\ReferralEntity;
use RxConnexionBundle\Entity\RxApiLogEntity;
use RxConnexionBundle\Entity\RxApiSessionEntity;
use RxConnexionBundle\Entity\UserAccessEntity;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

use RxConnexionBundle\Entity\GeneralUserEntity;
use Symfony\Component\Serializer\Encoder\JsonEncode;

/**
 * @Route("/rx/api")
 */
class RxApiController extends Controller
{

    //<editor-fold desc="AUTH">
    
    /**
     * @Route("/login", name="rx_api_login")
     */
    public function loginAction(Request $request){

        $logData = array(
            'Action' => 'Login',
            'Request Data' => null,
            'Outgoing Data' => null,
        );
        $request = $this->validateRequest($request);

        if($request['success']){
            $requestData = $request['data'];
            $logData['Request Data'] = $requestData;

            if(isset($requestData['username']) && isset($requestData['password'])) {
                $username = $requestData['username'];
                $password = $requestData['password'];
                $em = $this->em();

                $userType = 'Account';
                $user = $em->getRepository('RxConnexionBundle:AccountUserEntity')->findOneBy(array('username' => $username, 'isActive' => true, 'isDeleted' => false));
                if($user && ($user->getPassword() === crypt(md5($password), $user->getPassword()) || $user->getPassword() === $password)) {

                    $sessionToken = md5($user->getId() . '-' . uniqid() . '-' . rand(0, 999));
                    $rxApiSession = new RxApiSessionEntity();
                    $rxApiSession->setAccountUser($user);
                    $rxApiSession->setToken($sessionToken);
                    $rxApiSession->setExpiry(new \DateTime(date('Y-m-d H:i:s', strtotime('+1 day'))));
                    $em->persist($rxApiSession);
                    $em->flush();

                    $userData = array(
                        'userType'      => $userType,
                        'id'            => $user->getId(),
                        'username'      => $user->getUsername(),
                        'firstName'     => $user->getFirstName(),
                        'middleName'    => $user->getMiddleName(),
                        'fullName'      => $user->getFullName(),
                        'type'          => ($userType === 'System' ? $user->getType() : $user->getAccountUserType()->getDescription()),
                        'accountId'     => ($userType === 'System' ? 0 : $user->getAccountUserType()->getAccount()->getId()),
                        'sessionToken'  => $sessionToken
                    );

                    $result['success'] = true;
                    $result['userData'] = $userData;

                }else{
                    $result = array('success' => false, 'msg' => 'Invalid username or password.');
                }

            } else {
                $result = array('success' => false, 'msg' => 'Please enter your Username and Password.');
            }
        } else {
            $result = array('success' => false, 'msg' => 'Request is not valid. Contact administrator.');
        }

        $logData['Outgoing Data'] = $result;
        $this->appendLogs('login', json_encode($logData));

        return new JsonResponse($result);
    }
    
    /**
     * @Route("/get/user-data", name="rx_api_get_user_data")
     */
    public function user_dataAction(Request $request){
        $logData = array(
            'Action' => 'Get User Data',
            'Request Data' => null,
            'Outgoing Data' => null,
        );

        $request = $this->validateRequest($request);

        if($request['success']){
            $requestData = $request['data'];
            $logData['Request Data'] = $requestData;

            if(isset($requestData['sessionToken']) && isset($requestData['userId'])) {
                $sessionToken = $requestData['sessionToken'];
                $em = $this->em();

                if($em->getRepository(RxApiSessionEntity::class)->isSessionTokenValid($requestData['userId'], $sessionToken)){
                    /**@var AccountUserEntity $user*/
                    /**@var UserAccessEntity $userAccesses*/
                    /**@var AccountUserOtherAccessEntity $userOtherAccess*/
                    $user = $em->getRepository(AccountUserEntity::class)->find($requestData['userId']);
                    $userAccesses = $em->getRepository('RxConnexionBundle:UserAccessEntity')->findBy(array('type' => $user->getAccountUserType()->getDescription()));

                    $accesses = array();

                    foreach($userAccesses as $userAccess) {
                        $accesses[] = $userAccess->getDescription();
                    }

                    foreach($user->getUserOtherAccessesByType('Add') as $userOtherAccess) {
                        if(!in_array($userOtherAccess->getDescription(), $accesses)) {
                            $accesses[] = $userOtherAccess->getDescription();
                        }
                    }

                    $userOtherAccesses = $user->getUserOtherAccessesByType('Restrict');
                    if(count($userOtherAccesses)) {
                        foreach($userOtherAccesses as $userOtherAccess) {
                            if(FALSE !== $key = array_search($userOtherAccess->getDescription(), $accesses)) {
                                unset($accesses[$key]);
                            }
                        }
                        $accesses = array_values($accesses);
                    }

                    $userData = array(
                        'userType'      => 'Account',
                        'id'            => $user->getId(),
                        'username'      => $user->getUsername(),
                        'firstName'     => $user->getFirstName(),
                        'middleName'    => $user->getMiddleName(),
                        'fullName'      => $user->getFullName(),
                        'type'          => $user->getAccountUserType()->getDescription(),
                        'accountId'     => $user->getAccountUserType()->getAccount()->getId(),
                        'sessionToken'  => $sessionToken,
                        'accesses'      => $accesses,
                    );
                    $result = array(
                      'success' => true,
                      'userData' => $userData,
                    );
                } else {
                    $result = array('success' => false, 'msg' => 'Your session has expired. Please login again.');
                }

            } else {
                $result = array('success' => false, 'msg' => 'Incomplete request data. Please try again, if problem persist please contact app developer.');
            }
        } else {
            $result = array('success' => false, 'msg' => 'Request is not valid. Contact administrator.');
        }

        $logData['Outgoing Data'] = $result;
        $this->appendLogs('get-user-data', json_encode($logData));

        return new JsonResponse($result);
    }

    //</editor-fold>



    //<editor-fold desc="PATIENT">

    /**
     * @Route("/patient/get", name="rx_api_patient_get")
     */
    public function patient_getAction(Request $request){

        $result = array();

        $postData = $request->request->all();

        $logData = '[' . date('Y-m-d H:i:s') . ']';
        $logData .= ' Post Data: ' . json_encode($postData);


        $userId = $request->request->get('userId');
        $sessionToken = $request->request->get('sessionToken');
        $searchText = $request->request->get('searchText');

        $em = $this->em();
        if($this->isUserHasAccesses($userId, array('Admin Patient'))) {
            if($em->getRepository(RxApiSessionEntity::class)->isSessionTokenValid($userId, $sessionToken)) {

                $data = $em->getRepository('RxConnexionBundle:PatientEntity')->rx_patient_list($userId, $searchText);

                $result['success'] = true;
                $result['patients'] = $data['results'];
            } else {
                $result = array('success' => false, 'msg' => 'Your session has expired. Please login again.');
            }
        } else {
            $result['success'] = false;
            $result['msg'] = 'RXCONEXION: You don\'t have access. Please contact administrator.';
        }

        $logData .= ' Response: ' . json_encode($result) . ' [' . date('Y-m-d H:i:s') . ']';

        $this->appendLogs('patient-get', $logData);

        return new JsonResponse($result);
    }

    /**
     * @Route("/patient/details", name="rx_api_patient_details")
     */
    public function patient_detailsAction(Request $request){
        $result = array();

        $postData = $request->request->all();

        $logData = '[' . date('Y-m-d H:i:s') . ']';
        $logData .= ' Post Data: ' . json_encode($postData);

        $em = $this->em();

        if(isset($postData['userId']) && isset($postData['patientId'])){

            if($this->isUserHasAccesses($postData['userId'], array('Admin Patient Detail'))) {
                $encounter = $em->getRepository('RxConnexionBundle:PatientChartEntity')->rx_patient_encounter($postData['userId'], $postData['patientId']);
                $notes = $em->getRepository('RxConnexionBundle:PatientNoteEntity')->rx_patient_note($postData['userId'], $postData['patientId']);
                $billing = $em->getRepository('RxConnexionBundle:PatientEntity')->rx_patient_billing($postData['userId'], $postData['patientId']);
                $result['success'] = true;
                $result['encounter'] = $encounter;
                $result['notes'] = $notes;
                $result['billing'] = $billing;
            } else {
                $result['success'] = false;
                $result['msg'] = 'RXCONEXION: You don\'t have access. Please contact administrator.';
            }
        } else {
            $result['success'] = false;
            $result['msg'] = 'Invalid request data.';
        }

        $logData .= ' Response: ' . json_encode($result) . ' [' . date('Y-m-d H:i:s') . ']';

        $this->appendLogs('rx-api-patient-details', 'patient/details', $logData);
        return new JsonResponse($result);
    }

    /**
     * @Route("/patient/note/type/get", name="rx_api_patient_note_type_get")
     */
    public function patient_note_type_getAction(Request $request){

        $result = array();

        $userId = $request->request->get('userId');

        $patientNoteType = array(
            array(
                'id' => PatientNoteEntity::TYPE_CLINICAL,
                'description' => PatientNoteEntity::TYPE_CLINICAL,
            ),
            array(
                'id' => PatientNoteEntity::TYPE_BILLING,
                'description' => PatientNoteEntity::TYPE_BILLING,
            ),
            array(
                'id' => PatientNoteEntity::TYPE_APPOINTMENT,
                'description' => PatientNoteEntity::TYPE_APPOINTMENT,
            ),
            array(
                'id' => PatientNoteEntity::TYPE_SPECIALIST,
                'description' => PatientNoteEntity::TYPE_SPECIALIST,
            )
        );

        $result['success'] = true;
        $result['patientNoteType'] = $patientNoteType;

        return new JsonResponse($result);
    }

    /**
     * @Route("/patient/note/save", name="rx_api_patient_note_save")
     */
    public function patient_note_saveAction(Request $request){
        $result = array();

        $postData = $request->request->all();

        $logData = '[' . date('Y-m-d H:i:s') . ']';
        $logData .= ' Post Data: ' . json_encode($postData);

        if(isset($postData['userId']) && isset($postData['patientId']) && isset($postData['note'])){

            $user = $this->em()->getRepository('RxConnexionBundle:AccountUserEntity')->find($postData['userId']);
            $patient = $this->em()->getRepository('RxConnexionBundle:PatientEntity')->find($postData['patientId']);

            $note = json_decode($postData['note'], true);

            if($this->isUserHasAccesses($postData['userId'], array('Admin Patient Note New'))){
                if($patient){
                    $patientNote = $this->em()->getRepository('RxConnexionBundle:PatientNoteEntity')->find($note['id']);
                    if(!$patientNote){
                        $patientNote = new PatientNoteEntity();
                    }
                    $patientNote->setPatient($patient);
                    $patientNote->setType($note['type']);
                    $patientNote->setNote($note['note']);
                    $this->em()->persist($patientNote);
                    $this->em()->flush();

                    /* AFTER PERSIST FLUSH , OVERRIDE PRE-PERSIST && PRE-UPDATE DATA */
                    $patientNote->setCreatedBy($user->getUsername());
                    $patientNote->setUpdatedBy($user->getUsername());
                    $this->em()->flush();

                    $result['success'] = true;
                    $result['test'] = $postData['patientId'];
                } else {
                    $result['success'] = false;
                    $result['msg'] = 'Patient not found.';
                }
            } else {
                $result['success'] = false;
                $result['msg'] = 'RXCONEXION: You don\'t have access. Please contact administrator.';
            }


        } else {
            $result['success'] = false;
            $result['msg'] = 'Invalid request data.';
        }

        $logData .= ' Response: ' . json_encode($result) . ' [' . date('Y-m-d H:i:s') . ']';

        $this->appendLogs('rx-api-patient-note-save', 'patient/note/save', $logData);
        return new JsonResponse($result);
    }

    /**
     * @Route("/patient/encounter/statuses/get", name="rx_api_patient_encounter_statuses_get")
     */
    public function patient_encounter_statuses_getAction(Request $request) {

        $result = array();


        $postData = $request->request->all();

        $logData = '[' . date('Y-m-d H:i:s') . ']';
        $logData .= ' Post Data: ' . json_encode($postData);

        if(isset($postData['userId']) && isset($postData['encounterTypeId'])){

            $em = $this->getDoctrine()->getManager();
            $chartStatuses = $em->getRepository('RxConnexionBundle:ChartStatusEntity')->rx_get_status($postData['encounterTypeId']);

            $result['success'] = true;
            $result['statuses'] = $chartStatuses ;

        } else {
            $result['success'] = false;
            $result['msg'] = 'Invalid request data.';
        }


        $logData .= ' Response: ' . json_encode($result) . ' [' . date('Y-m-d H:i:s') . ']';

        $this->appendLogs('rx-api-patient-encounter-status-get', 'patient/encounter/status-get', $logData);
        return new JsonResponse($result);
    }

    /**
     * @Route("/patient/encounter/update", name="rx_api_patient_encounter_update")
     */
    public function patient_encounter_updateAction(Request $request) {

        $result = array();


        $postData = $request->request->all();

        $logData = '[' . date('Y-m-d H:i:s') . ']';
        $logData .= ' Post Data: ' . json_encode($postData);

        if(isset($postData['userId']) && isset($postData['statusId']) && isset($postData['patientId']) && isset($postData['note']) && isset($postData['encounterId']) && isset($postData['noteType'])){
            if($this->isUserHasAccesses($postData['userId'], array('Admin Schedule Update'))) {

                $em = $this->getDoctrine()->getManager();
                $user = $em->getRepository('RxConnexionBundle:AccountUserEntity')->find($postData['userId']);
                $patient = $em->getRepository('RxConnexionBundle:PatientEntity')->find($postData['patientId']);
                $patientChart = $em->getRepository('RxConnexionBundle:PatientChartEntity')->find($postData['encounterId']);

                if($user){
                    if($patient) {

                        $chartStatus = $em->getRepository('RxConnexionBundle:ChartStatusEntity')->find($postData['statusId']);

                        $patientChart->setChartStatus($chartStatus);

                        $patientChartNote = new PatientChartNoteEntity();
                        $patientChartNote->setPatientChart($patientChart);
                        $patientChartNote->setNote($postData['note']);
                        $em->persist($patientChartNote);
                        $patientNote = new PatientNoteEntity();
                        $patientNote->setPatient($patient);
                        $patientNote->setType($postData['noteType']);
                        $patientNote->setNote($postData['note']);
                        $em->persist($patientNote);

                        $em->flush();
                        $patientNote->setCreatedBy($user->getUsername());
                        $patientChartNote->setCreatedBy($user->getUsername());
                        $em->flush();

                    } else {
                        $result['success'] = false;
                        $result['msg'] = 'Patient not found.';
                    }
                } else {
                    $result['success'] = false;
                    $result['msg'] = 'User not found.';
                }

                $result['success'] = true;
            } else {
                $result['success'] = false;
                $result['msg'] = 'RXCONEXION: You don\'t have access. Please contact administrator.';
            }


        } else {
            $result['success'] = false;
            $result['msg'] = 'Invalid request data.';
        }


        $logData .= ' Response: ' . json_encode($result) . ' [' . date('Y-m-d H:i:s') . ']';

        $this->appendLogs('rx-api-patient-encounter-update', 'patient/encounter/update', $logData);
        return new JsonResponse($result);
    }

    //</editor-fold>
    
    
    
    //<editor-fold desc="APPOINTMENT">


    /**
     * @Route("/appointment/branch/get", name="rx_api_appointment_branch_get")
     */
    public function appointment_branch_getAction(Request $request){

        $result = array();
        $get = array();

        $userId = $request->request->get('userId');
        
        $em = $this->em();
        

        $healthFacilities = $em->getRepository('RxConnexionBundle:HealthFacilityEntity')->rx_get_all_active();

        $result['success'] = true;
        $result['branches'] = $healthFacilities;


        return new JsonResponse($result);
    }

    /**
     * @Route("/appointment/branch/providers", name="rx_api_appointment_branch_providers")
     */
    public function appointment_branch_providersAction(Request $request){

        $result = array();
        $get = array();

        $userId = $request->request->get('userId');
        $branchId = $request->request->get('branchId');
        $date = $request->request->get('date');

        $em = $this->em();

        $providers = $em->getRepository('RxConnexionBundle:ProviderHealthFacilityEntity')->rx_provider_by_health_facility($branchId, $date);

        $result['success'] = true;
        $result['providers'] = $providers;


        return new JsonResponse($result);
    }

    /**
     * @Route("/appointment/calendar/view", name="rx_api_appointment_calendar_view")
     */
    public function appointment_calendar_viewAction(Request $request) {

        $result = array();

        $userId = $request->request->get('userId');

        if($this->isUserHasAccesses($userId, array('Admin Calendar'))) {

            $branchId = $request->request->get('branchId');
            $providerId = $request->request->get('providerId');
            $date = $request->request->get('date');


            $em = $this->getDoctrine()->getManager();
            $times = array();
            $provider = $em->getRepository('RxConnexionBundle:ProviderEntity')-> rx_schedule_calendar_view_provider($branchId, $date, $providerId);
            $schedules = $em->getRepository('RxConnexionBundle:ScheduleEntity')-> rx_schedule_calendar_view_schedules_by_provider($branchId, $date, $providerId);


            $dayName = date('l', $date);
            for($i=6; $i<=20; $i++) {
                for($ii=0; $ii<60; $ii+=15) {
                    $hm = sprintf('%002d', $i) . ':' . sprintf('%002d', $ii);
                    $dt = strtotime($date . ' ' . $hm);
                    $text = date('h:i A', $dt);
                    $dtEnd = strtotime('+14 minute', $dt);
                    foreach($schedules as $schedule){
                        $sDT = strtotime($schedule['scheduleDT']);
                        $sDTEnd = strtotime($schedule['scheduleDTEnd']);
                        if(($sDT >= $dt && $sDT <= $dtEnd) || ($sDTEnd > $dt && $sDT <= $dt)){

                            if($provider['id'] != $schedule['providerId']){
                                continue;
                            }
                            if(isset($provider['schedules'])){
                                $found = false;
                                foreach($provider['schedules'] as $key2 => $providerSchedule){
                                    if($providerSchedule['id'] == $schedule['id']){
                                        $provider['schedules'][$key2]['rowSpan']++;
                                        $provider['schedules'][$key2]['rowSpanTimes'][] = $text;
                                        $found = true;
                                        break;
                                    }
                                }
                                if(!$found){
                                    $schedule['timeText'] = $text;
                                    $schedule['rowSpan'] = 1;
                                    $schedule['rowSpanTimes'] = array();
                                    $provider['schedules'][] = $schedule;
                                }
                            }else{
                                $schedule['timeText'] = $text;
                                $schedule['rowSpan'] = 1;
                                $schedule['rowSpanTimes'] = array();
                                $provider['schedules'] = array(
                                    $schedule
                                );
                            }
                        }
                    }
                    $workSchedules = array(
                        'regular' => array(),
                        'irregular' => array(),
                        'out' => array()
                    );
                    if(!isset($provider['workSchedules'])){
                        $provider['workSchedules'] = $workSchedules;
                    }
                    $providerWorkSchedules = explode('@', $provider['providerWorkSchedules']);
                    foreach ($providerWorkSchedules as $providerWorkSchedule) {
                        $workSchedule = explode('|', $providerWorkSchedule);
                        switch ($workSchedule[0]) {
                            case 'Regular' :
                                $workSchedules['regular'][] = array(
                                    'type' => $workSchedule[0],
                                    'dayName' => $workSchedule[1],
                                    'timeFrom' => $workSchedule[2],
                                    'timeTo' => $workSchedule[3],
                                    'healthFacility' => $workSchedule[4],
                                );
                                break;

                            case 'Irregular':
                                $workSchedules['irregular'][] = array(
                                    'type' => $workSchedule[0],
                                    'fromDate' => $workSchedule[1],
                                    'toDate' => $workSchedule[2],
                                    'timeFrom' => $workSchedule[3],
                                    'timeTo' => $workSchedule[4],
                                    'healthFacility' => $workSchedule[5],
                                );

                                break;

                            case 'Out':
                                $workSchedules['out'][] = array(
                                    'type' => $workSchedule[0],
                                    'fromDate' => $workSchedule[1],
                                    'toDate' => $workSchedule[2],
                                    'timeFrom' => $workSchedule[3],
                                    'timeTo' => $workSchedule[4],
                                );

                                break;

                        }
                    }
                    foreach ($workSchedules['out'] as  $wsOut){
                        $outTimeFromDT = strtotime($date . ' ' . $wsOut['timeFrom']);
                        $outTimeToDT = strtotime($date . ' ' . $wsOut['timeTo']);
                        if($dt >= $outTimeFromDT && $dt <= $outTimeToDT){
                            $provider['workSchedules']['out'][] = $text;
                        }
                    }
                    foreach ($workSchedules['irregular'] as  $wsIrregular){
                        $regularTimeFromDT = strtotime($date . ' ' . $wsIrregular['timeFrom']);
                        $regularTimeToDT = strtotime($date . ' ' . $wsIrregular['timeTo']);
                        if($dt >= $regularTimeFromDT && $dt <= $regularTimeToDT){
                            $provider['workSchedules']['irregular'][] = array(
                                'hfId' => $wsIrregular['healthFacility'],
                                'time' => $text
                            );
                        }
                    }
                    foreach ($workSchedules['regular'] as  $wsRegular){
                        $regularTimeFromDT = strtotime($date . ' ' . $wsRegular['timeFrom']);
                        $regularTimeToDT = strtotime($date . ' ' . $wsRegular['timeTo']);
                        if($dayName == $wsRegular['dayName'] && $dt >= $regularTimeFromDT && $dt <= $regularTimeToDT){
                            $provider['workSchedules']['regular'][] = $text;
                        }
                    }
                    $times[] = array(
                        'text' => $text,
                    );
                }
            }
            $result['success'] = true;
            $result['provider'] = $provider;
            $result['schedules'] = $schedules;
            $result['times'] = $times;
        } else {
            $result['success'] = false;
            $result['msg'] = 'RXCONEXION: You don\'t have access. Please contact administrator.';
        }

        return new JsonResponse($result);
    }

    /**
     * @Route("/appointment/calendar/list", name="rx_api_appointment_calendar_list")
     */
    public function appointment_calendar_listAction(Request $request) {

        $result = array();

        $userId = $request->request->get('userId');

        $branchId = $request->request->get('branchId');
        $providerId = $request->request->get('providerId');
        $date = $request->request->get('date');

        if($this->isUserHasAccesses($userId, array('Admin Calendar'))) {

            $em = $this->getDoctrine()->getManager();
            $schedules = $em->getRepository('RxConnexionBundle:ScheduleEntity')-> rx_schedule_calendar_list($branchId, $date, $providerId);
            $result['success'] = true;
            $result['schedules'] = $schedules;
        } else {
            $result['success'] = false;
            $result['msg'] = 'RXCONEXION: You don\'t have access. Please contact administrator.';

        }

        return new JsonResponse($result);
    }

    /**
     * @Route("/appointment/statuses/get", name="rx_api_appointment_statuses_get")
     */
    public function appointment_statuses_getAction(Request $request) {

        $result = array();
        $em = $this->getDoctrine()->getManager();
        $scheduleStatuses = $em->getRepository('RxConnexionBundle:ScheduleStatusEntity')-> rx_get_status();

        $result['success'] = true;
        $result['statuses'] = $scheduleStatuses;

        return new JsonResponse($result);
    }

    /**
     * @Route("/appointment/update-status", name="rx_api_appointment_update_status")
     */
    public function appointment_update_statusAction(Request $request) {

        $result = array();
        $em = $this->getDoctrine()->getManager();

        $userId = $request->request->get('userId');
        $schedule = $request->request->get('appointmentId');
        $statusId = $request->request->get('appointmentStatus');
        $note = $request->request->get('appointmentNote');

        if($this->isUserHasAccesses($userId, array('Admin Schedule Update'))) {

            $user = $em->getRepository('RxConnexionBundle:AccountUserEntity')->find($userId);
            $schedule = $em->getRepository('RxConnexionBundle:ScheduleEntity')->find($schedule);
            $status = $em->getRepository('RxConnexionBundle:ScheduleStatusEntity')->find($statusId);

            if($schedule){
                $patientChart = $em->getRepository('RxConnexionBundle:PatientChartEntity')->findOneBy(array(
                    'schedule' => $schedule->getId()
                ));

                if($patientChart->getChartStatus()){
                    $scheduleStatus = $em->getRepository('RxConnexionBundle:ScheduleStatusEntity')->find($statusId);
                }else{
                    $scheduleStatus = array();
                }
                $chartStatus = $em->getRepository('RxConnexionBundle:ChartStatusEntity')->findOneBy(array(
                    'description' => $status->getDescription(),
                    'chartType' => $schedule->getChartType()->getId()
                ));

                if($chartStatus && $scheduleStatus){
                    $patientChart->setChartStatus($chartStatus);
                }

                $patientNote = null;
                $patientChartNote = null;
                if($schedule->getNote() != $note){
                    $patientChartNote = new PatientChartNoteEntity();
                    $patientChartNote->setPatientChart($patientChart);
                    $patientChartNote->setNote($note);
                    $em->persist($patientChartNote);
                    $patientNote = new PatientNoteEntity();
                    $patientNote->setPatient($schedule->getPatient());
                    $patientNote->setType(PatientNoteEntity::TYPE_APPOINTMENT);
                    $patientNote->setNote($note);
                    $em->persist($patientNote);
                }

                $schedule->setScheduleStatus($status);
                $schedule->setNote($note);
                $em->flush();

                if(!is_null($patientChartNote) && !is_null($patientNote)){
                    $patientNote->setCreatedBy($user->getUsername());
                    $patientChartNote->setCreatedBy($user->getUsername());
                }

                $result['success'] = true;
            } else {
                $result['success'] = false;
                $result['msg'] = 'Cannot find schedule';

            }
        } else {

            $result['success'] = false;
            $result['msg'] = 'RXCONEXION: You don\'t have access. Please contact administrator.';
        }


        return new JsonResponse($result);
    }


    //</editor-fold>



    //<editor-fold desc="REPORT">

    /**
     * @Route("/report/list", name="rx_api_report_list")
     */
    public function report_listAction(Request $request){

        $logData = array(
            'Action' => 'Report List',
            'Request Data' => null,
            'Outgoing Data' => null,
        );
        $request = $this->validateRequest($request);

        if($request['success']){
            $requestData = $request['data'];
            $logData['Request Data'] = $requestData;

            if(isset($requestData['sessionToken']) && isset($requestData['userId'])) {
                $sessionToken = $requestData['sessionToken'];
                $em = $this->em();

                if($em->getRepository(RxApiSessionEntity::class)->isSessionTokenValid($requestData['userId'], $sessionToken)){
                    $data = array();

                    if($this->isUserHasAccesses($requestData['userId'], array('Admin Report Encounter'))) {
                        $data[] = array(
                            'description' => 'Encounter',
                            'url' => '/report/encounter',
                            'filters' => array(
                                array(
                                    'input' => 'date',
                                    'label' => 'Date From',
                                    'name' => 'date_from',
                                    'value' => (new \DateTime())->format("Y-m-d\TH:i:s.000\Z"),
                                ),
                                array(
                                    'input' => 'date',
                                    'label' => 'Date To',
                                    'name' => 'date_to',
                                    'value' => (new \DateTime())->format("Y-m-d\TH:i:s.000\Z"),
                                ),
                            ),
                        );
                    }

                    if($this->isUserHasAccesses($requestData['userId'], array('Admin Report Accounts Receivable'))) {
                        $data[] = array(
                            'description' => 'Accounts Receivable',
                            'url' => '/report/ar',
                            'filters' => array(
                                array(
                                    'input' => 'select',
                                    'label' => 'Date Interval',
                                    'name' => 'interval',
                                    'choices' => array(
                                        array(
                                            'value' => 'All',
                                            'description' => 'All'
                                        ),
                                        array(
                                            'value' => 'Current',
                                            'description' => 'Current'
                                        ),
                                        array(
                                            'value' => '30Days',
                                            'description' => '30 Days'
                                        ),
                                        array(
                                            'value' => '60Days',
                                            'description' => '60 Days'
                                        ),
                                        array(
                                            'value' => '90Days',
                                            'description' => '90 Days'
                                        ),
                                        array(
                                            'value' => '120Days',
                                            'description' => '120 or More Days'
                                        ),
                                    ),
                                ),
                            ),
                        );
                    }

                    if($this->isUserHasAccesses($requestData['userId'], array('Admin Report Referral'))) {
                        $data[] = array(
                            'description' => 'Referral',
                            'url' => '/report/referral',
                            'filters' => array(
                                array(
                                    'input' => 'date',
                                    'label' => 'Date From',
                                    'name' => 'date_from',
                                    'value' => (new \DateTime())->format("Y-m-d\TH:i:s.000\Z"),
                                ),
                                array(
                                    'input' => 'date',
                                    'label' => 'Date To',
                                    'name' => 'date_to',
                                    'value' => (new \DateTime())->format("Y-m-d\TH:i:s.000\Z"),
                                ),
                                array(
                                    'input' => 'date',
                                    'label' => 'Received Date From',
                                    'name' => 'received_date_from',
                                    'value' => null,
                                ),
                                array(
                                    'input' => 'date',
                                    'label' => 'Received Date To',
                                    'name' => 'received_date_to',
                                    'value' => null,
                                ),
                            ),
                        );
                    }

                        $result = array(
                        'success' => true,
                        'data' => $data
                    );
                } else {
                    $result = array('success' => false, 'msg' => 'Your session has expired.');
                }
            } else {
                $result = array('success' => false, 'msg' => 'Incomplete request data. Please try again, if problem persist please contact app developer.');
            }
        } else {
            $result = array('success' => false, 'msg' => 'Request is not valid. Contact administrator.');
        }

        $logData['Outgoing Data'] = $result;
        $this->appendLogs('report-list', json_encode($logData));

        return new JsonResponse($result);
    }

    /**
     * @Route("/report/encounter", name="rx_api_report_encounter")
     */
    public function report_encounterAction(Request $request){

        $logData = array(
            'Action' => 'Report Encounter',
            'Request Data' => null,
            'Outgoing Data' => null,
        );
        $request = $this->validateRequest($request);

        if($request['success']){
            $requestData = $request['data'];
            $logData['Request Data'] = $requestData;

            if(isset($requestData['sessionToken']) && isset($requestData['userId'])) {
                $sessionToken = $requestData['sessionToken'];
                $em = $this->em();

                if($em->getRepository(RxApiSessionEntity::class)->isSessionTokenValid($requestData['userId'], $sessionToken)){

                    $filters = $requestData['data'];
                    $params = array();
                    foreach($filters as $filter){
                        $filter = (array) $filter;
                        $params[$filter['name']] = $filter['input'] == 'date' ? (new \DateTime($filter['value']))->format('m/d/Y') : $filter['value'];
                    }

                    $records = $em->getRepository('RxConnexionBundle:PatientChartEntity')->reportEncounter($params);

                    $footer = array(
                        'Total: ',
                        count($records),
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        //'',
                    );

                    $result = array(
                        'success' => true,
                        'data' => array(
                            'records' => $records,
                            'header' => array(
                                'encounterId' => 'Encounter ID',
                                'accountUser'   => 'Staff',
                                'encounterDate'   => 'Encounter Date',
                                'patient'     => 'Patient',
                                'companyDesc' => 'Company',
                                'branch'      => 'Branch',
                                'clinician'=>'Clinician',
                                'encounterType'=>'Encounter Type',
                                'encounterStatus'=>'Status',
                                //'note'        => 'Note',
                            ),
                            'footer' => $footer,
                        ),
                    );

                } else {
                    $result = array('success' => false, 'msg' => 'Your session has expired.');
                }
            } else {
                $result = array('success' => false, 'msg' => 'Incomplete request data. Please try again, if problem persist please contact app developer.');
            }
        } else {
            $result = array('success' => false, 'msg' => 'Request is not valid. Contact administrator.');
        }

        $logData['Outgoing Data'] = $result;
        $this->appendLogs('report-encounter', json_encode($logData));

        return new JsonResponse($result);
    }

    /**
     * @Route("/report/referral", name="rx_api_report_referral")
     */
    public function report_referralAction(Request $request){

        $logData = array(
            'Action' => 'Referral Report',
            'Request Data' => null,
            'Outgoing Data' => null,
        );
        $request = $this->validateRequest($request);

        if($request['success']){
            $requestData = $request['data'];
            $logData['Request Data'] = $requestData;

            if(isset($requestData['sessionToken']) && isset($requestData['userId'])) {
                $sessionToken = $requestData['sessionToken'];
                $em = $this->em();

                if($em->getRepository(RxApiSessionEntity::class)->isSessionTokenValid($requestData['userId'], $sessionToken)){

                    $filters = $requestData['data'];
                    $params = array();
                    foreach($filters as $filter){
                        $filter = (array) $filter;
                        $params[$filter['name']] = $filter['input'] == 'date' ? (new \DateTime($filter['value']))->format('m/d/Y') : $filter['value'];
                    }

                    $records =
                    $records = $em->getRepository(ReferralEntity::class)->reportReferral($params);

                    $footer = array(
                        'Total: ',
                        count($records['referral']),
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                    );

                    $result = array(
                        'success' => true,
                        'data' => array(
                            'records' => $records['referral'],
                            'header' => array(
                                'referralId' => 'Referral ID',
                                'accountUser'   => 'Staff',
                                'referral_date'   => 'Referral Date',
                                'receive_date'   => 'Received Date',
                                'patient'     => 'Patient',
                                'branch'      => 'Branch',
                                'referring_affiliate'      => 'Referring Affiliate',
                                'referring_physician'      => 'Referring Physician',
                                'chartType'      => 'Encounter Type',
                                'chartStatus'      => 'Encounter Status',
                                'letterType'      => 'Letter Type',
                                'letterStatus'      => 'Letter Status',
                                'sales_agent'      => 'Agent',
                                'note'      => 'Notes',
                            ),
                            'footer' => $footer,
                        ),
                    );

                    $footer = array(
                        'Total: ',
                        count($records['referralCount']),
                    );

                    $result['data']['summary'] = array(
                        'records' => $records['referralCount'],
                        'header' => array(
                            'referringProvider' => 'Referring Physician',
                            'referralCount' => 'Count',
                        ),
                        'footer' => $footer,
                    );

                } else {
                    $result = array('success' => false, 'msg' => 'Your session has expired.');
                }
            } else {
                $result = array('success' => false, 'msg' => 'Incomplete request data. Please try again, if problem persist please contact app developer.');
            }
        } else {
            $result = array('success' => false, 'msg' => 'Request is not valid. Contact administrator.');
        }

        $logData['Outgoing Data'] = $result;
        $this->appendLogs('report-referral', json_encode($logData));

        return new JsonResponse($result);
    }

    /**
     * @Route("/report/ar", name="rx_api_report_ar")
     */
    public function report_arAction(Request $request){

        $logData = array(
            'Action' => 'Report AR',
            'Request Data' => null,
            'Outgoing Data' => null,
        );
        $request = $this->validateRequest($request);

        if($request['success']){
            $requestData = $request['data'];
            $logData['Request Data'] = $requestData;

            if(isset($requestData['sessionToken']) && isset($requestData['userId'])) {
                $sessionToken = $requestData['sessionToken'];
                $em = $this->em();

                if($em->getRepository(RxApiSessionEntity::class)->isSessionTokenValid($requestData['userId'], $sessionToken)){

                    $filters = $requestData['data'];
                    $params = array();
                    foreach($filters as $filter){
                        $filter = (array) $filter;
                        $params[$filter['name']] = $filter['input'] == 'date' ? (new \DateTime($filter['value']))->format('m/d/Y') : $filter['value'];
                    }

                    $records = $em->getRepository('RxConnexionBundle:PatientBillingEntity')->arReport($params);


                    $totalLastPayment = 0;
                    $totalAmtBalance = 0;
                    $totalAmtInvoice = 0;
                    foreach($records as $record){
                        $totalLastPayment += floatval($record['lastPaymentAmt']);
                        $totalAmtBalance += floatval($record['amtBalance']);
                        $totalAmtInvoice += floatval($record['amtDue']);
                    }
                    $footer = array(
                        'Total:',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        number_format($totalLastPayment, 2),
                        number_format($totalAmtBalance, 2),
                        number_format($totalAmtInvoice, 2),
                        '',
                        '',
                        '',
                        '',
                    );


                    $result = array(
                        'success' => true,
                        'data' => array(
                            'records' => $records,
                            'header' => array(
                                'patient' => 'Patient',
                                'payer' => 'Payer',
                                'healthFacility_desc' => 'Billing Branch',
                                'healthFacilityForAddress_desc' => 'Billing Branch Address',
                                'notNullHealthFacility_companyDesc' => 'Company',
                                'accountPhase' => 'Account Phase',
                                'invoiceNo' =>'Invoice No.',
                                'billingDate' =>'Date',
                                'id' =>'Reference No',
                                'lastPaymentDate' =>'Last Payment',
                                'lastPaymentAmt' =>'Last Payment Amount',
                                'amtBalance' =>'Outstanding Balance',
                                'amtDue' =>'Total Invoice',
                                'patientBilling_nextDue' =>'Next Due date (Payment Plan)',
                                'patientBilling_demandLetterDate' =>'Demand Letter Date',
                                'patientBilling_insuranceClaimDate' =>'Date Claim to Insurance',
                                'lastCalled' =>'Date last called',
                                'billing_endorsedTo' =>'Endorsed To',
                                //'billingStatus' =>'Note',
                            ),
                            'footer' => $footer,
                        ),
                    );

                    $records = $em->getRepository('RxConnexionBundle:PatientBillingEntity')->arReportSummary($params);

                    $sumTotalCount = 0;
                    $sumTotalAr = 0;
                    foreach($records as $record){
                        $sumTotalCount += $record['totalCount'];
                        $sumTotalAr += $record['totalBalance'];
                    }
                    $footer = array(
                        '',
                        number_format($sumTotalCount,2),
                        number_format($sumTotalAr,2),
                    );

                    $result['data']['summary'] = array(
                        'records' => $records,
                        'header' => array(
                            'healthFacility' => 'Billing Branch',
                            'totalCount' => 'Count',
                            'totalBalance' => 'Accounts Receivable',
                        ),
                        'footer' => $footer,
                    );

                } else {
                    $result = array('success' => false, 'msg' => 'Your session has expired.');
                }
            } else {
                $result = array('success' => false, 'msg' => 'Incomplete request data. Please try again, if problem persist please contact app developer.');
            }
        } else {
            $result = array('success' => false, 'msg' => 'Request is not valid. Contact administrator.');
        }

        $logData['Outgoing Data'] = $result;
        $this->appendLogs('report-billing', json_encode($logData));

        return new JsonResponse($result);
    }

    /**
     * @Route("/report/ar/summary", name="rx_api_report_ar_summary")
     */
    public function report_ar_summaryAction(Request $request){

        $logData = array(
            'Action' => 'Report AR Summary',
            'Request Data' => null,
            'Outgoing Data' => null,
        );
        $request = $this->validateRequest($request);

        if($request['success']){
            $requestData = $request['data'];
            $logData['Request Data'] = $requestData;

            if(isset($requestData['sessionToken']) && isset($requestData['userId'])) {
                $sessionToken = $requestData['sessionToken'];
                $em = $this->em();

                if($em->getRepository(RxApiSessionEntity::class)->isSessionTokenValid($requestData['userId'], $sessionToken)){

                    $filters = $requestData['data'];
                    $params = array();
                    foreach($filters as $filter){
                        $filter = (array) $filter;
                        $params[$filter['name']] = $filter['input'] == 'date' ? (new \DateTime($filter['value']))->format('m/d/Y') : $filter['value'];
                    }

                    $records = $em->getRepository('RxConnexionBundle:PatientBillingEntity')->arReportSummary($params);


                    $sumTotalCount = 0;
                    $sumTotalAr = 0;
                    foreach($records as $record){
                        $sumTotalCount += $record['totalCount'];
                        $sumTotalAr += $record['totalBalance'];
                    }
                    $footer = array(
                        '',
                        number_format($sumTotalCount,2),
                        number_format($sumTotalAr,2),
                    );

                    $result = array(
                        'success' => true,
                        'data' => array(
                            'records' => $records,
                            'header' => array(
                                'healthFacility' => 'Billing Branch',
                                'totalCount' => 'Count',
                                'totalBalance' => 'Accounts Receivable',
                            ),
                            'footer' => $footer,
                        ),
                    );

                } else {
                    $result = array('success' => false, 'msg' => 'Your session has expired.');
                }
            } else {
                $result = array('success' => false, 'msg' => 'Incomplete request data. Please try again, if problem persist please contact app developer.');
            }
        } else {
            $result = array('success' => false, 'msg' => 'Request is not valid. Contact administrator.');
        }

        $logData['Outgoing Data'] = $result;
        $this->appendLogs('report-billing', json_encode($logData));

        return new JsonResponse($result);
    }


    //</editor-fold>



    //<editor-fold desc="MANAGEMENT DASHBOARD">

    /**
     * @Route("/management-dashboard/get-filter", name="rx_api_management_dashboard_get_filter")
     */
    public function management_dashboard_get_filter_listAction(Request $request){

        $result = array();

        $postData = $request->request->all();

        $logData = '[' . date('Y-m-d H:i:s') . ']';
        $logData .= ' Post Data: ' . json_encode($postData);

        $userId = $request->request->get('userId');

        $em = $this->em();

        $companies = $em->getRepository('RxConnexionBundle:CompanyEntity')->companiesForMultiple();
        $healthFacilities = $em->getRepository('RxConnexionBundle:HealthFacilityEntity')->rx_get_all_active();
        $provider = $em->getRepository('RxConnexionBundle:ProviderEntity')->clinicianForMultiple();

        $result['success'] = true;
        $result['filter'] = array(
            'branch' => $healthFacilities,
            'company' => $companies,
            'clinician' => $provider,
        );

        $logData .= ' Response: ' . json_encode($result) . ' [' . date('Y-m-d H:i:s') . ']';

        $this->appendLogs('report-list', $logData);

        return new JsonResponse($result);
    }

    /**
     * @Route("/management-dashboard/preview", name="rx_api_management_dashboard_preview")
     */
    public function management_dashboard_previewAction(Request $request){

        $result = array();

        $postData = $request->request->all();

        $logData = '[' . date('Y-m-d H:i:s') . ']';
        $logData .= ' Post Data: ' . json_encode($postData);

        $postData = $request->request->get('data');

        $em = $this->em();

        $params = array(
            'date_from' => (new \DateTime($postData['dateFrom']))->format('m-d-Y'),
            'date_to' => (new \DateTime($postData['dateTo']))->format('m-d-Y'),
            'company' => empty($postData['company']) ? 'null' : $postData['company'],
            'branch' => empty($postData['branch']) ? 'null' : $postData['branch'],
            'provider' => empty($postData['clinician']) ? 'null' : $postData['clinician'],
        );

        $data= null;
        switch(strtoupper($postData['type'])){
            case 'MONTHLY':
                $data = $em->getRepository('RxConnexionBundle:PatientChartEntity')->managementDashboard_monthly($params);
                break;
            case 'PRODUCTIVITY':
                $data = $em->getRepository('RxConnexionBundle:PatientChartEntity')->managementDashboard_encounters($params);
                break;
            case 'CONVERSION':
                $data = $em->getRepository('RxConnexionBundle:PatientChartEntity')->managementDashboard_conversion($params);
                break;
            case 'CYCLE OVERDUE':
                $data = $em->getRepository('RxConnexionBundle:PatientChartEntity')->managementDashboard_cycle($params);
                break;

        }


        $result['success'] = true;
        $result['data'] = $data;

        $logData .= ' Response: ' . json_encode($result) . ' [' . date('Y-m-d H:i:s') . ']';

        $this->appendLogs('report-list', $logData);

        return new JsonResponse($result);
    }


    //</editor-fold>



    // <editor-fold desc="PRIVATE FUNCTIONS">

    private function em(){
        return $this->getDoctrine()->getManager();
    }

    private function appendLogs($logName, $logData) {
        $now = (new \DateTime())->format('Y-m-d');
        $logDir = $this->getParameter('rx_api_log_dir');
        $filesystem = new Filesystem();
        $filesystem->appendToFile( $logDir .'/'. $logName . '/' . $now . '.log', '[' . date('Y-m-d H:i:s') . ']' . stripslashes($logData). "\n");
    }

    private function validateApi(Request $request){
        header('Access-Control-Allow-Origin: *');
        //header('Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, Origin');
        header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');

        $logData = '[' . date('Y-m-d H:i:s') . ']';

        //$auth = explode(' ', $request->headers->get('Authorization'));
        $postData = $request->request->all();
        //$this->appendLogs('validate-api', json_encode($postData));
        //if(isset($auth[0]) && 'Bearer' === $auth[0] && isset($auth[1])) {
        if($postData['authKey'] === $this->getParameter('rx_api_secret')) {

            /*try {
                $payload = (array)JWT::decode($auth[1], $this->getParameter('jwt_public_key'), array($this->getParameter('jwt_alg')));
            } catch (\Exception $e) {
                $payload = null;
            }
            //$logData .= ' Payload: ' . new JsonResponse($payload);
            */
            $logData .= ' Request Data: ' . json_encode($postData);

            $result = array('success' => true, 'logData' => $logData, 'postData' => $postData);
        } else {
            $result = array('success' => false, 'logData' => $logData, 'msg' => 'RXCONEXION: Invalid request. Please try again, if problem persist please contact app developer.');
        }

        return $result;
    }

    private function validateRequest(Request $request){
        $token = $request->query->get('token');
        try{
            $inboundData = (array)JWT::decode($token, $this->getParameter('rx_api_secret'), array($this->getParameter('rx_api_jwt_alg')));
            if(!is_null($inboundData)){
                $data = array(
                    'success' => true,
                    'data' => $inboundData,
                );
            } else {
                $data = array(
                    'success' => false,
                    'msg' => 'Request has no data.'
                );
            }
        } catch (\Exception $e) {
            $data = array(
                'success' => false,
                'msg' => 'Invalid Request. ' . $e->getMessage()
            );
        }
        return $data;
    }

    private function isUserHasAccesses($userId, $accessDescriptions){
        $user = $this->em()->getRepository('RxConnexionBundle:AccountUserEntity')->find($userId);

        $userAccesses = $this->em()->getRepository('RxConnexionBundle:UserAccessEntity')->findBy(array('type' => $user->getAccountUserType()->getDescription()));
        $accesses = array();

        foreach($userAccesses as $userAccess) {
            $accesses[] = $userAccess->getDescription();
        }

        foreach($user->getUserOtherAccessesByType('Add') as $userOtherAccess) {
            if(!in_array($userOtherAccess->getDescription(), $accesses)) {
                $accesses[] = $userOtherAccess->getDescription();
            }
        }

        $userOtherAccesses = $user->getUserOtherAccessesByType('Restrict');
        if(count($userOtherAccesses)) {
            foreach($userOtherAccesses as $userOtherAccess) {
                if(FALSE !== $key = array_search($userOtherAccess->getDescription(), $accesses)) {
                    unset($accesses[$key]);
                }
            }
            $accesses = array_values($accesses);
        }


        $accessCtr = 0;
        foreach($accessDescriptions as $accessDescription) if(in_array($accessDescription, $accesses)) $accessCtr++;
        $hasAccess = count($accessDescriptions) === $accessCtr;
        if(!$hasAccess) {
            return false;
        } else {
            return true;
        }
    }

    
    // </editor-fold>
}
