src/Models/Repo.ps1

# Repo — Estado de un repositorio git tal como lo presenta la UI.
# Mapea 1:1 con la shape de window.RN.REPOS en new-design/repo-nav/js/data.js.
# Status válidos:
# 'clean' | 'dirty' | 'unpushed' | 'behind' | 'conflict' | 'nogit'
# 'unloaded' → enumerado pero sin git status cargado todavía (modo
# AutoLoadMode = Favorites/None). El user lo carga con R o
# al navegar encima.

class Repo {
    [string]   $Id              # identificador estable derivado del nombre/path
    [string]   $Name            # nombre del directorio
    [string]   $Alias           # alias visible "[Kompra]" — opcional
    [string]   $AliasColor      # key de RNTheme.palette: 'c1'..'c10' — opcional
    [bool]     $IsFavorite
    [bool]     $IsContainer     # carpeta sin .git con ≥1 repo git al primer nivel adentro

    [string]   $Branch          # branch activa, "—" si nogit
    [bool]     $IsOnMainBranch  # branch == 'main'/'master'/'develop'
    [string]   $Status          # ver header
    [int]      $Ahead
    [int]      $Behind

    [int]      $Modified
    [int]      $Added
    [int]      $Deleted
    [int]      $Untracked

    [string]   $Path            # absoluto
    [string[]] $Tags = @()      # 'work', 'side', 'learning', etc.
    [string]   $Remote          # 'github', 'gitlab', null
    [Commit]   $LastCommit      # null si nogit
    [string]   $PackageManager  # 'npm', 'pnpm', 'yarn', null
    [int]      $StashCount

    Repo() {
        $this.Tags = @()
        $this.Status = 'clean'
    }

    Repo([string]$id, [string]$name, [string]$path) {
        $this.Id = $id
        $this.Name = $name
        $this.Path = $path
        $this.Tags = @()
        $this.Status = 'clean'
    }

    # Total de cambios en working tree (modified + added + deleted + untracked).
    [int] DirtyCount() {
        return $this.Modified + $this.Added + $this.Deleted + $this.Untracked
    }

    [string] ToString() { return "[$($this.Id)] $($this.Branch) ($($this.Status))" }
}