<?php

$loader = $this->registry->get('load');
$loader->controller('base/base_controller');

class ControllerSaleSchedule extends BaseController
{
    protected $referencePathFile = 'sale/schedule';
    
    private $error = array();
    protected $settings = [];

    protected function loadScript() {
        $this->document->addScript("admin/public/js/$this->referencePathFile.js");
    }

    protected function breadcrumbs() {
        $this->dataVue['breadcrumbs'] = [
            [
                'href' => $this->url->link('common/home', 'token=' . $this->token, 'SSL'),
                'text' => $this->language->get('text_home'),
            ],
            [
                'href' => $this->url->link($this->referencePathFile, 'token=' . $this->token, 'SSL'),
                'text' => $this->language->get('heading_title'),
            ]
        ];
    }

    protected function actionUrls() {
        $this->dataVue['action'] = $this->url->link(
            "$this->referencePathFile/save",
            'token=' . $this->token,
            'SSL'
        );

        $this->dataVue['token'] = $this->token;
    
        $this->dataVue['back'] = $this->url->linkAnchor(
            'extension/module',
            'token=' . $this->token,
            'SSL'
        );
    }

    public function loadData() {

        $this->document->setTitle($this->language->get('heading_title'));
        
        $this->load->helper('ftr_geral');
        $this->load->type('tipocomum');
        $this->load->model('sale/schedule');

        if (!$this->cache->get('deleteScheduleDatetimeRoutineKey')) {

            $responseFlag = $this->model_sale_schedule->deleteOlderScheduleDatetimes();

            // value in seconds (6 hours)
            $this->cache->set('deleteScheduleDatetimeRoutineKey', $responseFlag, 21600);  
        }
    }

    public function index($settings = []) {
        $this->settings = $settings;

        $this->loadLanguage();

        $this->breadcrumbs();

        $this->loadScript();

        $this->loadModel();

        $this->loadController();

        $this->loadData();

        $this->childrens();

        $this->actionUrls();

        $this->response->setOutput($this->render($this->referencePathFile));
    }  

    public function newSchedule() {
		if ($this->request->server['REQUEST_METHOD'] == 'POST') {		
			$response_json = [];

            $availableTimes = $this->scheduleGenerator($this->request->post);
            
			$this->load->model('sale/schedule');
			$response_json['success'] = $this->model_sale_schedule->addSchedule($this->request->post, $availableTimes);

			return $this->response->setOutputJson($response_json);
		}
	}

    public function editSchedule() {
        if ($this->request->server['REQUEST_METHOD'] == 'POST') {		
			$response_json = [];
            
			$this->load->model('sale/schedule');
			$response_json = $this->model_sale_schedule->editSchedule($this->request->post);

			return $this->response->setOutputJson($response_json);
		}
    }    

    public function deleteScheduleHasNotOrder() {
        if ($this->request->server['REQUEST_METHOD'] == 'POST') {	
            
            $this->load->model('sale/schedule');
            $response_json = $this->model_sale_schedule->deleteScheduleHasNotOrder($this->request->post['schedule_id']);

            return $this->response->setOutputJson($response_json);
        }
    }

    public function getScheduleWithoutOrder() {
        if ($this->request->server['REQUEST_METHOD'] == 'POST') {	
            $this->load->model('sale/schedule');

            $response_json = $this->model_sale_schedule->getScheduleWithoutOrderDB($this->request->post);

			return $this->response->setOutputJson($response_json);
        }
    }

    public function getSchedule() {
        if ($this->request->server['REQUEST_METHOD'] == 'POST') {	
            $this->load->model('sale/schedule');

            $response_json = $this->model_sale_schedule->getScheduleDb($this->request->post);

			return $this->response->setOutputJson($response_json);
        }
    }

    public function getScheduleOrder() {
        if ($this->request->server['REQUEST_METHOD'] == 'POST') {	
            $this->load->model('sale/schedule');
            $this->load->model('sale/order');

            $response_json = $this->model_sale_schedule->getScheduleOrderDb($this->request->post);

            if($response_json){
                $order = $this->request->post;

                $url_order = $this->url->link('sale/order/info', 'token=' . $this->token . '&order_id=' . $order['id'] . '#tab-info=5', 'SSL');

                $response_json['url_order'] = $url_order;
            }else{
                $response_json = false;          
            };
            return $this->response->setOutputJson($response_json);
        };
    }

    public function getScheduled() {
        if ($this->request->server['REQUEST_METHOD'] == 'POST') {	
            $this->load->model('sale/schedule');
        
            $response_json = $this->model_sale_schedule->getScheduledDb($this->request->post);
            
			return $this->response->setOutputJson($response_json);
        }
    }

    public function updateOrder(){
        if ($this->request->server['REQUEST_METHOD'] == 'POST') {	
            $this->load->model('sale/schedule');

            $response_json = $this->model_sale_schedule->updateOrderDb($this->request->post);

			return $this->response->setOutputJson($response_json);
        }
    }

    public function updateScheduleStatus(){
        if ($this->request->server['REQUEST_METHOD'] == 'POST') {	
            $this->load->model('sale/schedule');

            $response_json = $this->model_sale_schedule->updateupdateScheduleStatusDb($this->request->post);

			return $this->response->setOutputJson($response_json);
        }
    }
   
    public function postOrder(){
        if ($this->request->server['REQUEST_METHOD'] == 'POST') {	
            $this->load->model('sale/schedule');

            $response_json = $this->model_sale_schedule->postOrderDb($this->request->post);

            return $this->response->setOutputJson($response_json);
        }
    }

    public function updateScheduleBlock(){
        if ($this->request->server['REQUEST_METHOD'] == 'POST') {	
            $this->load->model('sale/schedule');

            $response_json = $this->model_sale_schedule->updateScheduleBlockDb($this->request->post);

			return $this->response->setOutputJson($response_json);
        }
    }

    public function getScheduleTime(){
        if ($this->request->server['REQUEST_METHOD'] == 'POST') {	
            
            $this->load->model('sale/schedule');
            $responseSchedule = $this->model_sale_schedule->getScheduleDb($this->request->post);
            $increment = $this->request->post['increment'];
            $incrementIndex = intval($this->request->post['index']);
            $rest = $this->request->post['restValue'];
            $schedule = []; 
            $isEnd = false;
            $currentDate = new DateTime();
            $currentDateFormat = $currentDate->format('Y-m-d');
    
            if($responseSchedule) {
                $days = $this->model_sale_schedule->getScheduleDateDb($responseSchedule[0]['date_start'], $responseSchedule[0]['date_end']); 
                $dividedTime = $this->model_sale_schedule->getScheduleTimesDb($responseSchedule[0]['time_start'], $responseSchedule[0]['time_end'], $responseSchedule[0]['interval_to_meet']); 
                
                $index = array_search($currentDateFormat, array_column($days, 'fullDate'));
                if ($index === false) {
                    $index = 0; 
                };
                       
                if (($increment === 'next' && ($incrementIndex + 14) >= count($days))) {
                    $start = max(0, count($days) - 7); 
                    $parcialDays = array_slice($days, $start);
                    $rest = ($incrementIndex + 7) - count($days);
                    $isEnd = true;
                    if(!$incrementIndex){
                        $incrementIndex = true;
                    };
                }else {                 
                    if ($increment === 'next') {
                        $incrementIndex += 7;       
                    } elseif ($increment === 'back') {
                        if (isset($rest) && $rest !== 'false') {
                            $incrementIndex = $incrementIndex;
                            $rest = false;
                        }else{
                            $incrementIndex -= 7;
                            $incrementIndex = abs($incrementIndex);
                        }          
                    } else {
                        $incrementIndex = floor($index / 7) * 7;
                    };
                    $parcialDays = array_slice($days, $incrementIndex, 7);

                    if(count($parcialDays) <7 && $days > 7 || (count($days) - $index) < 7 && ($increment !== 'back' && $increment !== 'next')){
                        $parcialDays = array_slice($days, -7);
                        $isEnd = true;
                    }
                }
                                       
                $parcialSchedule = $this->model_sale_schedule->getParcialScheduleDb($parcialDays[0]['fullDate'], $parcialDays[count($parcialDays) - 1]['fullDate'], $this->request->post);
                            
                $lengthTable = count($days) > 7;
                $dayNumbers = array_column($parcialDays, 'dayNumber');
                $smallNumber = min($dayNumbers);

                foreach ($parcialDays as $daysNumber) {
                    if ($daysNumber['dayNumber'] === $smallNumber) {
                        $monthName = $daysNumber['monthName'];
                        $yearName = substr($daysNumber['fullDate'], 0, 4);
                        break;
                    };
                };
    
                $schedule = array_map(function($time) use ($parcialDays) {
                    return array_map(function($day) use ($time) {
                        return [
                            'date' => $day['fullDate'],
                            'time' => $time['dividTime'],
                            'value' => '',
                            'schedule_times_id' => ''
                        ];
                    }, $parcialDays);
                }, $dividedTime);

                $scheduleArray = array_merge(...$schedule);
            
                $emptyValue = array_filter($scheduleArray, function($item1) use ($parcialSchedule) {
                    return empty(array_filter($parcialSchedule, function($item2) use ($item1) {
                        return $item1['date'] === $item2['date'] && $item1['time'] === $item2['formatted_time'];
                    }));
                });
            
                foreach ($emptyValue as $item) {
                    foreach ($schedule as &$line) {
                        foreach ($line as &$column) {
                            if ($column['date'] === $item['date'] && $column['time'] === $item['time']) {
                                $column['value'] = 'indisponivel';
                            };
                        };
                    };
                };
             
                foreach ($parcialSchedule as $item) {
                    foreach ($dividedTime as $x => $time) {
                        foreach ($parcialDays as $i => $day) {
                            if ($item['date'] === $schedule[$x][$i]['date'] && $item['formatted_time'] === $schedule[$x][$i]['time']) {
                                $schedule[$x][$i]['observation'] = $item['observation'];
                                if (!empty($item['schedule_times_id'])) $schedule[$x][$i]['schedule_times_id'] = $item['schedule_times_id'];
                                if (!empty($item['order_id'])) $schedule[$x][$i]['value'] = $item['order_id'];
                                if ($item['weekend'] === '1' && $item['work_on_weekend'] === '0') $schedule[$x][$i]['value'] = 'indisponivel';
                                if (($item['blocked_time'] === '1' && $item['weekend'] !== '1') || ($item['work_on_weekend'] === '1' && $item['weekend'] === '1' && $item['blocked_time'] === '1')) $schedule[$x][$i]['value'] = 'bloqueado';
                            };
                        };
                    };
                };
     
                $outPutData = [
                    'schedule' => $schedule,
                    'days' => $days,
                    'end' => $isEnd,
                    'lengthTable' => $lengthTable,
                    'parcialDays' => $parcialDays,
                    'monthName' => $monthName,
                    'dividedTime' => $dividedTime,
                    'blockStartIndex' => $incrementIndex,
                    'rest' =>  $rest,
                    'yearName' => $yearName,
                ];
            
                return $this->response->setOutputJson($outPutData);
            };
        };
    }
    // Below is the functions to generate all datetimes 
    public function scheduleGenerator($formData) {
        $availableTimes = array();
        
        extract($formData);
    
        $startTime = new DateTime("1970-01-01T$time_start:00");
        $endTime = new DateTime("1970-01-01T$time_end:00");
    
        $startTimeHours = $startTime->format('H');
        $startTimeMinutes = $startTime->format('i');
        $endTimeHours = $endTime->format('H');
        $endTimeMinutes = $endTime->format('i');
    
        list($lunchStartTime, $lunchEndTime) = $this->convertLunchTime(
            isset($interval_for_lunch_status) ? $interval_for_lunch_status : null, 
            isset($interval_for_lunch) ? $interval_for_lunch : null,
        );
    
        $lunchStartHours = $lunchStartTime->format('H');
        $lunchStartMinutes = $lunchStartTime->format('i');
        $lunchEndHours = $lunchEndTime->format('H');
        $lunchEndMinutes = $lunchEndTime->format('i');
    
        $current_date = $this->convertDates($date_start);
        $current_date->setTime($startTimeHours, $startTimeMinutes, 0, 0);

        $schedule_date_end = $this->convertDates($date_end);
        $schedule_date_end->setTime($endTimeHours, $endTimeMinutes, 59, 59); // Definir para o último minuto do último dia

        while ($current_date <= $schedule_date_end) {
            $current_date_hours = $current_date->format('H');
            $current_date_minutes = $current_date->format('i');
    
            $isLunchTime =
                ($lunchEndTime && $current_date_hours > $lunchStartHours && $current_date_hours < $lunchEndHours) ||
                ($current_date_hours === $lunchStartHours && $current_date_minutes >= $lunchStartMinutes) ||
                ($current_date_hours === $lunchEndHours && $current_date_minutes < $lunchEndMinutes);
    
            $isWorkingHour =
                $current_date_hours > $startTimeHours ||
                ($current_date_hours === $startTimeHours &&
                    $current_date_minutes >= $startTimeMinutes &&
                    $current_date_hours < $endTimeHours) ||
                ($current_date_hours === $endTimeHours && $current_date_minutes <= $endTimeMinutes);
    
            $isWeekend = $current_date->format('N') == 6 || $current_date->format('N') == 7; // Sábado: 6, Domingo: 7
    
            $dateFormatted = $current_date->format('d/m/Y');
            $timeFormatted = $current_date->format('H:i');
    
            if ($isWorkingHour) {
                $availableTimes[] = array(
                    'date' => $dateFormatted,
                    'time' => $timeFormatted,
                    'isWeekend' => $isWeekend,
                    'isLunchTime' => $isLunchTime,
                );
            }
    
            $current_date->add(new DateInterval('PT' . $interval_to_meet . 'M'));
    
            // Verifica se ultrapassou o horário de trabalho e ajusta para o próximo dia
            if (
                $current_date_hours > $endTimeHours ||
                ($current_date_hours === $endTimeHours && $current_date_minutes > $endTimeMinutes)
            ) {
                $current_date->add(new DateInterval('P1D'));
                $current_date->setTime($startTimeHours, $startTimeMinutes, 0, 0);
                array_pop($availableTimes); // remove last element
            }
        }
    
        return $availableTimes;
    }
    
    public function convertDates($actuallyDate) {
        $dateParts = explode('/', $actuallyDate);
        $newDate = new DateTime();
        $newDate->setDate($dateParts[2], $dateParts[1], $dateParts[0]);
        return $newDate;
    }
    
    public function convertLunchTime($status, $initialTime) {
        if ($status == 'true' && $initialTime && preg_match('/\d{2}:\d{2}/', $initialTime)) {
            $lunchStartTime = new DateTime("1970-01-01T$initialTime:00");
            $lunchEndTime = clone $lunchStartTime; 
            $lunchEndTime->modify('+1 hour'); // Adicione 1 hora ao horário de almoço

        } else {
            $lunchStartTime = new DateTime('1970-01-01T00:00:00');
            $lunchEndTime = new DateTime('1970-01-01T00:00:00');
        }

        return array($lunchStartTime, $lunchEndTime);
    }  
}