<?php

// Private runtime configuration.
// Las credenciales deben vivir fuera del document root. El servidor ICYLAB usa
// /home/icyla826/private_config.php; ICYLAB_PRIVATE_CONFIG_PATH permite moverlas
// sin cambiar el código. El fallback local queda deshabilitado salvo opt-in
// explícito para desarrollo.
$privateConfigCandidates = array();
$explicitPrivateConfigPath = getenv('ICYLAB_PRIVATE_CONFIG_PATH');
$allowLocalPrivateConfig = filter_var(
    getenv('ICYLAB_ALLOW_LOCAL_PRIVATE_CONFIG') ?: 'false',
    FILTER_VALIDATE_BOOLEAN
);

if (is_string($explicitPrivateConfigPath) && trim($explicitPrivateConfigPath) !== '') {
    $privateConfigCandidates[] = trim($explicitPrivateConfigPath);
} else {
    $privateConfigCandidates[] = '/home/icyla826/private_config.php';
    $privateConfigCandidates[] = dirname(dirname(__DIR__)) . '/private_config.php';
    if ($allowLocalPrivateConfig) {
        $privateConfigCandidates[] = __DIR__ . '/private_config.php';
    }
}

$privateConfigPath = null;
foreach (array_unique($privateConfigCandidates) as $candidate) {
    if (is_file($candidate) && is_readable($candidate)) {
        $privateConfigPath = realpath($candidate) ?: $candidate;
        break;
    }
}

if ($privateConfigPath === null) {
    throw new RuntimeException(
        'Configuración privada no disponible. Instala private_config.php fuera de la raíz pública.'
    );
}

$applicationRoot = realpath(dirname(__DIR__));
$resolvedPrivateConfig = realpath($privateConfigPath);
if (
    !$allowLocalPrivateConfig
    && $applicationRoot !== false
    && $resolvedPrivateConfig !== false
    && (
        $resolvedPrivateConfig === $applicationRoot
        || strpos($resolvedPrivateConfig, $applicationRoot . DIRECTORY_SEPARATOR) === 0
    )
) {
    throw new RuntimeException('La configuración privada no puede residir dentro de la raíz pública.');
}

require_once $privateConfigPath;
if (!defined('ICYLAB_PRIVATE_CONFIG_PATH_USED')) {
    define('ICYLAB_PRIVATE_CONFIG_PATH_USED', $privateConfigPath);
}

// Google Maps backend key.
// Usada por endpoints PHP: api/geo/maps_suggest.php, maps_place.php y backfill.
if (!defined('GOOGLE_MAPS_API_KEY')) {
    define(
        'GOOGLE_MAPS_API_KEY',
        defined('ICYLAB_GOOGLE_MAPS_SERVER_KEY') ? trim((string) ICYLAB_GOOGLE_MAPS_SERVER_KEY) : ''
    );
}

// Google Maps frontend key.
// Sólo usar si se implementa mapa visual en navegador.
if (!defined('GOOGLE_MAPS_BROWSER_KEY')) {
    define(
        'GOOGLE_MAPS_BROWSER_KEY',
        defined('ICYLAB_GOOGLE_MAPS_BROWSER_KEY') ? trim((string) ICYLAB_GOOGLE_MAPS_BROWSER_KEY) : ''
    );
}

// Google Maps Map ID.
// Sólo usar si se implementa gmp-map / Advanced Markers.
if (!defined('GOOGLE_MAPS_MAP_ID')) {
    define(
        'GOOGLE_MAPS_MAP_ID',
        defined('ICYLAB_GOOGLE_MAPS_MAP_ID') ? trim((string) ICYLAB_GOOGLE_MAPS_MAP_ID) : ''
    );
}

define('APP_NAME', 'ICYLAB OS');
if (!defined('APP_URL')) {
    define('APP_URL', defined('ICYLAB_APP_URL') ? ICYLAB_APP_URL : 'https://app.icylab.cl');
}
if (!defined('APP_ENV')) {
    define('APP_ENV', defined('ICYLAB_APP_ENV') ? ICYLAB_APP_ENV : 'production');
}

// Polyfills mínimos para servidores PHP sin extensión mbstring.
// Evita errores fatales en navegación, usuarios, clientes, productos y embudo.
if (!function_exists('mb_strlen')) {
    function mb_strlen($string, $encoding = null) {
        return strlen((string)$string);
    }
}
if (!function_exists('mb_substr')) {
    function mb_substr($string, $start, $length = null, $encoding = null) {
        $string = (string)$string;
        return $length === null ? substr($string, $start) : substr($string, $start, $length);
    }
}
if (!function_exists('mb_strtolower')) {
    function mb_strtolower($string, $encoding = null) {
        return strtolower((string)$string);
    }
}



// Runtime secrets.
// Las credenciales reales deben vivir en core/private_config.php o variables de entorno.
if (!defined('DB_HOST')) {
    define('DB_HOST', defined('ICYLAB_DB_HOST') ? ICYLAB_DB_HOST : (getenv('ICYLAB_DB_HOST') ?: 'localhost'));
}
if (!defined('DB_NAME')) {
    define('DB_NAME', defined('ICYLAB_DB_NAME') ? ICYLAB_DB_NAME : (getenv('ICYLAB_DB_NAME') ?: ''));
}
if (!defined('DB_USER')) {
    define('DB_USER', defined('ICYLAB_DB_USER') ? ICYLAB_DB_USER : (getenv('ICYLAB_DB_USER') ?: ''));
}
if (!defined('DB_PASS')) {
    define('DB_PASS', defined('ICYLAB_DB_PASS') ? ICYLAB_DB_PASS : (getenv('ICYLAB_DB_PASS') ?: ''));
}

if (!defined('GOOGLE_CLIENT_ID')) {
    define('GOOGLE_CLIENT_ID', defined('ICYLAB_GOOGLE_CLIENT_ID') ? ICYLAB_GOOGLE_CLIENT_ID : (getenv('ICYLAB_GOOGLE_CLIENT_ID') ?: ''));
}
if (!defined('GOOGLE_CLIENT_SECRET')) {
    define('GOOGLE_CLIENT_SECRET', defined('ICYLAB_GOOGLE_CLIENT_SECRET') ? ICYLAB_GOOGLE_CLIENT_SECRET : (getenv('ICYLAB_GOOGLE_CLIENT_SECRET') ?: ''));
}
if (!defined('GOOGLE_ALLOWED_DOMAIN')) {
    define('GOOGLE_ALLOWED_DOMAIN', defined('ICYLAB_GOOGLE_ALLOWED_DOMAIN') ? ICYLAB_GOOGLE_ALLOWED_DOMAIN : (getenv('ICYLAB_GOOGLE_ALLOWED_DOMAIN') ?: 'icylab.cl'));
}

if (!defined('CLICKUP_API_TOKEN')) {
    define('CLICKUP_API_TOKEN', defined('ICYLAB_CLICKUP_API_TOKEN') ? ICYLAB_CLICKUP_API_TOKEN : (getenv('ICYLAB_CLICKUP_API_TOKEN') ?: ''));
}

// -----------------------------------------------------------------------------
// FACTO / Koywe multiambiente
// -----------------------------------------------------------------------------
// Compatibilidad:
// - Si solo existen las constantes antiguas ICYLAB_FACTO_*, se usan como ambiente production.
// - Para operar sandbox/production en paralelo, define las constantes por ambiente en private_config.php.
// - No hardcodear credenciales en repositorio ni en frontend.

if (!function_exists('icylab_env_value')) {
    function icylab_env_value($constantName, $envName, $default = '') {
        if (defined($constantName)) {
            return constant($constantName);
        }

        $value = getenv($envName);
        return $value !== false && $value !== '' ? $value : $default;
    }
}

if (!function_exists('icylab_facto_normalize_environment')) {
    function icylab_facto_normalize_environment($environment = null) {
        $env = strtolower(trim((string) ($environment ?: icylab_env_value('ICYLAB_FACTO_ENVIRONMENT', 'ICYLAB_FACTO_ENVIRONMENT', 'production'))));
        return in_array($env, array('sandbox', 'production'), true) ? $env : 'production';
    }
}

if (!function_exists('icylab_facto_config')) {
    function icylab_facto_config($environment = null) {
        $environment = icylab_facto_normalize_environment($environment);
        $prefix = $environment === 'sandbox' ? 'ICYLAB_FACTO_SANDBOX_' : 'ICYLAB_FACTO_PRODUCTION_';
        $legacyAllowed = $environment === 'production';

        $baseUrl = icylab_env_value($prefix . 'API_BASE_URL', $prefix . 'API_BASE_URL', '');
        $clientId = icylab_env_value($prefix . 'CLIENT_ID', $prefix . 'CLIENT_ID', '');
        $clientSecret = icylab_env_value($prefix . 'CLIENT_SECRET', $prefix . 'CLIENT_SECRET', '');
        $username = icylab_env_value($prefix . 'USERNAME', $prefix . 'USERNAME', '');
        $password = icylab_env_value($prefix . 'PASSWORD', $prefix . 'PASSWORD', '');
        $accountId = icylab_env_value($prefix . 'ACCOUNT_ID', $prefix . 'ACCOUNT_ID', '');

        if ($legacyAllowed) {
            $baseUrl = $baseUrl ?: icylab_env_value('ICYLAB_FACTO_API_BASE_URL', 'ICYLAB_FACTO_API_BASE_URL', 'https://api-billing.koywe.com/V1');
            $clientId = $clientId ?: icylab_env_value('ICYLAB_FACTO_CLIENT_ID', 'ICYLAB_FACTO_CLIENT_ID', '');
            $clientSecret = $clientSecret ?: icylab_env_value('ICYLAB_FACTO_CLIENT_SECRET', 'ICYLAB_FACTO_CLIENT_SECRET', '');
            $username = $username ?: icylab_env_value('ICYLAB_FACTO_USERNAME', 'ICYLAB_FACTO_USERNAME', '');
            $password = $password ?: icylab_env_value('ICYLAB_FACTO_PASSWORD', 'ICYLAB_FACTO_PASSWORD', '');
            $accountId = $accountId ?: icylab_env_value('ICYLAB_FACTO_ACCOUNT_ID', 'ICYLAB_FACTO_ACCOUNT_ID', '');
        }

        if (!$baseUrl) {
            $baseUrl = 'https://api-billing.koywe.com/V1';
        }

        return array(
            'environment' => $environment,
            'base_url' => rtrim((string) $baseUrl, '/'),
            'client_id' => (string) $clientId,
            'client_secret' => (string) $clientSecret,
            'username' => (string) $username,
            'password' => (string) $password,
            'account_id' => (string) $accountId,
            'timeout' => (int) icylab_env_value('ICYLAB_FACTO_TIMEOUT', 'ICYLAB_FACTO_TIMEOUT', 45),
            'connect_timeout' => (int) icylab_env_value('ICYLAB_FACTO_CONNECT_TIMEOUT', 'ICYLAB_FACTO_CONNECT_TIMEOUT', 12)
        );
    }
}

if (!defined('FACTO_DEFAULT_ENVIRONMENT')) {
    define('FACTO_DEFAULT_ENVIRONMENT', icylab_facto_normalize_environment());
}

// Constantes legacy para compatibilidad con servicios antiguos.
$__factoLegacyConfig = icylab_facto_config(FACTO_DEFAULT_ENVIRONMENT);
if (!defined('FACTO_API_BASE_URL')) {
    define('FACTO_API_BASE_URL', $__factoLegacyConfig['base_url']);
}
if (!defined('FACTO_CLIENT_ID')) {
    define('FACTO_CLIENT_ID', $__factoLegacyConfig['client_id']);
}
if (!defined('FACTO_CLIENT_SECRET')) {
    define('FACTO_CLIENT_SECRET', $__factoLegacyConfig['client_secret']);
}
if (!defined('FACTO_USERNAME')) {
    define('FACTO_USERNAME', $__factoLegacyConfig['username']);
}
if (!defined('FACTO_PASSWORD')) {
    define('FACTO_PASSWORD', $__factoLegacyConfig['password']);
}
if (!defined('FACTO_ACCOUNT_ID')) {
    define('FACTO_ACCOUNT_ID', $__factoLegacyConfig['account_id']);
}
unset($__factoLegacyConfig);

// -----------------------------------------------------------------------------
// Billing production runtime gates
// -----------------------------------------------------------------------------
// Fail-closed: si una constante no existe, la operación productiva queda bloqueada.
if (!defined('ICYLAB_BILLING_PRODUCTION_READ_ENABLED')) {
    define('ICYLAB_BILLING_PRODUCTION_READ_ENABLED', false);
}
if (!defined('ICYLAB_BILLING_PRODUCTION_FINANCE_ENABLED')) {
    define('ICYLAB_BILLING_PRODUCTION_FINANCE_ENABLED', false);
}
if (!defined('ICYLAB_BILLING_PRODUCTION_ISSUE_ENABLED')) {
    define('ICYLAB_BILLING_PRODUCTION_ISSUE_ENABLED', false);
}

require_once __DIR__ . '/../services/billing/BillingRuntimeGate.php';


// SMTP / Notificaciones.
// Configurar preferentemente en core/private_config.php o variables de entorno.
if (!defined('SMTP_HOST')) {
    define('SMTP_HOST', defined('ICYLAB_SMTP_HOST') ? ICYLAB_SMTP_HOST : (getenv('ICYLAB_SMTP_HOST') ?: ''));
}
if (!defined('SMTP_PORT')) {
    define('SMTP_PORT', defined('ICYLAB_SMTP_PORT') ? (int) ICYLAB_SMTP_PORT : (int) (getenv('ICYLAB_SMTP_PORT') ?: 587));
}
if (!defined('SMTP_SECURE')) {
    define('SMTP_SECURE', defined('ICYLAB_SMTP_SECURE') ? ICYLAB_SMTP_SECURE : (getenv('ICYLAB_SMTP_SECURE') ?: 'tls'));
}
if (!defined('SMTP_USERNAME')) {
    define('SMTP_USERNAME', defined('ICYLAB_SMTP_USERNAME') ? ICYLAB_SMTP_USERNAME : (getenv('ICYLAB_SMTP_USERNAME') ?: ''));
}
if (!defined('SMTP_PASSWORD')) {
    define('SMTP_PASSWORD', defined('ICYLAB_SMTP_PASSWORD') ? ICYLAB_SMTP_PASSWORD : (getenv('ICYLAB_SMTP_PASSWORD') ?: ''));
}
if (!defined('SMTP_EHLO_DOMAIN')) {
    define('SMTP_EHLO_DOMAIN', defined('ICYLAB_SMTP_EHLO_DOMAIN') ? ICYLAB_SMTP_EHLO_DOMAIN : (getenv('ICYLAB_SMTP_EHLO_DOMAIN') ?: 'app.icylab.cl'));
}
if (!defined('NOTIFICATIONS_EMAIL_FROM')) {
    define('NOTIFICATIONS_EMAIL_FROM', defined('ICYLAB_NOTIFICATIONS_EMAIL_FROM') ? ICYLAB_NOTIFICATIONS_EMAIL_FROM : (getenv('ICYLAB_NOTIFICATIONS_EMAIL_FROM') ?: 'no-reply@app.icylab.cl'));
}
if (!defined('NOTIFICATIONS_EMAIL_FROM_NAME')) {
    define('NOTIFICATIONS_EMAIL_FROM_NAME', defined('ICYLAB_NOTIFICATIONS_EMAIL_FROM_NAME') ? ICYLAB_NOTIFICATIONS_EMAIL_FROM_NAME : (getenv('ICYLAB_NOTIFICATIONS_EMAIL_FROM_NAME') ?: 'ICYLAB OS'));
}

function get_system_modules($only_active = false) {
    $pdo = db();
    
    // 1. Leer la configuración guardada por el Admin
    $stmt = $pdo->query("SELECT modules_config FROM system_settings WHERE id = 1");
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    $saved_config = [];
    if ($row && !empty($row['modules_config'])) {
        $saved_config = json_decode($row['modules_config'], true) ?: [];
    }

    // Normalizar claves legacy (por ejemplo "CRM") para que el registro sea
    // estable en servidores Linux, donde las rutas distinguen mayusculas.
    $normalized_saved_config = [];
    foreach ($saved_config as $saved_key => $saved_module) {
        if (is_array($saved_module)) {
            $normalized_saved_config[strtolower(trim((string)$saved_key))] = $saved_module;
        }
    }
    $saved_config = $normalized_saved_config;

    $modules_dir = __DIR__ . '/../modules/';
    $modules = [];
    
    // 2. Metadatos por defecto (Si el Admin nunca los ha modificado)
    $known_metadata = [
        'calendar'    => ['title' => 'Calendario', 'icon' => 'calendar-days', 'section' => 'Empresa', 'order' => 5],
        'operations'  => ['title' => 'Producción', 'icon' => 'flask-conical', 'section' => 'Operación', 'order' => 10],
        'quality'     => ['title' => 'Calidad', 'icon' => 'shield-check', 'section' => 'Operación', 'order' => 20],
        'stock'       => ['title' => 'Stock', 'icon' => 'boxes', 'section' => 'Operación', 'order' => 30],
        'dispatch'    => ['title' => 'Despacho', 'icon' => 'truck', 'section' => 'Operación', 'order' => 40],
        'commercial'  => ['title' => 'Dashboard Com.', 'icon' => 'line-chart', 'section' => 'Comercial', 'order' => 50],
        'crm'         => ['title' => 'CRM', 'icon' => 'briefcase-business', 'section' => 'Comercial', 'order' => 60],
        'customers'   => ['title' => 'Clientes', 'icon' => 'users', 'section' => 'Comercial', 'order' => 70],
        'products'    => ['title' => 'Productos', 'icon' => 'package', 'section' => 'Comercial', 'order' => 80],
        'billing'     => ['title' => 'Facturacion', 'icon' => 'file-text', 'section' => 'Finanzas', 'order' => 90],
        'costs'       => ['title' => 'Costos', 'icon' => 'calculator', 'section' => 'Finanzas', 'order' => 95],
        'treasury'    => ['title' => 'Tesorería', 'icon' => 'landmark', 'section' => 'Finanzas', 'order' => 97],
        'notifications' => ['title' => 'Notificaciones', 'icon' => 'bell', 'section' => 'Empresa', 'order' => 100]
    ];

    if (is_dir($modules_dir)) {
        // Ignoramos archivos del sistema y módulos maestros (dashboard/admin)
        $dirs = array_diff(scandir($modules_dir), ['..', '.', '.DS_Store', 'dashboard', 'admin']);
        
        foreach ($dirs as $dir) {
            $module_path = $modules_dir . '/' . $dir;
            $module_key = strtolower(trim((string)$dir));

            // Un directorio sin entrypoint no es un modulo navegable.
            if (is_dir($module_path) && is_file($module_path . '/index.php')) {
                
                $mod_data = $known_metadata[$module_key] ?? [
                    'title' => ucfirst(str_replace('_', ' ', $dir)),
                    'icon' => 'folder',
                    'section' => 'Otros Módulos',
                    'order' => 99 // Al final de la lista
                ];
                
                // 3. Sobrescribir con la BD si el Admin hizo cambios
                if (isset($saved_config[$module_key])) {
                    $saved_module = $saved_config[$module_key];
                    $mod_data['title'] = (string)($saved_module['title'] ?? $mod_data['title']);
                    $mod_data['icon'] = (string)($saved_module['icon'] ?? $mod_data['icon']);
                    $mod_data['section'] = (string)($saved_module['section'] ?? $mod_data['section']);
                    $mod_data['order'] = (int)($saved_module['order'] ?? $mod_data['order']);
                    $mod_data['is_active'] = !empty($saved_module['is_active']) ? 1 : 0;
                } else {
                    // Solo modulos conocidos se habilitan por defecto. Un
                    // directorio nuevo debe ser activado explicitamente.
                    $mod_data['is_active'] = isset($known_metadata[$module_key]) ? 1 : 0;
                }
                
                // 4. Filtrar si se solicitó ocultar los inactivos
                if ($only_active && $mod_data['is_active'] === 0) {
                    continue;
                }
                
                $modules[$module_key] = $mod_data;
            }
        }
    }
    
    // 5. Ordenar por el campo 'order' ascendente
    uasort($modules, function($a, $b) {
        return $a['order'] <=> $b['order'];
    });
    
    return $modules;
}
