<?php

namespace RxConnexionBundle\Controller;

use Firebase\JWT\JWT;
use RxConnexionBundle\Entity\PatientChartNoteEntity;
use RxConnexionBundle\Entity\PatientNoteEntity;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

use RxConnexionBundle\Entity\GeneralUserEntity;

/**
 * @Route("/zap/api")
 */
class ZapApiController extends Controller
{

    /* ============================================================= */
    /* ================== FOR ZAP SYS APP ========================== */ 
    /* ============================================================= */
    
    /**
     * @Route("/login", name="zap_api_login")
     */
    public function zap_api_loginAction(Request $request){

        $result = array('success' => false);

        $username = $request->request->get('username');
        $password = $request->request->get('password');

        $em = $this->em();

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

                $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()),
                    /*'ws_token' => JWT::encode(array(
                        'session' => md5(rand(0, 999) . '-' . time()),
                        'user_id' => $user->getId()
                    ), $this->container->getParameter('ws_key'))*/
                );

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

            }else{
                $result['msg'] = 'Invalid username or password.';
            }
        } else {
            $userType = 'System';
            $user = $em->getRepository('RxConnexionBundle:UserEntity')->findOneBy(array('username' => $username, 'isActive' => true));
            if($user && ($user->getPassword() === crypt(md5($password), $user->getPassword()) || $user->getPassword() === $password)) {

                $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()),
                    /*'ws_token' => JWT::encode(array(
                        'source' => 'rxconnexion',
                        'session' => md5(rand(0, 999) . '-' . time()),
                        'user_id' => $user->getId()
                    ), $this->container->getParameter('ws_key'))*/

                );

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

            }else{
                $result['msg'] = 'Invalid username or password.';
            }
        }

        return new JsonResponse($result);
    }


    /* ============================================================= */
    /* ====================== PATIENT MODULE ====================== */
    /* ============================================================= */

    /**
     * @Route("/patient/get", name="zap_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');
        $searchText = $request->request->get('searchText');

        $em = $this->em();
        
        $data = $em->getRepository('RxConnexionBundle:PatientEntity')->zapsys_patient_list($userId, $searchText);
        
        $result['success'] = true;
        $result['patients'] = $data['results'];


        return new JsonResponse($result);
    }

    /**
     * @Route("/patient/details", name="zap_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'])){
            $encounter = $em->getRepository('RxConnexionBundle:PatientChartEntity')->zapsys_patient_encounter($postData['userId'], $postData['patientId']);
            $notes = $em->getRepository('RxConnexionBundle:PatientNoteEntity')->zapsys_patient_note($postData['userId'], $postData['patientId']);

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

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

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

    /**
     * @Route("/patient/note/type/get", name="zap_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="zap_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($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'] = 'Invalid request data.';
        }

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

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

    /**
     * @Route("/patient/encounter/statuses/get", name="zap_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')-> zapsys_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('zap-api-patient-encounter-status-get', 'patient/encounter/status-get', $logData);
        return new JsonResponse($result);
    }

    /**
     * @Route("/patient/encounter/update", name="zap_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'])){

            $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'] = 'Invalid request data.';
        }


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

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

    /* ============================================================= */
    /* ===================== APPOINTMENT MODULE =================== */
    /* ============================================================= */


    /**
     * @Route("/appointment/branch/get", name="zap_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')->zapsys_get_all_active();

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


        return new JsonResponse($result);
    }

    /**
     * @Route("/appointment/branch/providers", name="zap_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')->zapsys_provider_by_health_facility($branchId, $date);

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


        return new JsonResponse($result);
    }

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

        $result = array();

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

        $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')-> zapsys_schedule_calendar_view_provider($branchId, $date, $providerId);
        $schedules = $em->getRepository('RxConnexionBundle:ScheduleEntity')-> zapsys_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;

        return new JsonResponse($result);
    }

    /**
     * @Route("/appointment/calendar/list", name="zap_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');


        $em = $this->getDoctrine()->getManager();
        $schedules = $em->getRepository('RxConnexionBundle:ScheduleEntity')-> zapsys_schedule_calendar_list($branchId, $date, $providerId);
        $result['success'] = true;
        $result['schedules'] = $schedules;

        return new JsonResponse($result);
    }

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

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

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

        return new JsonResponse($result);
    }

    /**
     * @Route("/appointment/update-status", name="zap_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');

        $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';

        }


        return new JsonResponse($result);
    }

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



    private function appendLogs($logName, $logPath, $logData) {

        /*$logAbsPath = $this->getParameter('api_log_dir') . '/' . $logPath;
        $logFilename = $logAbsPath . '/' . $logName . '.log';

        if(file_exists($logFilename)) {
            $logFile = fopen($logFilename, "a+");
            fwrite($logFile, PHP_EOL . $logData);
        } else {
            $logFile = fopen($logFilename, "w");
            fwrite($logFile, $logData);
        }
        fclose($logFile);

        $logSize = filesize($logFilename);
        if($logSize >= $this->getParameter('api_log_max_size')) {
            rename($logFilename, $logAbsPath . '/' . $logName . '-' . date('Y-m-d-H-i-s') . '.log');
        }*/
    }
}
