<?php

declare(strict_types=1);

namespace Flowaxy\Domain\User\Services;

use Flowaxy\Core\System\PathResolver;
use Flowaxy\Infrastructure\Config\Config;
use Flowaxy\Support\Facades\Hash;
use Flowaxy\Support\Facades\Log;
use Throwable;

use function defined;
use function file_exists;
use function is_readable;
use const DIRECTORY_SEPARATOR;
use const DS;

/**
 * Сервис для работы с конфигурацией root пользователя
 * Root пользователь не хранится в БД, а в файле storage/config/system/root.ini
 */
final class RootUserConfig
{
    private const ROOT_USERNAME = 'root';
    private const CONFIG_NAME = 'root';
    private const DEFAULT_PASSWORD = 'root';

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

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

        if (!file_exists($configPath) || !is_readable($configPath)) {
            error_log("RootUserConfig::loadConfig: Config file does not exist or is not readable. Path: {$configPath}, Exists: " . (file_exists($configPath) ? 'yes' : 'no') . ", Readable: " . (is_readable($configPath) ? 'yes' : 'no'));
            try {
                Log::Warning('RootUserConfig: Config file does not exist or is not readable', [
                    'file' => $configPath,
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
            return null;
        }

        try {
            // Используем parse_ini_file напрямую, так как Config может не правильно обрабатывать секции
            $iniData = parse_ini_file($configPath, true);
            error_log("RootUserConfig::loadConfig: Parsed INI file. Data is array: " . (is_array($iniData) ? 'yes' : 'no') . ", Has 'root' key: " . (is_array($iniData) && isset($iniData['root']) ? 'yes' : 'no'));

            if ($iniData !== false && isset($iniData['root']) && is_array($iniData['root'])) {
                // Убираем кавычки из значений, если они есть
                $config = [];
                foreach ($iniData['root'] as $key => $value) {
                    if (is_string($value)) {
                        // Убираем кавычки в начале и конце, если они есть
                        $config[$key] = trim($value, '"\'');
                    } else {
                        $config[$key] = $value;
                    }
                }

                error_log("RootUserConfig::loadConfig: Config loaded. Keys: " . implode(',', array_keys($config)) . ", Has password_hash: " . (isset($config['password_hash']) ? 'yes' : 'no') . ", Password_hash length: " . (isset($config['password_hash']) ? strlen($config['password_hash']) : '0'));

                try {
                    Log::Debug('RootUserConfig: Config loaded successfully', [
                        'file' => $configPath,
                        'has_password_hash' => isset($config['password_hash']) && !empty($config['password_hash']),
                    ]);
                } catch (Throwable $logError) {
                    // Ignore logging errors
                }

                return $config;
            } else {
                error_log("RootUserConfig::loadConfig: Failed to parse or missing [root] section. INI data: " . (is_array($iniData) ? 'array with keys: ' . implode(',', array_keys($iniData)) : 'not array'));
            }

            // Fallback: пробуем через Config
            if (class_exists(Config::class)) {
                $config = Config::getInstance();
                $rootConfig = $config->get('root', []);
                if (!empty($rootConfig) && is_array($rootConfig)) {
                    // Если Config вернул данные напрямую (без секции)
                    if (isset($rootConfig['username']) || isset($rootConfig['password_hash'])) {
                        return $rootConfig;
                    }
                    // Если Config вернул данные в секции
                    if (isset($rootConfig['root']) && is_array($rootConfig['root'])) {
                        return $rootConfig['root'];
                    }
                }
            }
        } catch (Throwable $e) {
            try {
                Log::Error('RootUserConfig: Failed to load root user config', [
                    'error' => $e->getMessage(),
                    'file' => $configPath,
                    'trace' => $e->getTraceAsString(),
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
        }

        return null;
    }

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

        try {
            if (class_exists(\Flowaxy\Support\Helpers\IniHelper::class)) {
                $data = ['root' => $config];
                return \Flowaxy\Support\Helpers\IniHelper::writeFile($configPath, $data);
            }

            // Fallback: записываем напрямую
            $content = "[root]\n";
            foreach ($config as $key => $value) {
                $content .= "{$key} = {$value}\n";
            }
            $result = @file_put_contents($configPath, $content) !== false;
            if ($result) {
                @chmod($configPath, 0600); // Только владелец может читать/писать
            }
            return $result;
        } catch (Throwable $e) {
            try {
                Log::Error('RootUserConfig: Failed to save root user config', [
                    'error' => $e->getMessage(),
                    'file' => $configPath,
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
            return false;
        }
    }

    /**
     * Проверить, существует ли root пользователь
     *
     * @return bool
     */
    public static function exists(): bool
    {
        $config = self::loadConfig();
        return $config !== null && isset($config['username']) && $config['username'] === self::ROOT_USERNAME;
    }

    /**
     * Получить хеш пароля root пользователя
     *
     * @return string|null
     */
    public static function getPasswordHash(): ?string
    {
        $config = self::loadConfig();
        if ($config === null) {
            error_log("RootUserConfig::getPasswordHash: Config is null");
            return null;
        }

        $passwordHash = $config['password_hash'] ?? '';

        // Если пароль не установлен, создаем дефолтный при первом обращении
        if (empty($passwordHash)) {
            try {
                // Используем password_hash напрямую, если Hash facade недоступен
                if (function_exists('password_hash')) {
                    $defaultHash = password_hash(self::DEFAULT_PASSWORD, PASSWORD_DEFAULT);
                } else {
                    // Fallback: пробуем через Hash facade
                    $defaultHash = Hash::make(self::DEFAULT_PASSWORD);
                }

                if (!empty($defaultHash) && self::setPasswordHash($defaultHash)) {
                    try {
                        Log::Info('RootUserConfig: Default password hash created for root user', [
                            'username' => self::ROOT_USERNAME,
                            'note' => 'Default password is "root" - should be changed on first login'
                        ]);
                    } catch (Throwable $logError) {
                        // Ignore logging errors
                    }
                    error_log("RootUserConfig::getPasswordHash: Default password hash created: " . substr($defaultHash, 0, 20) . "...");
                    return $defaultHash;
                } else {
                    error_log("RootUserConfig::getPasswordHash: Failed to create or save default password hash");
                }
            } catch (Throwable $e) {
                try {
                    Log::Error('RootUserConfig: Failed to create default password hash', [
                        'error' => $e->getMessage(),
                    ]);
                } catch (Throwable $logError) {
                    // Ignore logging errors
                }
                error_log("RootUserConfig::getPasswordHash: Exception: " . $e->getMessage());
                return null;
            }
        }

        error_log("RootUserConfig::getPasswordHash: Hash found, length: " . strlen($passwordHash) . ", prefix: " . substr($passwordHash, 0, 7));
        return $passwordHash;
    }

    /**
     * Установить хеш пароля root пользователя
     *
     * @param string $passwordHash
     * @return bool
     */
    public static function setPasswordHash(string $passwordHash): bool
    {
        $config = self::loadConfig() ?? [
            'username' => self::ROOT_USERNAME,
            'email' => 'root@localhost',
            'created_at' => date('Y-m-d H:i:s'),
            'is_active' => '1',
        ];

        $config['password_hash'] = $passwordHash;
        return self::saveConfig($config);
    }

    /**
     * Проверить пароль root пользователя
     *
     * @param string $password
     * @return bool
     */
    public static function verifyPassword(string $password): bool
    {
        $passwordHash = self::getPasswordHash();
        if ($passwordHash === null || $passwordHash === '') {
            error_log("RootUserConfig::verifyPassword: Password hash is null or empty");
            try {
                Log::Warning('RootUserConfig: Password hash is null or empty');
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
            return false;
        }

        try {
            // Используем password_verify напрямую, если Hash facade недоступен
            if (function_exists('password_verify')) {
                $result = password_verify($password, $passwordHash);
            } else {
                // Fallback: пробуем через Hash facade
                $result = Hash::check($password, $passwordHash);
            }

            error_log("RootUserConfig::verifyPassword: Result: " . ($result ? 'SUCCESS' : 'FAILED') . ", Password: '" . $password . "', Hash length: " . strlen($passwordHash));

            try {
                Log::Debug('RootUserConfig: Password verification', [
                    'result' => $result,
                    'hash_length' => strlen($passwordHash),
                    'hash_prefix' => substr($passwordHash, 0, 7),
                    'password_length' => strlen($password),
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }

            return $result;
        } catch (Throwable $e) {
            error_log("RootUserConfig::verifyPassword: Exception: " . $e->getMessage() . " | File: " . $e->getFile() . " | Line: " . $e->getLine());
            try {
                Log::Error('RootUserConfig: Password verification error', [
                    'error' => $e->getMessage(),
                    'trace' => $e->getTraceAsString(),
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
            return false;
        }
    }

    /**
     * Получить username root пользователя
     *
     * @return string
     */
    public static function getUsername(): string
    {
        return self::ROOT_USERNAME;
    }

    /**
     * Проверить, является ли username root пользователем
     *
     * @param string $username
     * @return bool
     */
    public static function isRootUsername(string $username): bool
    {
        $result = $username === self::ROOT_USERNAME;
        error_log("RootUserConfig::isRootUsername: Username: '{$username}', ROOT_USERNAME: '" . self::ROOT_USERNAME . "', Result: " . ($result ? 'yes' : 'no'));
        return $result;
    }
}
