src/App/Bootstrap.ps1

# Bootstrap — Carga constantes globales del v3 (ADR-003).
#
# **No dot-source-ea clases.** Las clases en PowerShell sólo viven en el scope del
# archivo que las dot-source-ea **directamente** — si las cargás vía Import-RNFile,
# el resto de los archivos no las "ven" como tipos. Por eso las clases se cargan
# directamente desde el entry repo-nav.ps1 en orden bottom-up.
#
# Este Bootstrap sólo carga:
# - Constantes (`$global:RNTokens`, `$global:RNThemes`, etc.)
# - Funciones que NO usan clases en su cuerpo

$script:RNRoot = Split-Path $PSScriptRoot -Parent

# Helper que VALIDA + DEVUELVE el path. NO dot-sourcea — el dot-source pasa
# afuera, en el scope del caller (este mismo archivo). Esto es CRÍTICO para
# las funciones definidas en I18nCatalog.ps1: si las dot-sourceáramos adentro
# de una función helper, quedarían en el scope local de esa función y
# I18nService.T no las podría llamar (TypeError 'Get-RepoNavI18nCatalog not
# recognized'). Al hacer el dot-source en este nivel, las funciones quedan
# en el scope de Bootstrap.ps1 → que es el scope del caller (repo-nav.ps1
# o repo-nav.psm1) → visible para todo lo cargado después.
function Resolve-RNConfig {
    param([Parameter(Mandatory)] [string] $RelativePath)
    $full = Join-Path $script:RNRoot $RelativePath
    if (-not (Test-Path $full)) { throw "Bootstrap: archivo no existe: $full" }
    return $full
}

# Config (sólo constantes y funciones standalone, sin classes).
# Dot-source DIRECTO (no via función helper) para que las funciones definidas
# acá queden visibles desde I18nService.T y similares.
. (Resolve-RNConfig 'Config/Tokens.ps1')
. (Resolve-RNConfig 'Config/Themes.ps1')
. (Resolve-RNConfig 'Config/I18nCatalog.ps1')

# Orden explícito de carga de archivos con `class`. El entry repo-nav.ps1
# itera sobre este array y los dot-sourcea uno a uno **desde el scope del entry**,
# así los tipos quedan visibles para cualquier otro archivo cargado después.
# Bottom-up: Models → Services → UI → App.
$global:RNLoadOrder = @(
    # Models (data classes, sin dependencias entre sí salvo Commit ← Repo)
    'Models/Commit.ps1'
    'Models/Repo.ps1'
    'Models/Branch.ps1'
    'Models/FileChange.ps1'
    'Models/Settings.ps1'
    'Models/IntegrationFlow.ps1'

    # Util — funciones standalone reusables (no clases). Cargado antes de
    # Services porque RepoDiscoveryService.DiscoverParallel necesita
    # Get-RepoStateData visible al parsearse el archivo.
    'Util/GitParse.ps1'

    # Services
    'Services/AnsiService.ps1'
    'Services/ThemeService.ps1'
    'Services/I18nService.ps1'
    'Services/GitService.ps1'
    'Services/RepoDiscoveryService.ps1'
    'Services/SettingsService.ps1'
    'Services/SetupService.ps1'

    # UI
    'UI/Renderer.ps1'
    'UI/Primitives.ps1'
    'UI/Frame.ps1'
    'UI/AppHeader.ps1'
    'UI/StatusBar.ps1'
    'UI/Viewport.ps1'
    'UI/BreadcrumbBuilder.ps1'
    'UI/NavStack.ps1'
    'UI/Components/FilteredListPicker.ps1'
    # IntegrateScreen va ANTES que BranchManagerScreen porque éste lo instancia
    # cuando el user selecciona el chip Integrate.
    'UI/Screens/IntegrateScreen.ps1'
    'UI/Screens/QuickChangeScreen.ps1'
    'UI/Screens/ReleaseScreen.ps1'
    'UI/Screens/GraphScreen.ps1'
    'UI/Screens/CherryPickScreen.ps1'
    'UI/Screens/CompareScreen.ps1'
    # BranchManagerScreen va ANTES que MainScreen porque MainScreen lo instancia
    # via `[BranchManagerScreen]::new(...)` y PS classes resuelven tipos at parse time.
    'UI/Screens/BranchManagerScreen.ps1'
    'UI/Screens/SetupScreen.ps1'
    # PreferencesScreen instancia SetupScreen (chip 'Setup & Status').
    'UI/Screens/PreferencesScreen.ps1'
    # ConfigScreen es la nueva pantalla de configuración global (alias + deps
    # + AutoLoadMode). Independiente del PreferencesScreen viejo, accesible
    # via `rnav config` desde la CLI.
    'UI/Screens/ConfigScreen.ps1'
    'UI/Screens/BrowseScreen.ps1'
    'UI/Screens/MainScreen.ps1'

    # App (funciones top-level)
    'App/Startup.ps1'
)