<?php
/**
* @package   BaForms
* @author    Balbooa http://www.balbooa.com/
* @copyright Copyright @ Balbooa
* @license   http://www.gnu.org/licenses/gpl.html GNU/GPL
*/

namespace Balbooa\Component\Forms\Administrator\Controller;

defined('_JEXEC') or die;

use Balbooa\Component\Forms\Administrator\Controller\Trait\HasDownloadFile;
use Balbooa\Component\Forms\Administrator\Controller\Trait\HasSessionTokenCheck;
use Balbooa\Component\Forms\Administrator\Helper\AccessGuard;
use Balbooa\Component\Forms\Administrator\Helper\Filesystem\File;
use Balbooa\Component\Forms\Site\Helper\Uploads\Enums\UploadEnum;
use Balbooa\Component\Forms\Site\Helper\Uploads\Factory\UploadsFactory;
use Joomla\CMS\MVC\Controller\AdminController;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Response\JsonResponse;

class SubmissionsController extends AdminController
{
    use HasSessionTokenCheck;
    use HasDownloadFile;

    public function getModel($name = 'Submission', $prefix = 'Administrator', $config = ['ignore_request' => true])
    {
        return parent::getModel($name, $prefix, $config);
    }

    public function removeTmpAttachment()
    {
        $input = Factory::getApplication()->input;
        $id = $input->get('id', 0, 'int');
        $submission = $input->get('submission', 0, 'int');
        $filename = $input->get('filename', '', 'string');
        $model = $this->getModel();
        $model->removeTmpAttachment($id, $filename, $submission);
        exit();
    }

    public function contextDelete()
    {
        AccessGuard::check('core.delete');
        $id = $this->input->get('id', 0, 'int');
        $model = $this->getModel();
        $model->contextDelete($id);
        exit;
    }

    public function delete()
    {
        AccessGuard::check('core.delete');
        $cid = $this->input->get('cid', [], 'array');
        $model = $this->getModel();
        $model->deleteFiles($cid);
        parent::delete();
        echo Text::_('COM_BAFORMS_N_ITEMS_DELETED');
        exit;
    }

    public function readAll()
    {
        $model = $this->getModel();
        $model->readAll();
        exit;
    }

    public function unread()
    {
        $cid = $this->input->get('cid', [], 'array');
        $model = $this->getModel();
        foreach ($cid as $id) {
            $model->setReadStatus($id, 1);
        }
        exit;
    }
    
    public function setReadStatus()
    {
        $id = $this->input->get('id', 0, 'int');
        $state = $this->input->get('state', 0, 'int');
        $model = $this->getModel();
        $model->setReadStatus($id, $state);
        exit;
    }

    public function getTotal($str)
    {
        $object = json_decode($str);
        $thousand = $object->options->thousand;
        $separator = $object->options->separator;
        $decimals = $object->options->decimals;
        $total = $object->total * 1;
        if ($object->options->tax->enable) {
            $tax = $total * $object->options->tax->value / 100;
            $total += $tax;
        }
        if (isset($object->promo)) {
            $discount = $object->options->promo->discount * 1;
            if ($object->options->promo->unit == '%') {
                $discount = $total * $discount / 100;
            }
            $total -= $discount;
        }
        if (isset($object->shipping)) {
            $shipping = $object->shipping->price * 1;
        }
        $price = $this->renderPrice((string)$total, $thousand, $separator, $decimals);
        if (!empty($object->options->position)) {
            $price .= ' '.$object->options->symbol;
        } else {
            $price = $object->options->symbol.' '.$price;
        }

        return $price;
    }

    public function renderPrice($value, $thousand, $separator, $decimals)
    {
        $delta = $value < 0 ? '-' : '';
        $value = str_replace('-', '', $value);
        $priceArray = explode('.', $value);
        $priceThousand = $priceArray[0];
        $priceDecimal = $priceArray[1] ?? '';
        $value = '';
        if (($pricestrlen = strlen($priceThousand)) > 3 && $thousand != '') {
            for ($i = 0; $i < $pricestrlen; $i++) {
                if ($i % 3 == 0 && $i != 0) {
                    $value .= $thousand;
                }
                $value .= $priceThousand[$pricestrlen - 1 - $i];
            }
            $value = strrev($value);
        } else {
            $value .= $priceThousand;
        }
        if ($decimals != 0) {
            $value .= $separator;
            for ($i = 0; $i < $decimals; $i++) {
                $value .= $priceDecimal[$i] ?? '0';
            }
        }

        return $delta.$value;
    }
    
    public function exportXML()
    {
        $data = explode(',', $_POST['data']);
        $doc = new \DOMDocument('1.0');
        $doc->formatOutput = true;
        $root = $doc->createElement('submissions');
        $root = $doc->appendChild($root);
        $model = $this->getModel();
        foreach($data as $id) {
            $obj = $model->getMessage($id);
            $files = $model->getFiles($id);
            $postroot = $doc->createElement('submission');
            $postroot = $root->appendChild($postroot);
            $title = $doc->createElement('title');
            $title = $postroot->appendChild($title);
            $text = $doc->createTextNode($obj->title);
            $text = $title->appendChild($text);
            $title = $doc->createElement('date');
            $title = $postroot->appendChild($title);
            $text = $doc->createTextNode($obj->date_time);
            $text = $title->appendChild($text);
            foreach($obj->message as $message) {
                $patern = ['~', '`', '!', '@', '"', '#', '№', '$', ';', '%', '^', '&', '?', '*',
                    '(', ')', '-', '+', '=', '/', '|', '.', "'", ',', '\\', '€', '£'];
                $replace = ' ';
                $title = str_replace($patern, $replace, $message->title);
                $title = preg_replace('/\s+/', ' ', $title);
                $title = trim($title);
                $title = str_replace(' ', '-', $title);
                if (empty($title)) {
                    $title = 'Label';
                }
                $title = $doc->createElement($title);
                $title = $postroot->appendChild($title);
                if ($message->type == 'total') {
                    $total = $this->getTotal($message->message);
                    $text = $total;
                } else if ($message->type == 'upload' && isset($files->{$message->field_id})) {
                    $pathes = [];
                    $attachmentsHelper = UploadsFactory::getInstance(UploadEnum::Attachments);
                    foreach ($files->{$message->field_id}->files as $file) {
                        $pathes[] = $attachmentsHelper->getFileLink($file->form_id, $file->filename);
                    }
                    $text = implode(', ', $pathes);
                } else if ($message->type == 'poll') {
                    $results = $obj->pollResults->{$message->field_id};
                    $text = $message->message;
                    foreach ($results as $result) {
                        $text .= ' '.$result->title.': '.$result->votes.' '.Text::_('VOTES').', '.$result->percent.'%;';
                    }
                } else {
                    $text = $message->message;
                }
                $text = str_replace('<br>', ' ', $text);
                $text = $doc->createTextNode($text);
                $text = $title->appendChild($text);
            }
        }
        $time = time();
        $file = "baform-$time.xml";

        $bytes = $doc->save(Factory::getConfig()->get('tmp_path') . "/$file");
        if ($bytes) {
            echo new JsonResponse(true, $file);
        } else {
            echo new JsonResponse(false, '', true);
        }
        jexit();
    }

    public function showSubmission()
    {
        $input = Factory::getApplication()->input;
        $id = $input->get('id', 0, 'int');
        $model = $this->getModel();
        $obj = $model->getMessage($id);
        $obj->time = date('H:i', strtotime($obj->date_time));
        $obj->files = $model->getFiles($id);
        $msg = json_encode($obj);
        echo $msg;exit();
    }
    
    public function exportCSV()
    {
        $str = $this->input->get('data', '', 'string');
        $data = explode(',', $str);
        $list = [];
        $model = $this->getModel();
        $csv = new \stdClass();
        $i = 2;
        $array = [Text::_('DATE'), Text::_('ID')];
        foreach ($data as $id) {
            $obj = $model->getMessage($id);
            $title = $obj->title;
            if (!isset($csv->{$title})) {
                $i = 2;
                $object = new \stdClass();
                $object->keys = [];
                $object->data = [];
                $csv->{$title} = $object;
            } else {
                $object = $csv->{$title};
            }
            foreach ($obj->message as $msg) {
                $title = $msg->title;
                if (!isset($object->keys[$title])) {
                    $object->keys[$title] = $i++;
                }
                $msg->ind = $object->keys[$title];
            }
            $object->data[] = $obj;
        }
        foreach ($csv as $title => $obj) {
            $list[] = [$title];
            $header = array_merge($array, []);
            foreach ($obj->keys as $key => $value) {
                $header[] = $key;
            }
            $list[] = $header;
            foreach ($obj->data as $object) {
                $info = [];
                $files = $model->getFiles($object->id);
                foreach ($header as $i => $value) {
                    $info[] = '';
                }
                $info[0] = $object->date_time;
                $info[1] = $object->id;
                foreach ($object->message as $value) {
                    if ($value->type == 'total') {
                        $info[$value->ind] = $this->getTotal($value->message);
                    } else if ($value->type == 'upload' && isset($files->{$value->field_id})) {
                        $pathes = [];
                        $attachmentsHelper = UploadsFactory::getInstance(UploadEnum::Attachments);
                        foreach ($files->{$value->field_id}->files as $file) {
                            $pathes[] = $attachmentsHelper->getFileLink($file->form_id, $file->filename);
                        }
                        $info[$value->ind] = implode(', ', $pathes);
                    } else if ($value->type == 'poll') {
                        $results = $object->pollResults->{$value->field_id};
                        $info[$value->ind] = strip_tags($value->message);
                        foreach ($results as $result) {
                            $info[$value->ind] .= ' '.$result->title.': '.$result->votes.' '.Text::_('VOTES').', '.$result->percent.'%;';
                        }
                    } else if ($value->type == 'selectMultiple' || $value->type == 'checkbox') {
                        $array = explode(';<br>', $value->message);
                        $result = array_filter($array, fn($el) => !empty($el));
                        $value->message = implode('; ', $result);
                        $info[$value->ind] = strip_tags($value->message);
                    } else {
                        $info[$value->ind] = preg_replace('~[\r\n]+~', '', strip_tags($value->message));
                    }
                }
                $list[] = $info;
            }
        }
        $time = time();
        $file =  "baform-$time.csv";
        $fp = fopen(Factory::getConfig()->get('tmp_path') . "/$file", 'w');
        fwrite ($fp, b"\xEF\xBB\xBF");
        foreach ($list as $row) {
            fputcsv($fp, $row);
        }
        fclose($fp);
        echo new JsonResponse(true, $file);
        jexit();
    }
    
    public function download()
    {
        $file = $this->input->get('file', '', 'string');
        $this->downloadFile($file);
    }
}