<?php

declare(strict_types=1);

namespace Flowaxy\Infrastructure\Config;

use Flowaxy\Core\System\PathResolver;
use Flowaxy\Support\Facades\Log;
use Flowaxy\Support\Helpers\IniHelper;
use Throwable;

use function defined;
use function file_exists;
use function is_array;
use function is_dir;
use function mkdir;
use const DIRECTORY_SEPARATOR;
use const DS;

/**
 * Менеджер конфигурации плагинов
 * Управляет состоянием плагинов через storage/config/system/plugins.ini
 */
final class PluginConfigManager
{
    private const CONFIG_FILE = 'plugins.ini';
    private const CONFIG_SECTION = 'plugins';

    /**
     * Получить путь к файлу конфигурации плагинов
     *
     * @return string
     */
    private static function getConfigPath(): string
    {
        $ds = defined('DS') ? DS : DIRECTORY_SEPARATOR;
        $configPath = PathResolver::storageConfig() . $ds . 'system' . $ds . self::CONFIG_FILE;

        // Создаем директорию, если её нет
        $configDir = dirname($configPath);
        if (!is_dir($configDir)) {
            @mkdir($configDir, 0755, true);
        }

        return $configPath;
    }

    /**
     * Загрузить конфигурацию плагинов
     *
     * @return array<string, string>
     */
    public static function loadConfig(): array
    {
        $configPath = self::getConfigPath();

        if (!file_exists($configPath)) {
            return [];
        }

        try {
            if (class_exists(IniHelper::class)) {
                $config = IniHelper::readFile($configPath, true);
                if (is_array($config) && isset($config[self::CONFIG_SECTION]) && is_array($config[self::CONFIG_SECTION])) {
                    return $config[self::CONFIG_SECTION];
                }
            } else {
                $config = parse_ini_file($configPath, true);
                if ($config !== false && isset($config[self::CONFIG_SECTION]) && is_array($config[self::CONFIG_SECTION])) {
                    return $config[self::CONFIG_SECTION];
                }
            }
        } catch (Throwable $e) {
            try {
                Log::Error('PluginConfigManager: Failed to load plugins config', [
                    'error' => $e->getMessage(),
                    'file' => $configPath,
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
        }

        return [];
    }

    /**
     * Сохранить конфигурацию плагинов
     *
     * @param array<string, string> $plugins
     * @return bool
     */
    private static function saveConfig(array $plugins): bool
    {
        $configPath = self::getConfigPath();

        try {
            // Проверяем права на запись
            $configDir = dirname($configPath);
            if (!is_writable($configDir) && !is_writable($configPath)) {
                try {
                    Log::Error('PluginConfigManager: Config directory or file is not writable', [
                        'file' => $configPath,
                        'dir_writable' => is_writable($configDir),
                        'file_writable' => file_exists($configPath) ? is_writable($configPath) : false,
                    ]);
                } catch (Throwable $logError) {
                    // Ignore logging errors
                }
                return false;
            }

            $data = [self::CONFIG_SECTION => $plugins];

            if (class_exists(IniHelper::class)) {
                $result = IniHelper::writeFile($configPath, $data);
                if (!$result) {
                    try {
                        Log::Error('PluginConfigManager: IniHelper::writeFile() returned false', [
                            'file' => $configPath,
                        ]);
                    } catch (Throwable $logError) {
                        // Ignore logging errors
                    }
                }
                return $result;
            }

            // Fallback: записываем напрямую
            $content = "[" . self::CONFIG_SECTION . "]\n";
            foreach ($plugins as $slug => $status) {
                $content .= "{$slug} = {$status}\n";
            }
            $result = @file_put_contents($configPath, $content) !== false;
            if ($result) {
                @chmod($configPath, 0644);
            } else {
                try {
                    Log::Error('PluginConfigManager: file_put_contents() failed', [
                        'file' => $configPath,
                        'dir_exists' => is_dir($configDir),
                        'dir_writable' => is_writable($configDir),
                    ]);
                } catch (Throwable $logError) {
                    // Ignore logging errors
                }
            }
            return $result;
        } catch (Throwable $e) {
            try {
                Log::Error('PluginConfigManager: Failed to save plugins config', [
                    'error' => $e->getMessage(),
                    'file' => $configPath,
                    'exception' => $e,
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
            return false;
        }
    }

    /**
     * Получить статус плагина
     *
     * @param string $slug
     * @return string 'active' | 'deactive' | 'Non-install'
     */
    public static function getStatus(string $slug): string
    {
        $plugins = self::loadConfig();
        return $plugins[$slug] ?? 'Non-install';
    }

    /**
     * Установить статус плагина
     *
     * @param string $slug
     * @param string $status 'active' | 'deactive' | 'Non-install'
     * @return bool
     */
    public static function setStatus(string $slug, string $status): bool
    {
        if (!in_array($status, ['active', 'deactive', 'Non-install'], true)) {
            try {
                Log::Warning('PluginConfigManager: Invalid status', [
                    'slug' => $slug,
                    'status' => $status,
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
            return false;
        }

        $plugins = self::loadConfig();
        $plugins[$slug] = $status;
        return self::saveConfig($plugins);
    }

    /**
     * Проверить, установлен ли плагин
     *
     * @param string $slug
     * @return bool
     */
    public static function isInstalled(string $slug): bool
    {
        $status = self::getStatus($slug);
        return $status !== 'Non-install';
    }

    /**
     * Проверить, активен ли плагин
     *
     * @param string $slug
     * @return bool
     */
    public static function isActive(string $slug): bool
    {
        return self::getStatus($slug) === 'active';
    }

    /**
     * Получить все плагины
     *
     * @return array<string, string>
     */
    public static function getAll(): array
    {
        return self::loadConfig();
    }

    /**
     * Удалить плагин из конфигурации
     *
     * @param string $slug
     * @return bool
     */
    public static function remove(string $slug): bool
    {
        $plugins = self::loadConfig();
        if (isset($plugins[$slug])) {
            unset($plugins[$slug]);
            return self::saveConfig($plugins);
        }
        return true;
    }
}
