<?php
namespace Teknisa\Libs\Service;

use Teknisa\Libs\Util\InstanceProvider;
use Teknisa\Libs\Util\Repositories\Migration as MigrationRepository;
use Teknisa\Libs\Util\Utilities;

class Migration {
    /** @var MigrationRepository $migrationRepository */
    private $migrationRepository;

    /**
     * @param MigrationRepository $migrationRepository
     */
    public function __construct(MigrationRepository $migrationRepository) {
        $this->migrationRepository = $migrationRepository;
    }

    /**
     * @param $nrOrg
     * @param $repositoriesInfo
     * @return array
     */
    public function getPendentMigrations($nrOrg, $repositoriesInfo) {
        try {
            $migrationInfo = array();
            $customEntityManager = InstanceProvider::getConnectionCustom()->updateVpdConnection($nrOrg);
            if(is_string($repositoriesInfo)) {
                $repositoriesInfo = json_decode($repositoriesInfo, true);
            }

            foreach ($repositoriesInfo as $repository) {
                $migDescription  = substr($repository['URL'], -50);
                if(!isset($migrationInfo[$migDescription])) {
                    try {                      
                        $versionObj = $this->migrationRepository->getLastAppliedMigration($migDescription, $customEntityManager);   
                    }  catch (\Exception $e) {
                        try{
                            $this->migrationRepository->executeUpdateVersaoObjetoScript($customEntityManager);
                        } catch (\Exception $e) { }
                        $versionObj = $this->migrationRepository->getLastAppliedMigration($migDescription, $customEntityManager);
                    }
                    $lastFile   = !empty($versionObj)  ? $versionObj[0]['NRVEROBJBD'] : null;
                    $pendFiles  = !empty($versionObj)  ? @json_decode($versionObj[0]['DSARQPENDMIG'], true) : array();
                    $pendFiles  = is_array($pendFiles) ? $pendFiles : array();

                    $migrationInfo[$migDescription] = array (
                        'REPOSITORY_ID'          => $repository['ID'],
                        'REPOSITORY_URL'         => $repository['URL'],
                        'REPOSITORY_NAME'        => $repository['NAME'],
                        'REPOSITORY_PATH'        => $repository['PATH'],
                        'REPOSITORY_REL_PATH'    => $repository['MIG_RELATIVE_PATH'],
                        'MIG_DESCRIPTION'        => $migDescription,
                        'MIG_LAST_FILE_NUMBER'   => $lastFile,
                        'MIG_PENDENT_FILES'      => $pendFiles
                    );
                }
            }

            return array_values($migrationInfo);
        } catch (\Exception $e) {
            return $this->errorTreatmentOnSQLExecution($e);
        }
    }

    /**
     * @param $script
     * @param $nrOrg
     * @return array
     * @throws \Exception
     */
    public function applyMigration($script, $nrOrg) {
        try {
            $customEntityManager = InstanceProvider::getConnectionCustom()->updateVpdConnection($nrOrg);
            $result = $this->migrationRepository->executeScript($script, $customEntityManager);
            return $this->errorTreatmentOnSQLExecution($result);
        } catch (\Exception $e) {
            return $this->errorTreatmentOnSQLExecution($e);
        }
    }

    /**
     * @param $file
     * @param $nrOrg
     * @return array
     * @throws \Exception
     */
    public function applyMigrationFile($file, $nrOrg) {
        try {
            $script = trim(file_get_contents($file), '"');
            try {
                unlink($file);
            } catch(\Exception $e) {}
            $customEntityManager = InstanceProvider::getConnectionCustom()->updateVpdConnection($nrOrg);
            $result = $this->migrationRepository->executeScript($script, $customEntityManager);
            return $this->errorTreatmentOnSQLExecution($result);
        } catch (\Exception $e) {
            return $this->errorTreatmentOnSQLExecution($e);
        }
    }

    /**
     * @param $nmObject
     * @param $fileName
     * @param $oldFile
     * @param $nrOrg
     * @param $cdOperator
     * @param $pendentFiles
     * @return array
     */
    public function saveLastSuccessMigration($nmObject, $fileName, $oldFile, $nrOrg, $cdOperator, $pendentFiles = '[]') {
        try {
            $customEntityManager = InstanceProvider::getConnectionCustom()->updateVpdConnection($nrOrg);
            if($oldFile) {
                $result = $this->migrationRepository->updateLastMigration($nmObject, $fileName, $nrOrg, $cdOperator, $customEntityManager, $pendentFiles);
            } else {
                $result = $this->migrationRepository->insertLastMigration($nmObject, $fileName, $nrOrg, $cdOperator, $customEntityManager, $pendentFiles);
            }
            return $this->errorTreatmentOnSQLExecution($result);
        } catch (\Exception $e) {
            return $this->errorTreatmentOnSQLExecution($e);
        }
    }

    /**
     * @param $result
     * @return array
     */
    private function errorTreatmentOnSQLExecution($result) {
        $error = $rowCount = null;

        if($result instanceof \Exception) {
            /** @var \Exception $result */
            $error = $result->getMessage();
        } else {
            /** @var \Doctrine\DBAL\Driver\Statement $result */
            $errorInfo = $result->errorInfo();
            if(isset($errorInfo['message']) && !empty($errorInfo['message'])) {
                $error = $errorInfo['message'];
            }
            $rowCount = $result->rowCount();
        }

        if(strpos($error, 'ORA-') !== false) {
            $error = 'ORA-' . explode('ORA-', $error)[1];
        }

        return array(
            'ROW_COUNT' => $rowCount,
            'ERROR'     => $error
        );
    }
}