<?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/logging.ini
 */
final class LoggingConfigManager
{
    private const CONFIG_FILE = 'logging.ini';
    private const CONFIG_SECTION = 'logging';

    /**
     * Получить путь к файлу конфигурации логирования
     *
     * @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|int>
     */
    public static function loadConfig(): array
    {
        $configPath = self::getConfigPath();

        if (!file_exists($configPath)) {
            return self::getDefaultConfig();
        }

        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('LoggingConfigManager: Failed to load logging config', [
                    'error' => $e->getMessage(),
                    'file' => $configPath,
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
        }

        return self::getDefaultConfig();
    }

    /**
     * Получить конфигурацию по умолчанию
     *
     * @return array<string, string|int>
     */
    private static function getDefaultConfig(): array
    {
        return [
            'enabled' => '1',
            'levels' => 'DEBUG,INFO,WARNING,ERROR,CRITICAL',
            'types' => 'file,db_queries,db_errors,slow_queries',
            'max_file_size' => '10485760',
            'retention_days' => '30',
            'rotation_type' => 'size',
            'rotation_time' => '24',
            'rotation_time_unit' => 'hours',
        ];
    }

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

        try {
            // Проверяем права на запись
            $configDir = dirname($configPath);
            if (!is_writable($configDir) && !is_writable($configPath)) {
                try {
                    Log::Error('LoggingConfigManager: 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;
            }

            // Нормализуем значения
            $normalizedConfig = [];
            foreach ($config as $key => $value) {
                // Сохраняем пустые строки как есть (для отключенных чекбоксов)
                if ($value === '' || $value === null) {
                    $normalizedConfig[$key] = '';
                } else {
                    $normalizedConfig[$key] = (string)$value;
                }
            }

            // Объединяем с настройками по умолчанию, но только для ключей, которые не были переданы
            $defaultConfig = self::getDefaultConfig();
            $finalConfig = [];
            foreach ($defaultConfig as $key => $defaultValue) {
                // Если значение передано (даже пустое), используем его, иначе значение по умолчанию
                if (array_key_exists($key, $normalizedConfig)) {
                    $finalConfig[$key] = $normalizedConfig[$key];
                } else {
                    $finalConfig[$key] = $defaultValue;
                }
            }

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

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

            // Fallback: записываем напрямую
            $content = "; Конфигурация автоматически создана Flowaxy Framework\n";
            $content .= "; Не редактируйте вручную, если не уверены\n\n";
            $content .= "[" . self::CONFIG_SECTION . "]\n";
            foreach ($finalConfig as $key => $value) {
                $content .= "{$key} = {$value}\n";
            }
            $result = @file_put_contents($configPath, $content) !== false;
            if ($result) {
                @chmod($configPath, 0644);
            } else {
                try {
                    Log::Error('LoggingConfigManager: 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('LoggingConfigManager: Failed to save logging config', [
                    'error' => $e->getMessage(),
                    'file' => $configPath,
                    'exception' => $e,
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
            return false;
        }
    }

    /**
     * Получить значение настройки
     *
     * @param string $key
     * @param string|int $default
     * @return string|int
     */
    public static function get(string $key, $default = '')
    {
        $config = self::loadConfig();
        return $config[$key] ?? $default;
    }

    /**
     * Установить значение настройки
     *
     * @param string $key
     * @param string|int $value
     * @return bool
     */
    public static function set(string $key, $value): bool
    {
        $config = self::loadConfig();
        $config[$key] = $value;
        return self::saveConfig($config);
    }
}
