<?php
/**
 * @copyright    OCTemplates
 * @support      https://octemplates.net/
 * @license      LICENSE.txt
 */

class ControllerOctemplatesModuleOctPriceTracker extends Controller {
	private $error = array();

	public function index() {
		$this->load->language('octemplates/module/oct_price_tracker');

		$this->document->addScript('view/javascript/codemirror/lib/codemirror.js');
		$this->document->addScript('view/javascript/codemirror/lib/xml.js');
		$this->document->addScript('view/javascript/codemirror/lib/formatting.js');
		$this->document->addStyle('view/javascript/codemirror/lib/codemirror.css');
		$this->document->addStyle('view/javascript/codemirror/theme/monokai.css');

		$this->document->addScript('view/javascript/summernote/summernote.js');
		$this->document->addScript('view/javascript/summernote/summernote-image-attributes.js');
		$this->document->addScript('view/javascript/summernote/opencart.js');
		$this->document->addStyle('view/javascript/summernote/summernote.css');
		$this->document->addScript('view/javascript/octemplates/bootstrap-notify/bootstrap-notify.min.js');
		$this->document->addScript('view/javascript/octemplates/oct_main.js');
		$this->document->addStyle('view/stylesheet/oct_promo.css');
		$this->document->setTitle($this->language->get('heading_title'));

		$this->load->model('setting/setting');
		$this->load->model('localisation/language');
		$this->load->model('octemplates/module/oct_price_tracker');
		$this->load->model('localisation/currency');

		$limit = (int)$this->config->get('config_limit_admin');
		if ($limit < 1) {
			$limit = 20; 
		}

		$languages = $this->model_localisation_language->getLanguages();
		$language_data = array();
		foreach ($languages as $language) {
			$language_data[$language['language_id']] = $language;
		}

		$currencies = $this->model_localisation_currency->getCurrencies();
		$currency_data = array();
		foreach ($currencies as $currency) {
			$currency_data[$currency['code']] = $currency;
		}

		$oct_price_tracker_info = $this->model_setting_setting->getSetting('oct_price_tracker');

		if (!$oct_price_tracker_info) {
			$this->response->redirect($this->url->link('octemplates/module/oct_price_tracker/install', 'user_token=' . $this->session->data['user_token'], true));
		}

		if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
			$this->model_setting_setting->editSetting('oct_price_tracker', $this->request->post);

			if (isset($this->request->post['oct_price_tracker_status']) && $this->request->post['oct_price_tracker_status'] == "on") {
				$this->addEvent();
			} else {
				$this->deleteEvent();
			}

			$this->session->data['success'] = $this->language->get('text_success');
			$this->response->redirect($this->url->link('octemplates/module/oct_price_tracker', 'user_token=' . $this->session->data['user_token'] . '&type=module', true));
		}

		$data['heading_title'] = $this->language->get('heading_title');

		if (isset($this->error['warning'])) {
			$data['error_warning'] = $this->error['warning'];
		} else {
			$data['error_warning'] = '';
		}

		if (isset($this->session->data['success'])) {
			$data['success'] = $this->session->data['success'];
			unset($this->session->data['success']);
		} else {
			$data['success'] = '';
		}

		$url = '';

		if (isset($this->request->get['filter_email'])) {
			$url .= '&filter_email=' . urlencode($this->request->get['filter_email']);
		}

		if (isset($this->request->get['filter_product'])) {
			$url .= '&filter_product=' . urlencode($this->request->get['filter_product']);
		}

		if (isset($this->request->get['filter_customer'])) {
			$url .= '&filter_customer=' . urlencode($this->request->get['filter_customer']);
		}

		if (isset($this->request->get['filter_status'])) {
			$url .= '&filter_status=' . urlencode($this->request->get['filter_status']);
		}

		if (isset($this->request->get['filter_email']) || isset($this->request->get['filter_product']) || isset($this->request->get['filter_customer']) || isset($this->request->get['filter_status'])) {
			$url .= '&tab=requests';
		}

		$filter_log_email = isset($this->request->get['filter_log_email']) ? htmlspecialchars($this->request->get['filter_log_email'], ENT_QUOTES, 'UTF-8') : null;
		$filter_log_product = isset($this->request->get['filter_log_product']) ? htmlspecialchars($this->request->get['filter_log_product'], ENT_QUOTES, 'UTF-8') : null;
		$filter_log_status = isset($this->request->get['filter_log_status']) ? htmlspecialchars($this->request->get['filter_log_status'], ENT_QUOTES, 'UTF-8') : null;

		if (isset($this->request->get['filter_log_email']) || isset($this->request->get['filter_log_product']) || isset($this->request->get['filter_log_status'])) {
			$url .= '&tab=logs';
		}

		$filter_log_data = array(
			'filter_email' => $filter_log_email,
			'filter_product' => $filter_log_product,
			'filter_status' => $filter_log_status
		);

		$data['filter_log_email'] = $filter_log_email;
		$data['filter_log_product'] = $filter_log_product;
		$data['filter_log_status'] = $filter_log_status;

		$total_logs = $this->model_octemplates_module_oct_price_tracker->getTotalLogs($filter_log_data);

		$log_page = isset($this->request->get['log_page']) ? max(1, (int)$this->request->get['log_page']) : 1;
		$start_logs = max(0, ($log_page - 1) * $limit);
		$filter_log_data['start'] = $start_logs;
		$filter_log_data['limit'] = $limit;

		$logs = $this->model_octemplates_module_oct_price_tracker->getLogs($filter_log_data);

		foreach ($logs as &$log) {
			$currency_code = $log['currency_code'] ?? $this->config->get('config_currency');
			$main_currency = $this->config->get('config_currency');
			
			$old_price_converted = $this->currency->convert($log['old_price'], $currency_code, $main_currency);
			$new_price_converted = $this->currency->convert($log['new_price'], $currency_code, $main_currency);
			
			$log['old_price_formatted'] = $this->currency->format($old_price_converted, $main_currency);
			$log['new_price_formatted'] = $this->currency->format($new_price_converted, $main_currency);
			
			$price_change = $new_price_converted - $old_price_converted;
			$log['price_change_formatted'] = $this->currency->format($price_change, $main_currency);
			$log['price_change_percent'] = $old_price_converted > 0 ? round(($price_change / $old_price_converted) * 100, 2) : 0;
			
			$log['product_id'] = (int)$log['product_id'];
			$log['product_link'] = $this->url->link('catalog/product/edit', 'user_token=' . $this->session->data['user_token'] . '&product_id=' . (int)$log['product_id'], true);
			$log['product_name'] = htmlspecialchars($log['product_name'] ?? '', ENT_QUOTES, 'UTF-8');
			$log['email'] = htmlspecialchars($log['email'] ?? '', ENT_QUOTES, 'UTF-8');
			$log['status'] = htmlspecialchars($log['status'] ?? '', ENT_QUOTES, 'UTF-8');
			$log['date_added'] = htmlspecialchars($log['date_added'] ?? '', ENT_QUOTES, 'UTF-8');
			
			if ($price_change > 0) {
				$log['price_change_class'] = 'text-success';
				$log['price_change_sign'] = '+';
			} else {
				$log['price_change_class'] = 'text-danger';
				$log['price_change_sign'] = '';
			}
		}

		$data['logs'] = $logs;

		$current_log_page = (isset($this->request->get['log_page']) ? (int)$this->request->get['log_page'] : 1);
		$start_log_item = (($current_log_page - 1) * $limit) + 1;
		$end_log_item = ($current_log_page * $limit < $total_logs) ? $current_log_page * $limit : $total_logs;
		$total_log_pages = ceil($total_logs / $limit);

		$data['log_results'] = sprintf($this->language->get('text_pagination'), $start_log_item, $end_log_item, $total_logs, $total_log_pages);

		$log_url = '';
		if ($filter_log_email) $log_url .= '&filter_log_email=' . urlencode($filter_log_email);
		if ($filter_log_product) $log_url .= '&filter_log_product=' . urlencode($filter_log_product);
		if ($filter_log_status) $log_url .= '&filter_log_status=' . urlencode($filter_log_status);

		$log_pagination = new Pagination();
		$log_pagination->total = $total_logs;
		$log_pagination->page = $start_logs / $limit + 1;
		$log_pagination->limit = $limit;
		$log_pagination->url = $this->url->link('octemplates/module/oct_price_tracker', 'user_token=' . $this->session->data['user_token'] . $log_url . '&log_page={page}&tab=logs', true);
		$data['log_pagination'] = $log_pagination->render();

		$filter_email = isset($this->request->get['filter_email']) ? htmlspecialchars($this->request->get['filter_email'], ENT_QUOTES, 'UTF-8') : null;
		$filter_product = isset($this->request->get['filter_product']) ? htmlspecialchars($this->request->get['filter_product'], ENT_QUOTES, 'UTF-8') : null;
		$filter_customer = isset($this->request->get['filter_customer']) ? htmlspecialchars($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8') : null;
		$filter_status = isset($this->request->get['filter_status']) ? htmlspecialchars($this->request->get['filter_status'], ENT_QUOTES, 'UTF-8') : null;

		$data['breadcrumbs'] = array();
		$data['breadcrumbs'][] = array(
			'text' => $this->language->get('text_home'),
			'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true)
		);
		$data['breadcrumbs'][] = array(
			'text' => $this->language->get('heading_title'),
			'href' => $this->url->link('octemplates/module/oct_price_tracker', 'user_token=' . $this->session->data['user_token'] . $url, true)
		);

		$data['action'] = $this->url->link('octemplates/module/oct_price_tracker', 'user_token=' . $this->session->data['user_token'], true);
		$data['cancel'] = $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true);
		$data['user_token'] = $this->session->data['user_token'];
		$data['languages'] = $this->model_localisation_language->getLanguages();

		if (isset($this->request->post['oct_price_tracker_status'])) {
			$data['oct_price_tracker_status'] = $this->request->post['oct_price_tracker_status'];
		} else {
			$data['oct_price_tracker_status'] = $this->config->get('oct_price_tracker_status');
		}

		if (isset($this->request->post['oct_price_tracker_data'])) {
			$data['oct_price_tracker_data'] = $this->request->post['oct_price_tracker_data'];
		} else {
			$data['oct_price_tracker_data'] = $this->config->get('oct_price_tracker_data');
		}

		if (isset($data['oct_price_tracker_data']['cron_secret']) && $data['oct_price_tracker_data']['cron_secret']) {
			$site_link = $this->request->server['HTTPS'] ? HTTP_CATALOG : HTTPS_CATALOG;
			$data['cron_url'] = $site_link . "index.php?route=octemplates/module/oct_price_tracker/cron&cron_secret=" . urlencode($data['oct_price_tracker_data']['cron_secret']);
		}

		$filter_data = array(
			'filter_email' => $filter_email,
			'filter_product' => $filter_product,
			'filter_customer' => $filter_customer,
			'filter_status' => $filter_status
		);

		$data['filter_email'] = $filter_email;
		$data['filter_product'] = $filter_product;
		$data['filter_customer'] = $filter_customer;
		$data['filter_status'] = $filter_status;

		$total_requests = $this->model_octemplates_module_oct_price_tracker->getTotalRequests($filter_data);

		$page = isset($this->request->get['page']) ? max(1, (int)$this->request->get['page']) : 1;
		$start = max(0, ($page - 1) * $limit);
		$filter_data['start'] = $start;
		$filter_data['limit'] = $limit;

		$requests = $this->model_octemplates_module_oct_price_tracker->getRequests($filter_data);

		foreach ($requests as &$request) {
			$product_id = (int)$request['product_id'];
			$customer_id = (int)$request['customer_id'];
			$language_id = (int)$request['language_id'] ?? 1;
			$currency_code = $request['currency_code'] ?? $this->config->get('config_currency');
			
			$decimal_place = isset($currency_data[$currency_code]) ? (int)$currency_data[$currency_code]['decimal_place'] : 2;

			$request['current_price_formatted'] = $request['symbol_left'] . number_format($request['current_price'], $decimal_place) . $request['symbol_right'];
			if (empty($request['symbol_left']) && empty($request['symbol_right'])) {
				$request['current_price_formatted'] .= ' ' . $currency_code;
			}

			$request['currency_info'] = $currency_data[$currency_code] ?? array('symbol_left' => '', 'symbol_right' => $currency_code);
			$request['language_info'] = $language_data[$language_id] ?? array('name' => 'Unknown', 'code' => 'unknown');

			$user_link = false;
			$product_link = $this->url->link('catalog/product/edit', 'user_token=' . $this->session->data['user_token'] . '&product_id=' . $product_id, true);

			if (!empty($customer_id)) {
				$user_link = $this->url->link('customer/customer/edit', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $customer_id, true);
			}

			$request['product_id'] = $product_id;
			$request['customer_id'] = $customer_id;
			$request['product_link'] = $product_link;
			$request['user_link'] = $user_link;
			$request['product_name'] = htmlspecialchars($request['product_name'] ?? '', ENT_QUOTES, 'UTF-8');
			$request['email'] = htmlspecialchars($request['email'] ?? '', ENT_QUOTES, 'UTF-8');
			$request['firstname'] = htmlspecialchars($request['firstname'] ?? '', ENT_QUOTES, 'UTF-8');
			$request['lastname'] = htmlspecialchars($request['lastname'] ?? '', ENT_QUOTES, 'UTF-8');
			$request['status'] = htmlspecialchars($request['status'] ?? '', ENT_QUOTES, 'UTF-8');
			$request['date_added'] = htmlspecialchars($request['date_added'] ?? '', ENT_QUOTES, 'UTF-8');
		}

		$data['requests'] = $requests;

		$current_page = (isset($this->request->get['page']) ? (int)$this->request->get['page'] : 1);
		$start_item = (($current_page - 1) * $limit) + 1;
		$end_item = ($current_page * $limit < $total_requests) ? $current_page * $limit : $total_requests;
		$total_pages = ceil($total_requests / $limit);

		$data['results'] = sprintf($this->language->get('text_pagination'), $start_item, $end_item, $total_requests, $total_pages);

		$pagination = new Pagination();
		$pagination->total = $total_requests;
		$pagination->page = $start / $limit + 1;
		$pagination->limit = $limit;
		$pagination->url = $this->url->link('octemplates/module/oct_price_tracker', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}&tab=requests', true);
		$data['pagination'] = $pagination->render();

		$data['base'] = $this->url->link('octemplates/module/oct_price_tracker', 'user_token=' . $this->session->data['user_token'] . '&tab=requests', true);
		$data['error_message'] = array();

		if (!empty($this->error['oct_price_tracker_data_subject'])) {
			$data['error_message']['subject'] = $this->error['oct_price_tracker_data_subject'];
		}

		if (!empty($this->error['oct_price_tracker_data_message'])) {
			$data['error_message']['message'] = $this->error['oct_price_tracker_data_message'];
		}

		if (!empty($this->error['cron_secret'])) {
			$data['error_message']['cron_secret'] = $this->error['cron_secret'];
		}

		$data['header'] = $this->load->controller('common/header');
		$data['column_left'] = $this->load->controller('common/column_left');
		$data['footer'] = $this->load->controller('common/footer');

		$this->response->setOutput($this->load->view('octemplates/module/oct_price_tracker', $data));
	}

	public function deleteSelected() {
		$this->load->language('octemplates/module/oct_price_tracker');

		if (!$this->checkModifyPermission(true)) {
			return;
		}

		$json = [];

		$this->load->model('octemplates/module/oct_price_tracker');

		$info = $this->model_octemplates_module_oct_price_tracker->checkRequest((int) $this->request->get['delete']);

		if ($info) {
			$this->model_octemplates_module_oct_price_tracker->deleteRequest((int) $this->request->get['delete']);
			$this->session->data['success'] = $this->language->get('text_success_deleted');
		}

		$this->response->addHeader('Content-Type: application/json');
		$this->response->setOutput(json_encode($json));
	}

	public function deleteAllSelected() {
		$this->load->language('octemplates/module/oct_price_tracker');

		if (!$this->checkModifyPermission(true)) {
			return;
		}

		$json = [];

		$this->load->model('octemplates/module/oct_price_tracker');

		if (isset($this->request->request['selected'])) {
			foreach ($this->request->request['selected'] as $request_id) {
				$info = $this->model_octemplates_module_oct_price_tracker->checkRequest((int) $request_id);

				if ($info) {
					$this->model_octemplates_module_oct_price_tracker->deleteRequest((int) $request_id);
					$this->session->data['success'] = $this->language->get('text_success_deleted');
				}
			}
		}

		$this->response->addHeader('Content-Type: application/json');
		$this->response->setOutput(json_encode($json));
	}

	public function install() {
		$this->load->language('octemplates/module/oct_price_tracker');

		if (!$this->checkModifyPermission()) {
			return;
		}

		$this->load->model('setting/setting');
		$this->load->model('user/user_group');
		$this->load->model('octemplates/module/oct_price_tracker');
		$this->model_octemplates_module_oct_price_tracker->install();

        $this->addEvent();

		$this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'octemplates/module/oct_price_tracker');
		$this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'octemplates/module/oct_price_tracker');

		$cron_secret = bin2hex(random_bytes(16));

		$this->model_setting_setting->editSetting('oct_price_tracker', [
			'oct_price_tracker_status' => '1',
			'oct_price_tracker_data' => [
				'cron_secret' => $cron_secret,
				'customer_name' => 1,
				'phone' => 1,
                'notify_on_edit' => 1,
				'custom_message' => 0,
				'subject' => [],
				'message' => []
			]
		]);

		$this->session->data['success'] = $this->language->get('text_success_install');

		$this->response->redirect($this->url->link('octemplates/module/oct_price_tracker', 'user_token=' . $this->session->data['user_token'], true));
	}

	public function uninstall() {
		$this->load->language('octemplates/module/oct_price_tracker');

		if (!$this->checkModifyPermission()) {
			return;
		}

		$this->load->model('setting/setting');
		$this->load->model('user/user_group');
		$this->load->model('octemplates/module/oct_price_tracker');

		$this->model_octemplates_module_oct_price_tracker->uninstall();

		$this->model_user_user_group->removePermission($this->user->getGroupId(), 'access', 'octemplates/module/oct_price_tracker');
		$this->model_user_user_group->removePermission($this->user->getGroupId(), 'modify', 'octemplates/module/oct_price_tracker');

		$this->model_setting_setting->deleteSetting('oct_price_tracker');

        $this->deleteEvent();

		$this->response->redirect($this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true));
	}

	protected function validate() {
		if (!$this->user->hasPermission('modify', 'octemplates/module/oct_price_tracker')) {
			$this->error['warning'] = $this->language->get('error_permission');
		}

		if (empty($this->request->post['oct_price_tracker_data']['cron_secret'])) {
			$this->error['warning'] = $this->language->get('error_cron_secret');
			$this->error['cron_secret'] = $this->language->get('error_cron_secret');
		}

		if (isset($this->request->post['oct_price_tracker_data']['custom_message'])) {
			foreach ($this->request->post['oct_price_tracker_data']['subject'] as $language_id => $value) {
				if (!$value) {
					$this->error['oct_price_tracker_data_subject'][$language_id] = $this->language->get('error_subject_empty');
					$this->error['warning'] = $this->language->get('text_warning');
				}
			}

			foreach ($this->request->post['oct_price_tracker_data']['message'] as $language_id => $value) {
				if (!$value || strlen($value) < 30) {
					$this->error['oct_price_tracker_data_message'][$language_id] = $this->language->get('error_message_empty');
					$this->error['warning'] = $this->language->get('text_warning');
				}
			}
		}

		return !$this->error;
	}

    public function addEvent() {

        if (!$this->checkModifyPermission()) {
            return;
        }

        $this->load->model('setting/event');

        if ($this->model_setting_event->getEventByCode('octemplates-promo-price-tracker')) {
            return;
        }

        $this->deleteEvent();

        $events = [
            [
                'code' => 'octemplates-promo-price-tracker',
                'trigger' => 'admin/model/catalog/product/editProduct/after',
                'action' => 'octemplates/module/oct_price_tracker/send',
            ]
        ];

        foreach ($events as $event) {
            if (!$this->model_setting_event->getEventByCode($event['code'])) {
                $this->model_setting_event->addEvent($event['code'], $event['trigger'], $event['action'], 1, 550);
            }
        }
	}

	public function deleteEvent() {

        if (!$this->checkModifyPermission()) {
            return;
        }

        $this->load->model('setting/event');

        $eventCodes = [
            'octemplates-promo-price-tracker'
        ];

        foreach ($eventCodes as $code) {
            if ($this->model_setting_event->getEventByCode($code)) {
                $this->model_setting_event->deleteEventByCode($code);
            }
        }
	}

	public function send(&$route, &$data, &$output) {
		$oct_price_tracker_data = $this->config->get('oct_price_tracker_data');

		if ($this->shouldNotify($oct_price_tracker_data)) {            
			$this->load->model('octemplates/module/oct_price_tracker');

			$product_id = $data[0];
			
			if ($this->model_octemplates_module_oct_price_tracker->hasActivePriceRequests((int) $product_id)) {
				$cron_url = $this->getCronUrl($oct_price_tracker_data['cron_secret'], $product_id);
				$this->triggerCron($cron_url);
			}
		}
	}

	private function shouldNotify($oct_price_tracker_data) {
		return isset($oct_price_tracker_data['notify_on_edit']) && $oct_price_tracker_data['notify_on_edit'] &&
				isset($oct_price_tracker_data['cron_secret']) && $oct_price_tracker_data['cron_secret'];
	}

	private function getCronUrl($cron_secret, $product_id) {
		$site_link = $this->request->server['HTTPS'] ? HTTPS_CATALOG : HTTP_CATALOG;
		return $site_link . "index.php?route=octemplates/module/oct_price_tracker/cron&cron_secret=" . urlencode($cron_secret) . "&product_id=" . (int)$product_id;
	}

	private function triggerCron($cron_url) {
		$opts = [
			'http' => [
				'timeout' => 10
			]
		];

		$context = stream_context_create($opts);
		@file_get_contents($cron_url, false, $context);
	}

	private function checkModifyPermission($json_response = false) {
		if (!$this->user->hasPermission('modify', 'octemplates/module/oct_price_tracker')) {
			$error_message = $this->language->get('error_permission');

			if ($json_response) {
				$this->response->addHeader('Content-Type: application/json');
				$this->response->setOutput(json_encode(['error' => $error_message]));
			} else {
				$this->session->data['error_warning'] = $error_message;
				$this->response->redirect($this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true));
			}
			return false;
		}
		return true;
	}
}