<?php

// Load composer libraries
require_once __DIR__ . '/../vendor/autoload.php';

function dd($object)
{
    echo "<pre>";
    print_r($object);
    die();
}

// Setup environment variables
$dotenv = new Dotenv\Dotenv(__DIR__ . '/../');
$dotenv->load();

require '../app/configs/application.php';

// Setup sentry as soon as possible after getting $applicationConfig
if ($applicationConfig['sentry_enabled'] == 'TRUE') {
    Sentry\init([
        'dsn' => $applicationConfig['sentry_dsn'],
        'environment' => $applicationConfig['sentry_environment'],
    ]);
}

use Phalcon\Loader;
use Phalcon\Mvc\Micro;
use Phalcon\Mvc\Micro\Collection;
use Phalcon\Di\FactoryDefault;
use Phalcon\Db\Adapter\Pdo\Postgresql as PdoPg;
use Phalcon\Db\Adapter\Pdo\Mysql as PdoMysql;
use Phalcon\Events\Manager;
use Phalcon\Logger\Adapter\File as FileAdapter;
use Phalcon\Flash\Direct as FlashDirect;
use Phalcon\Security;
use Phalcon\Mvc\Model\Transaction\Manager as TxManager;

// Load Application Files

$loader = new Loader();
$loader->registerDirs(
    [
        __DIR__ . '/../app/models/',
        __DIR__ . '/../app/middlewares/',
        __DIR__ . '/../app/controllers/',
        __DIR__ . '/../app/middlewares/',
        __DIR__ . '/../app/libraries/',
        __DIR__ . '/../app/exceptions/',
        __DIR__ . '/../app/responses/',
        __DIR__ . '/../app/tools/',
        __DIR__ . '/../app/tools/validator/',
        __DIR__ . '/../app/traits/',
    ]
);
$loader->registerNamespaces(
    [
        'Jaga\Traits' => __DIR__ . '/../app/traits',
        'Jaga\Models' => __DIR__ . '/../app/models',
        'Jaga\Tools\Validator' => __DIR__ . '/../app/tools/validator',
        //'Jaga\Controllers' => __DIR__ . '/../app/controllers',
    ]
);
$loader->register();

// Setup dependency injections
$di = new FactoryDefault();

$di->set(
    'flash',
    function () {
        $flash = new FlashDirect(
            [
                'error'   => 'alert alert-danger',
                'success' => 'alert alert-success',
                'notice'  => 'alert alert-info',
                'warning' => 'alert alert-warning',
            ]
        );

        return $flash;
    }
);

$random = new \Phalcon\Security\Random();
$requestId = $random->hex(8);
$sharedMem = new stdClass();

$di->set('shared', function () use ($sharedMem) {
    return $sharedMem;
});

$di->set('setShared', function ($shared) use ($sharedMem) {
    $sharedMem = $shared;
});

$di->set('config', function () use ($applicationConfig) {
    return $applicationConfig;
});

$di->set(
    'minio',
    function () {
        $minio = new MinioService(new Aws\S3\S3Client([
            'version'  => getenv("MINIO_VERSION"),
            'region'   => getenv("MINIO_REGION"),
            'endpoint' => getenv("MINIO_ENDPOINT"),
            'http'     => [
                'verify' => boolval(getenv("MINIO_VERIFY_SSL"))
            ],
            'use_path_style_endpoint' => true,
            'credentials' => [
                'key'    => getenv("MINIO_KEY"),
                'secret' => getenv("MINIO_SECRET"),
            ],
        ]));
        return $minio;
    }
);

$di->set(
    'db',
    function () use ($applicationConfig) {
        $connection = new PdoPg($applicationConfig['database']);
        return $connection;
    }
);

$di->set(
    'databaseElhkpnMart',
    function () use ($applicationConfig) {
        $connection = new PdoMysql($applicationConfig['databaseElhkpnMart']);
        return $connection;
    }
);

$di->set('databaseNewStranas2024',
    function () use ($applicationConfig) {
        $connection = new PdoPg($applicationConfig['databaseNewStranas2024']);
        return $connection;
    }
);

$di->set('databaseNewStranas2025',
    function () use ($applicationConfig) {
        $connection = new PdoPg($applicationConfig['databaseNewStranas2025']);
        return $connection;
    }
);

$di->set(
    'logger',
    function () use ($applicationConfig, $requestId) {
        $date = date('Y-m-d');
        $filename = $applicationConfig['log']['prefix'] . '-' . $date . '.log';
        $basicLogger = new FileAdapter($applicationConfig['log']['dir'] . $filename);
        return new BaseKvLogger($basicLogger, $requestId);
    }
);

$di->set(
    'apiLog',
    function () use ($applicationConfig) {
        return new ApiErrorsService($applicationConfig);
    }
);


$di->set('requestId', $requestId);

$di->set(
    'security',
    function () {
        $security = new Security();

        // Set the password hashing factor to 12 rounds
        $security->setWorkFactor(12);

        return $security;
    },
    true
);

$di->set("transaction", function () {
    $txManager = new TxManager();
    $transaction = $txManager->get();
    return $transaction;
});

$di->set("bg", function () use ($applicationConfig) {
    return new BackgroundJob($applicationConfig["beanstalk_config"]);
});

/**
 * Using Redis as Caching Machine
 */
$di->set('redis', function () {
    $redis = new \Redis();
    $redis->connect(getenv("REDIS_HOST"), getenv("REDIS_PORT"));
    return $redis;
});

$app = new Micro($di);

// Register routes
$eventsManager = new Manager();

foreach ($applicationConfig['routes'] as $key => $routeConfig) {
    $collection = new Collection();
    $collection->setPrefix($routeConfig['prefix']);
    $collection->setHandler($routeConfig['controller'], true);

    foreach ($routeConfig['paths'] as $key => $pathEntry) {
        $verb = $pathEntry['verb'];

        $collection->$verb(
            $pathEntry['path'],
            $pathEntry['method'],
            isset($pathEntry['name']) ? $pathEntry['name'] : null
        );
    }

    $app->mount($collection);
}

// Register Middlewares
foreach ($applicationConfig['middlewares'] as $joint => $middlewares) {
    foreach ($middlewares as $key => $middlewareClass) {
        $eventsManager->attach('micro', new $middlewareClass);
        $app->$joint(new $middlewareClass);
    }
}

// Special middleware: Logging Middleware. Same instance for before & after
$loggingMiddleware = new LoggingMiddleware();
$eventsManager->attach('micro', $loggingMiddleware);
$app->before($loggingMiddleware);
$app->after($loggingMiddleware);

$app->setEventsManager($eventsManager);

require '../app/error_handler.php';

// Good to go!
$app->handle();
