<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use DB;
use DateTime;
use App\Models\CronLog;
use Maatwebsite;
use App\Feedback;
use App\FtpDetails;
use App\FtpFilesDetails;
use App\Organization;
use Auth;
use App\User;
use App\Branch;
use App\Manager;
use App\SycleFilesDetails;
use Carbon\Carbon;

class FeedbackPatientData extends Command
{
    protected $signature = 'patientData:feedback';
    protected $description = 'Patient Feedback';
    protected $errorLog = array();
    protected $old_appointment_value = array();
    protected $is_send_link = 0;
    protected $token = '';
    protected $clinic_id = '';

    /**
     * Execute the command.
     *
     * @return void
     */
    public function handle()
    {
        $ftpFilesDetails = DB::table('sycle_files_details')
            ->select('id', 'sync_status', 'filepath', 'filename')
            ->where('sync_status', 'Pending')
            ->limit(2)
            ->get();
        
        if (!empty($ftpFilesDetails)) {
            foreach ($ftpFilesDetails as $key => $files) {
                // $filePath = 'public/uploads/cyclecsv/' . $files->bussiness_id;
                $filePath = env('SYCLE_CSV_MOVED_PATH');
                $inputFileName = $filePath . '/' . $files->filename;
                $data = Maatwebsite\Excel\Facades\Excel::load($inputFileName)->get();
                $this->errorLog = array();

                $arr = array();
                $info = array();
                if ($data->count()) {
                    foreach ($data as $value) {
                        if ($this->isValidData($value)) {
                            if ($this->isValidClinicId($value)) {
                                $info[] = $value;
                            }
                        }
                    }
                }

                if (!empty($this->errorLog)) {
                    $error['error'] = $this->errorLog;
                    $errorJson = json_encode($error);
                    $this->updateErrorLog($errorJson, $files->id);
                    // Update status Failed
                    $this->updateSyncStatus('Failed', $files->id);

                    echo 'Something went wrong. Please check error log for file: '.$files->filename;
                    exit();
                }

                //In process
                $this->updateSyncStatus('Inprocess', $files->id);

                //Update Total Rec in ftp_files tbl
                $this->updateTotalRec(count($info), $files->id);

                if (!empty($info)) {
                    foreach ($info as $key => $value) {
                        if ($this->checkAlreadyExistsSameUserAppointment($value)) {
                            $this->saveFeedbackData($value, 'insert', null);
                        }
                    }
                }

                // Update status Completed
                $this->updateSyncStatus('Completed', $files->id);
                echo "\n  File: ".$files->filename. " Successfully Imported... \n";

                // Unlink file from location
                $this->unlinkFile($filePath . "/". $files->filename);
                echo "\n  File: ".$files->filename. " Successfully Removed from " .$filePath. "\n";
            }
        } else {
            echo 'No Pending files found ';
        }

        $this->updateCronLog();
    }

    public function checkAlreadyExistsSameUserAppointment($value)
    {
        $feedbackExists = DB::table('feedback')
            ->where('appointment_id', $value->appointment_id)
            ->first();

        if (!empty($feedbackExists)) {
            //Update
            $this->saveOldData($feedbackExists);
            $this->saveFeedbackData($value, 'update', $feedbackExists->id);
        } else {
            return true;
        }
    }

    public function saveOldData($feebackOldInfo)
    {
        $this->old_appointment_value = json_encode($feebackOldInfo);
        $this->is_send_link = $feebackOldInfo->is_send_link;
        $this->token = $feebackOldInfo->token;
        $this->clinic_id = $feebackOldInfo->clinic_id;
    }

    public function saveFeedbackData($value, $action, $id)
    {
        if ($action == 'update') {
            $feedback = Feedback::where('id', $id)->first();
            $feedback->old_appointment_value = $this->old_appointment_value;
        } else {
            $feedback = new Feedback();
        }

        $feedback->customer_name = $value->patient_first_name . ' ' . $value->patient_last_name;
        $feedback->email = $value->email;

        $branch = Branch::where('sycle_clinic_id', $value->clinic_id)->first();

        $organizationId = $branch->organization_id;
        $organization = Organization::where('id', $organizationId)->first();

        $feedback->user_id = $organization->user_id;
        $feedback->location = $branch->name;

        $date = new \DateTime();
        $feedback->created = $date->format('Y-m-d H:i:s');
        $feedback->mobile = $this->getCleanMobileNumber($value->cell_number);
        $feedback->status = $value->sms_status;
        
        $feedback->organization_id = $organizationId;

        $feedback->imported_from = 'Sycle';

        if ($action == 'update') {
            $feedback->token = $this->token;
            if ($this->clinic_id != $value->clinic_id) {
                $feedback->token = str_random(60);
            }
            $feedback->is_send_link = $this->is_send_link;
        } else {
            $feedbackIsCompleted = DB::table('feedback')
            ->where('patient_id', $value->patient_id)
            ->where('clinic_id', $value->clinic_id)
            ->whereIn('appointment_status', ['Confirmed','Completed'])
            ->count();
            if ($feedbackIsCompleted > 0) {
                $feedback->is_send_link = 1;
                $feedback->will_actual_send = 0;
            } else {
                $feedback->is_send_link = 0;
            }
            $feedback->token = str_random(60);
        }

        //Get details from user tbl
        $feedback->send_sycle_time = $this->getTimeForFeedbackNotification($value->appointment_time_and_date);  //get from user tbl time_of_feedback_notification

        $feedback->is_queue = 1;
        $feedback->patient_id = $value->patient_id;
        $feedback->clinic_id = $value->clinic_id;
        $feedback->appointment_dt = $value->appointment_time_and_date;
        $feedback->appointment_status = ucwords(trim($value->appointment_status));
        $feedback->appointment_type = $value->appointment_type;
        $feedback->appointment_id = $value->appointment_id;
        
        $info['instance_id'] = $value->instance_id;
        $info['patient_id'] = $value->patient_id;
        $info['appointment_id'] = $value->appointment_id;
        $info['appointment_time_and_date'] = $value->appointment_time_and_date;
        $info['appointment_status'] = ucwords(trim($value->appointment_status));
        $info['email_status'] = $value->email_status;

        $feedback->additional_patient_data = json_encode($info);

        $feedback->save();

        if ($action == 'update') {
            if ($this->clinic_id != $value->clinic_id) {
                $this->saveFeedbackLog($feedback, $value, $action);
            }
        } else {
            $this->saveFeedbackLog($feedback, $value, $action);
        }
    }

    public function saveFeedbackLog($feedback, $value, $action)
    {
        $manager = Manager::where('user_id', $feedback->user_id)->first();
        $locationName = $feedback->location;
        $locationClinicId = $feedback->clinic_id;
        $branch = Branch::where('sycle_clinic_id', $locationClinicId)->first();
        $place = '';
        if ($manager && $manager->review_identifier != '') {
            $link = ANGULARURL . 'feedback-facebook?token=' . $feedback->token . '&place=' . $branch->place_value;
        } elseif ($place != '') {
            $link = ANGULARURL . 'feedbackplace?token=' . $feedback->token . '&place=' . $branch->place_value;
        } else {
            $link = ANGULARURL . 'feedback-options?token=' . $feedback->token . '&place=' . $branch->place_value;
        }
        
        try {
            $tokenizer = uniqid() . '_' . $feedback->id;
            $shortURL = ANGULARURL . "feedback-invitation/" . $tokenizer;

            $date = new \DateTime();
            $created_date = $date->format('Y-m-d');

            $feedbackIsCompleted = DB::table('feedback')
            ->where('patient_id', $value->patient_id)
            ->where('clinic_id', $value->clinic_id)
            ->whereIn('appointment_status', ['Confirmed','Completed'])
            ->where('is_send_link', 1)
            ->count();
            $status =  ($feedbackIsCompleted > 0) ? 'ignore' :'check';
            $feedback_link_log = array(
                'token' => $tokenizer,
                'long_url' => $link,
                'short_url' => $shortURL,
                'feedback_id' => $feedback->id,
                'is_clicked' => 0,
                'is_clicked_count' => 0,
                'created_date' => $created_date,
                'status' => $status,
            );
        } catch (Exception $e) {
            return $longUrl;
        }

        if ($action == 'update') {
            DB::table('feedback_send_link_log')->where('feedback_id', $feedback->id)->update($feedback_link_log);
        } else {
            $id = DB::table('feedback_send_link_log')->insertGetId($feedback_link_log);
        }
    }

    public function unlinkFile($file)
    {
        unlink($file);
    }

    public function updateCronLog()
    {
        $date = date('Y-m-d H:i:s');
        DB::table('cron_log')->where('name', $this->signature)->update(['cron_at' => $date]);
    }

    public function updateTotalRec($totalRecord, $id)
    {
        $ftpFilesDetails1 = SycleFilesDetails::where('id', $id)->first();
        $ftpFilesDetails1->total_rec   = $totalRecord;
        $ftpFilesDetails1->save();
    }

    public function updateSyncStatus($status, $id)
    {
        // $ftpFilesDetails1 = FtpFilesDetails::where('id', $id)->first();
        // $ftpFilesDetails1->sync_status   = $status;
        // $ftpFilesDetails1->save();

        $ftpFilesDetails1 = SycleFilesDetails::where('id', $id)->first();
        $ftpFilesDetails1->sync_status   = $status;
        $ftpFilesDetails1->save();
    }

    public function updateErrorLog($error, $id)
    {
        $ftpFilesDetails1 = SycleFilesDetails::where('id', $id)->first();
        $ftpFilesDetails1->error_log   = $error;
        $ftpFilesDetails1->save();
    }

    public function getCleanMobileNumber($cellNumber)
    {
        $mobile = str_replace("+1 ", "", $cellNumber);
        $mobile = str_replace("(", "", $mobile);
        $mobile = str_replace(") ", "", $mobile);
        $mobile = str_replace("-", "", $mobile);
        return $mobile;
    }

    public function getTimeForFeedbackNotification($appointment_time_and_date)
    {
        $time_of_feedback_notification = date("Y-m-d H:i:s", strtotime(date("Y-m-d H:i:s", strtotime($appointment_time_and_date)) . " + 1 hours"));
        $dateObj = Carbon::parse($time_of_feedback_notification, env('APP_TIMEZONE'))->setTimezone(env('APP_TIMEZONE'));
        return $dateObj->toDateTimeString();
    }

    public function isValidClinicId($data)
    {
        $branch = Branch::where('sycle_clinic_id', $data->clinic_id)->first();
        if (empty($branch)) {
            $this->errorLog = array('Clinic Id '. $data->clinic_id. ' not Found' );
            return false;
        } else {
            $organizationId = $branch->organization_id;
            $organization = Organization::where('id', $organizationId)->first();
            if (empty($organization)) {
                $this->errorLog = array('Organization Id '. $organizationId. ' not Found' );
                return false;
            }
            return true;
        }
        return true;
    }

    public function isValidData($data)
    {
        $bool = false;
        if ($data->email == '' && $data->cell_number == '') {
            $bool = false;
        }
        if ($data->email != '') {
            $bool = true;
        }
        if ($data->cell_number != '') {
            $bool = true;
        }
        return $bool;
    }
}
