<?php

namespace PortalPeople\indicator;

use Yii;
use yii\base\BootstrapInterface;
use yii\base\Module as BaseModule;
use yii\console\Application as ConsoleApplication;
use yii\base\InvalidConfigException;
use PortalPeople\indicator\services\FtpDownloadService;
use PortalPeople\indicator\services\ProcessFilesService;

class Module extends BaseModule implements BootstrapInterface
{
    public $defaultRoute = 'config/index';
    public $controllerNamespace = 'PortalPeople\\indicator\\controllers';

    public bool $enabled = false;
    public string $protocol = 'sftp';
    public string $host = '';
    public int $port = 22;
    public string $username = '';
    public string $password = '';
    public string $remotePath = '/';
    public bool $deleteAfterDownload = false;
    public bool $moveAfterDownload = false;
    public string $moveToPath = '';
    public bool $passiveMode = true;
    public int $pickupIntervalSeconds = 900;
    public int $processIntervalSeconds = 120;
    public string $summaryEmail = '';
    public string $defaultAccountCode = 'ZUPA001';
    public string $cartClass = 'PortalPeople\\indicator\\models\\Cart';
    public string $queueComponent = 'queue';
    public bool $debug = false;

    public function bootstrap($app): void
    {
        $this->id = 'indicator';

        if (!isset($app->getModules()[$this->id])) {
            $app->setModule($this->id, $this);
        }

        if (!($app instanceof ConsoleApplication) && isset($app->urlManager)) {
            $app->urlManager->addRules([
                'indicator/<controller:[\\w\\-]+>/<action:[\\w\\-]+>' => 'indicator/<controller>/<action>',
                'indicator/<action:[\\w\\-]+>' => 'indicator/config/<action>',
            ], true);
        }
    }

    public function init(): void
    {
        parent::init();

        $this->loadConfigFromParams();

        if (Yii::$app instanceof ConsoleApplication) {
            $this->controllerNamespace = 'PortalPeople\\indicator\\commands';
        }

        $this->ensureRuntimeDirectories();
    }

    public function isConfigured(): bool
    {
        return $this->enabled
            && trim($this->host) !== ''
            && trim($this->username) !== '';
    }

    /**
     * @throws InvalidConfigException
     */
    public function createDownloadService(): FtpDownloadService
    {
        if (!$this->enabled) {
            throw new InvalidConfigException('Indicator module is disabled.');
        }

        return new FtpDownloadService([
            'module' => $this,
            'protocol' => strtolower($this->protocol),
            'host' => $this->host,
            'port' => $this->port,
            'username' => $this->username,
            'password' => $this->password,
            'remotePath' => $this->remotePath,
            'deleteAfterDownload' => $this->deleteAfterDownload,
            'moveAfterDownload' => $this->moveAfterDownload,
            'moveToPath' => $this->moveToPath,
            'passiveMode' => $this->passiveMode,
            'inboxPath' => $this->getInboxPath(),
        ]);
    }

    /**
     * @throws InvalidConfigException
     */
    public function createProcessService(): ProcessFilesService
    {
        if (!$this->enabled) {
            throw new InvalidConfigException('Indicator module is disabled.');
        }

        return new ProcessFilesService([
            'module' => $this,
            'inboxPath' => $this->getInboxPath(),
            'processedPath' => $this->getProcessedPath(),
            'failedPath' => $this->getFailedPath(),
            'cartClass' => $this->cartClass,
        ]);
    }

    public function getInboxPath(): string
    {
        return Yii::getAlias('@runtime/indicator/inbox');
    }

    public function getProcessedPath(): string
    {
        return Yii::getAlias('@runtime/indicator/processed');
    }

    public function getFailedPath(): string
    {
        return Yii::getAlias('@runtime/indicator/failed');
    }

    private function ensureRuntimeDirectories(): void
    {
        $paths = [
            $this->getInboxPath(),
            $this->getProcessedPath(),
            $this->getFailedPath(),
        ];

        foreach ($paths as $path) {
            if (!is_dir($path)) {
                @mkdir($path, 0755, true);
            }
        }
    }

    private function loadConfigFromParams(): void
    {
        $params = Yii::$app->params;
        $config = $params['plugins']['indicator'] ?? $params['indicator'] ?? null;

        if (!is_array($config)) {
            return;
        }

        foreach ([
            'enabled',
            'protocol',
            'host',
            'port',
            'username',
            'remotePath',
            'deleteAfterDownload',
            'moveAfterDownload',
            'moveToPath',
            'passiveMode',
            'pickupIntervalSeconds',
            'processIntervalSeconds',
            'summaryEmail',
            'defaultAccountCode',
            'cartClass',
            'queueComponent',
            'debug',
        ] as $key) {
            if (array_key_exists($key, $config)) {
                $this->$key = $config[$key];
            }
        }

        if (array_key_exists('password', $config)) {
            $stored = (string) $config['password'];
            $this->password = $stored;

            if ($stored !== '') {
                // Primary: base64 + decryptByPassword (written by ConfigForm)
                $binary = base64_decode($stored, true);
                if ($binary !== false) {
                    try {
                        $this->password = Yii::$app->security->decryptByPassword($binary, 'indicator_password_key');
                    } catch (\Throwable $e) {
                        // Fall through to legacy method
                    }
                }

                // Legacy fallback: backend Security class
                if ($this->password === $stored && class_exists('backend\\components\\Security')) {
                    try {
                        $this->password = \backend\components\Security::decryptSensitiveData($stored);
                    } catch (\Throwable $e) {
                        // Leave as-is (may already be plaintext)
                    }
                }
            }
        }

        // Support old-style key names saved before v1.0.1
        if (empty($this->host) && isset($config['ftpHost'])) {
            $this->host = $config['ftpHost'];
        }
        if (empty($this->username) && isset($config['user'])) {
            $this->username = $config['user'];
        }
        if ($this->remotePath === '/' && isset($config['path'])) {
            $this->remotePath = $config['path'];
        }
        if (empty($this->cartClass) && isset($config['cart_class'])) {
            $this->cartClass = $config['cart_class'];
        }
        if (!$this->enabled && isset($config['host']) && $config['host'] !== '') {
            $this->enabled = true;
        }

        if ((int) $this->port <= 0) {
            $proto = strtolower((string) $this->protocol);
            $this->port = ($proto === 'ftp' || $proto === 'ftps') ? 21 : 22;
        }
    }
}
