<?php
require_once APPPATH . 'libraries/Cf_REST_Controller.php';

/**
 * Class Api
 */
class Api extends Cf_REST_Controller
{
    /**
     * @rbacName Allow to export and import system settings
     * @rbacGroup Data transfer
     * @rbacAlias data_transfer_api.admin_permissions
     */

    /**
     * Api constructor.
     */
    public function __construct()
    {
        parent::__construct();
        $this->load->model('data_transfer/data_transfer_model');
        $this->load->helper('cf_directory');
        $this->load->library('Cf_Encrypt');
        $this->data_transfer_model->setRestClient($this->getRestClient());
        $this->data_transfer_model->setIsAdmin(isActionAllowed('data_transfer_api.admin_permissions'));
    }

    /**
     * @rbacName API: Export
     * @rbacGroup Data transfer
     * @rbacAlias data_transfer_api.export_get
     * @rbacAllowedByDefault
     *
     * @throws Exception
     */
    public function export_get()
    {
        try {
            $inputs = $_REQUEST;
            $fileName = $this->data_transfer_model->export([
                'items' => $inputs['items'],
                'username' => $this->session->userdata('username'),
                'exportOnlyUserItems' => $inputs['exportOnlyUserItems'],
                'encryptionKey' => $inputs['encryptionKey'],
            ]);

            $this->respond(200, json_encode(['name' => $fileName], JSON_PRETTY_PRINT));
            return;
        } catch (Exception $exception) {
            log_message('error', 'Unable to export. Error: ' . $exception->getMessage());
            throw $exception;
        }
    }

    /**
     * @rbacName API: Get export categories
     * @rbacGroup Data transfer
     * @rbacAlias data_transfer_api.exportItems_get
     * @rbacAllowedByDefault
     *
     * @throws Exception
     */
    public function exportItems_get()
    {
        try {
            $cats = $this->data_transfer_model->getExportCategories();
            $this->respond(200, json_encode($cats, JSON_PRETTY_PRINT));
            return;
        } catch (Exception $exception) {
            log_message('error', 'Unable to get export categories. Error: ' . $exception->getMessage());
            throw $exception;
        }
    }

    /**
     * @rbacName API: Import
     * @rbacGroup Data transfer
     * @rbacAlias data_transfer_api.import_post
     * @rbacAllowedByDefault
     *
     * @throws Exception
     */
    public function import_post()
    {
        try {
            $phar = $this->readPharFromFile();

            if (!isset($phar['export.json']) || !$phar['export.json']->isFile()) {
                throw new Exception('Wrong archive');
            }

            if (!$this->data_transfer_model->validateEncryptionKey($phar, $this->input->post('encryptionKey'))) {
                throw new Exception('Wrong encryption key');
            }

            $this->data_transfer_model->import($phar, [
                'username' => $this->session->userdata('username'),
                'skipDuplicates' => $this->input->post('skipDuplicates'),
                'encryptionKey' => $this->input->post('encryptionKey'),
            ]);
        } catch (Exception $exception) {
            log_message('error', 'Unable to get import. Error: ' . $exception->getMessage());
            throw $exception;
        }
    }

    /**
     * @rbacName API: Analyze import file
     * @rbacGroup Data transfer
     * @rbacAlias data_transfer_api.analyzeImportFile_post
     * @rbacAllowedByDefault
     *
     * @throws Exception
     */
    public function analyzeImportFile_post()
    {
        $archive = $this->readPharFromFile();
        if (isset($archive['export.json']) && $archive['export.json']->isFile()) {
            $info = $this->data_transfer_model->analyzeImport(
                json_decode($archive['export.json']->getContent(), JSON_OBJECT_AS_ARRAY),
            );
            $this->respond(200, json_encode($info, JSON_PRETTY_PRINT));
            return;
        } else {
            $message = 'Wrong archive was upload to import';
            log_message('debug', $message);
            throw new Exception($message);
        }
    }

    /**
     * @rbacName API: Download export file
     * @rbacGroup Data transfer
     * @rbacAlias data_transfer_api.download_get
     * @rbacAllowedByDefault
     *
     * @param $name
     * @throws Exception
     */
    public function download_get($name)
    {
        $tmpPath = get_tmpdir();
        $fullPath = realpath($tmpPath . '/' . $name);

        if (!file_exists($fullPath)) {
            $message = "Export file $name not found.";
            log_message('debug', $message);
            throw new Exception($message);
        }

        if (!strstr($fullPath, $tmpPath)) {
            throw new Exception('Resolved path must be a sub directory of ' . $tmpPath . $fullPath);
        }

        download_file($fullPath, $name);
        exit();
    }

    /**
     * @return Phar
     * @throws Exception
     */
    private function readPharFromFile()
    {
        if (isset($_FILES['file']) && file_exists($_FILES['file']['tmp_name'])) {
            $filePath = get_tmpdir() . $_FILES['file']['name'];
            copy($_FILES['file']['tmp_name'], $filePath);
            return new Phar($filePath);
        } else {
            throw new Exception('Something went wrong during file uploading');
        }
    }
}
