<?php

namespace WPD\Application;

final class Config
{
    private $values;
    private $error;

    private function __construct(array $values, $error = null)
    {
        $this->values = $values;
        $this->error = $error;
    }

    public static function load($root)
    {
        $file = rtrim($root, '/\\') . '/config.php';
        if (!is_file($file)) {
            return new self(array(), 'Falta config.php. Copia config.example.php, define un token nuevo y vuelve a cargar esta página.');
        }

        $values = require $file;
        if (!is_array($values)) {
            return new self(array(), 'config.php debe devolver un array de configuración.');
        }

        $token = isset($values['access_token']) ? trim((string) $values['access_token']) : '';
        if (strlen($token) < 32 || strpos($token, 'CAMBIA-ESTE-TOKEN') === 0) {
            return new self($values, 'La herramienta está bloqueada. Define en config.php un token aleatorio de al menos 32 caracteres.');
        }

        $defaultAllowed = dirname(realpath($root) ?: $root);
        $allowed = empty($values['allowed_root']) ? $defaultAllowed : realpath((string) $values['allowed_root']);
        if ($allowed === false || !is_dir($allowed)) {
            return new self($values, 'La ruta allowed_root de config.php no existe o no es accesible.');
        }

        $values['access_token'] = $token;
        $values['allowed_root'] = rtrim($allowed, '/\\');
        $values['session_timeout'] = max(300, min(1800, isset($values['session_timeout']) ? (int) $values['session_timeout'] : 1800));
        $values['allow_insecure_http'] = !empty($values['allow_insecure_http']);

        foreach (array('allowed_ips', 'trusted_proxy_ips') as $listKey) {
            $list = isset($values[$listKey]) && is_array($values[$listKey]) ? $values[$listKey] : array();
            $normalized = array();
            foreach ($list as $address) {
                $address = trim((string) $address);
                if (filter_var($address, FILTER_VALIDATE_IP) === false) {
                    return new self($values, $listKey . ' contiene una dirección IP no válida.');
                }
                $normalized[] = $address;
            }
            $values[$listKey] = array_values(array_unique($normalized));
        }

        if ($values['allow_insecure_http'] && !$values['allowed_ips']) {
            return new self($values, 'El modo HTTP de emergencia exige al menos una IP exacta en allowed_ips.');
        }

        return new self($values);
    }

    public function isValid()
    {
        return $this->error === null;
    }

    public function error()
    {
        return $this->error;
    }

    public function get($key, $default = null)
    {
        return array_key_exists($key, $this->values) ? $this->values[$key] : $default;
    }
}
