<?php

namespace Teknisa\Libs\Controller;

use Teknisa\Libs\Util\Environment;
use Teknisa\Libs\Service\CRUD as CRUDService;
use Zeedhi\Framework\DTO\Response\Error;
use Zeedhi\Framework\DTO;
use Zeedhi\Framework\DataSource\DataSet;
use Zeedhi\Framework\DataSource\FilterCriteria;

class CRUD {
    const DATABASE_NAME = 'dbname';

    /** @var CRUD */
    protected $crudService;
    /** @var  Environment */
    protected $environment;
    protected $dataSourceName;
    protected $dataSourceNameToSave = false;

    public function __construct(CRUDService $crudService, Environment $environment) {
        $this->crudService = $crudService;
        $this->environment = $environment;
    }

    public function checkHistory(DTO\Response $response, $row) {
        $condition = array(
            array(
                "columnName" => "NRORG",
                "operator" => "=",
                "value" => $this->environment->getNrOrgTrab()
            ),
            array(
                "columnName" => strtoupper($row['saveHistoryTable']['__table_master_pk']),
                "operator" => "=",
                "value" => $row[strtoupper($row['saveHistoryTable']['__table_master_pk'])]
            ),
            array(
                "columnName" => strtoupper($row['saveHistoryTable']['__table_competenc']),
                "operator" => "=",
                "value" => $row[strtoupper($row['saveHistoryTable']['__table_competenc'])]
            )
        );

        $filterCriteria = new FilterCriteria($row['saveHistoryTable']['__table_history_name'], $condition);
        $newFilterCriteria = $this->crudService->populateParameterBag($filterCriteria, array());
        $this->crudService->find($response, $newFilterCriteria);

        if (count($response->getDataSets()[0]->getRows()) > 0) {
            return true;
        } else {
            return false;
        }
    }

    public function save(DTO\Request $request, DTO\Response $response) {
        try {
            $this->dataSourceName = $request->getParameter(self::DATABASE_NAME);
            $this->dataSourceNameToSave = $this->crudService->getDataSourceNameToSaveByName($this->dataSourceName);
            $this->dataSourceName = $this->dataSourceNameToSave ? $this->dataSourceNameToSave : $this->dataSourceName;
            $rows = $this->crudService->getRowsToSave($request, $this->dataSourceName);
            $this->crudService->save($this->dataSourceName, $rows);

            $request = $this->crudService->buildDataSetIfRow($request, $this->dataSourceName);

            $currentRow = current($request->getDataSet()->getRows());

            if(isset($currentRow['saveHistoryTable'])) {

                if (!$currentRow['__is_new']) {
                    if (!$this->checkHistory($response, $currentRow)) {
                        // is new history
                        $currentRow['__is_new'] = true;
                    }
                }

                $tableMasterPK = strtoupper($currentRow['saveHistoryTable']['__table_master_pk']);
                $newCode = array_filter($this->crudService->getColumnsToReturn(), function ($element) use ($tableMasterPK) {
                    return $element[$tableMasterPK];
                });

                $this->dataSourceNameToSave = $this->crudService->getDataSourceNameToSaveByName($currentRow['saveHistoryTable']['__table_history_name']);
                $this->dataSourceName = $this->dataSourceNameToSave ? $this->dataSourceNameToSave : $this->dataSourceName;
                $currentRow[strtoupper($currentRow['saveHistoryTable']['__table_master_pk'])] = intval($newCode[0][strtoupper($currentRow['saveHistoryTable']['__table_master_pk'])]);

                // set history properties
                $currentRow['__new_code_pk'] = $currentRow['saveHistoryTable']['__table_history_name'];
                $currentRow['__table_pk'] = $currentRow['saveHistoryTable']['__table_history_pk'];
                $currentRow['__columns_to_return'] = $currentRow['saveHistoryTable']['__columns_to_return'];

                $newDataSet = new DataSet($this->dataSourceName, array($currentRow));
                $newRequest = new \Zeedhi\Framework\DTO\Request\DataSet($newDataSet,
                    $request->getMethod(), $request->getRoutePath(), $request->getUserId());
                $rows = $this->crudService->getRowsToSave($newRequest, $this->dataSourceName);
                $this->crudService->save($this->dataSourceName, $rows);

            }
            $response->addDataset(new DataSet('columnsToReturn', $this->crudService->getColumnsToReturn()));
        } catch (\Exception $e) {
            $response->setError(new Error($e->getMessage(), 500));
        }
    }

    public function find(DTO\Request\Filter $request, DTO\Response $response) {
        try {
            $this->dataSourceName = $request->getParameter(self::DATABASE_NAME);
            $filterCriteria = $request->getFilterCriteria();
            $filterCriteria->setDataSourceName($this->dataSourceName);
            $filterCriteria = $this->crudService->getFilterCriteriaWithNrOrg($filterCriteria);
            $newFilterCriteria = $this->crudService->getPopulatedFilterCriteria($filterCriteria, array());
            $this->crudService->find($response, $newFilterCriteria);
        } catch (\Exception $e) {
            $response->setError(new Error($e->getMessage(), 500));
        }
    }

    public function delete(DTO\Request $request, DTO\Response $response) {
        try {
            $this->dataSourceName = $request->getParameter(self::DATABASE_NAME);
            $this->dataSourceName = $this->crudService->getDataSourceNameToSaveByName($this->dataSourceName);
            $request = $this->crudService->buildDataSetIfRow($request, $this->dataSourceName);
            $rows = $this->crudService->getRowsToDelete($request, $this->dataSourceName);
            $dataSet = new DataSet($this->dataSourceName, (array)$rows);
            $this->crudService->delete($response, $dataSet);
        } catch (\Exception $e) {
            $response->setError(new Error($e->getMessage(), 500));
        }
    }
}