     1→# NEOG Command - macOS Control Center
     2→
     3→App SwiftUI nativo macOS para controle unificado do ecossistema NEOG: 36 iOS apps, 368 web apps, e 16 serviços backend.
     4→
     5→## Quick Start
     6→
     7→```bash
     8→# Abrir no Xcode
     9→open ~/Apps/macOS/NEOGHub/NEOGCommand.xcodeproj
    10→
    11→# Regenerar projeto (após adicionar arquivos)
    12→cd ~/Apps/macOS/NEOGHub && ruby generate_project.rb
    13→
    14→# Build via terminal
    15→xcodebuild -project NEOGCommand.xcodeproj -scheme NEOGCommand -destination 'platform=macOS' build
    16→
    17→# Rodar
    18→xcodebuild -project NEOGCommand.xcodeproj -scheme NEOGCommand run
    19→```
    20→
    21→## Arquitetura
    22→
    23→### Tech Stack
    24→- **SwiftUI** - macOS 14+
    25→- **Swift Charts** - Visualizações
    26→- **URLSession** - Networking
    27→- **Zero dependências externas**
    28→
    29→### Estrutura
    30→```
    31→NEOGCommand/
    32→├── NEOGCommandApp.swift          # Entry point
    33→├── App/
    34→│   ├── AppState.swift            # Estado global @MainActor
    35→│   ├── ContentView.swift         # NavigationSplitView root
    36→│   └── MenuBar/
    37→│       └── MenuBarView.swift     # Menu bar widget
    38→├── Core/
    39→│   ├── Navigation/
    40→│   │   ├── SidebarCategory.swift # Enum de categorias
    41→│   │   └── SidebarView.swift     # Sidebar com status
    42→│   └── Search/
    43→│       └── SearchService.swift   # Busca global (Cmd+K)
    44→├── Components/
    45→│   └── Charts/
    46→│       └── ROICharts.swift       # Swift Charts components
    47→├── Models/
    48→│   └── Domain/
    49→│       └── CCModels.swift        # ROISummary, CCRun, etc.
    50→├── Modules/
    51→│   ├── Dashboard/
    52→│   │   └── DashboardView.swift   # Cards de ROI, Budget, Services
    53→│   ├── Monitoring/
    54→│   │   └── MonitoringView.swift  # Lista de CC runs + detalhes
    55→│   ├── Services/
    56→│   │   └── ServicesView.swift    # Status dos backends
    57→│   ├── WebApps/
    58→│   │   └── WebAppsView.swift     # Catálogo de 368 web apps
    59→│   └── Settings/
    60→│       └── SettingsView.swift    # Configurações
    61→└── Services/
    62→    ├── Network/
    63→    │   ├── APIClient.swift       # REST client genérico
    64→    │   └── Endpoint.swift        # Endpoints API
    65→    ├── Integration/
    66→    │   └── CCTrackingService.swift # CC ROI API wrapper
    67→    ├── Realtime/
    68→    │   └── RealtimeService.swift  # Polling adaptativo + eventos
    69→    └── ProcessManager/
    70→        └── ServiceManager.swift   # Start/Stop backend services
    71→```
    72→
    73→## Features
    74→
    75→### Dashboard
    76→- **ROI Summary** - Custo, valor, profit, ROI% do dia
    77→- **All-Time Stats** - Estatísticas totais
    78→- **Budget Status** - Uso diário/mensal com progress bars
    79→- **Services Status** - Status dos 4 backends principais
    80→- **Recent Runs** - Últimas execuções CC
    81→- **Quick Actions** - Ações rápidas
    82→
    83→### Monitoring (CC ROI)
    84→- Lista de runs com filtros por status
    85→- Detalhes completos de cada run
    86→- Métricas: tokens, custo, valor, ROI
    87→- Tools usados e arquivos modificados
    88→- Timeline de eventos
    89→
    90→### Services
    91→- Status em tempo real (ports 9001, 5555, 9002, 9004)
    92→- Endpoints de cada serviço
    93→- Copiar URLs para clipboard
    94→- Start/Stop (TODO)
    95→
    96→### Web Apps
    97→- Catálogo de 368 apps
    98→- Filtro por categoria
    99→- Busca por nome
   100→- Lançamento direto no browser
   101→
   102→### Global Search (Cmd+K)
   103→- Busca em runs, services, web apps
   104→- Quick actions
   105→- Navegação rápida
   106→
   107→## Keyboard Shortcuts
   108→
   109→### Navigation
   110→| Shortcut | Action |
   111→|----------|--------|
   112→| `⌘1` | Dashboard |
   113→| `⌘2` | Monitoring |
   114→| `⌘3` | Services |
   115→| `⌘4` | Web Apps |
   116→| `⌘,` | Settings |
   117→| `⌘]` | Next Section |
   118→| `⌘[` | Previous Section |
   119→
   120→### Search & Actions
   121→| Shortcut | Action |
   122→|----------|--------|
   123→| `⌘K` | Global Search |
   124→| `⌘R` | Refresh Data |
   125→| `⇧⌘O` | Open ROI Dashboard |
   126→| `⌘/` | Keyboard Shortcuts Help |
   127→
   128→### Services
   129→| Shortcut | Action |
   130→|----------|--------|
   131→| `⇧⌘S` | Start All Services |
   132→| `⇧⌘X` | Stop All Services |
   133→
   134→### Export (v1.3.0)
   135→| Shortcut | Action |
   136→|----------|--------|
   137→| `⌘E` | Export as JSON |
   138→| `⇧⌘E` | Export as CSV |
   139→| `⌥⌘E` | Export Summary Report |
   140→
   141→### Lists & Search Results
   142→| Shortcut | Action |
   143→|----------|--------|
   144→| `↑/↓` | Navigate Items |
   145→| `↵` (Enter) | Select/Open Item |
   146→| `⎋` (Escape) | Cancel/Close |
   147→
   148→## API Integration
   149→
   150→### Log Server (Port 9001)
   151→```
   152→GET  /api/cc/roi/summary      # Stats do dia
   153→GET  /api/cc/roi/all-time     # Stats totais
   154→GET  /api/cc/runs             # Lista runs
   155→GET  /api/cc/run/<id>         # Detalhes run
   156→GET  /api/cc/budget           # Limites budget
   157→GET  /api/cc/health           # Health check
   158→```
   159→
   160→### System Monitor (Port 5555)
   161→```
   162→GET  /api/system/all          # Métricas sistema
   163→```
   164→
   165→### WiFi API (Port 9002)
   166→```
   167→GET  /networks                # Lista redes
   168→GET  /scan                    # Scan WiFi
   169→```
   170→
   171→### Workspace API (Port 9004)
   172→```
   173→GET  /api/disk/overview       # Uso de disco
   174→GET  /api/projects/overview   # Lista projetos
   175→```
   176→
   177→## AppState
   178→
   179→```swift
   180→@MainActor
   181→final class AppState: ObservableObject {
   182→    // Navigation
   183→    @Published var selectedCategory: SidebarCategory = .dashboard
   184→    @Published var isSearchPresented: Bool = false
   185→
   186→    // CC ROI Data
   187→    @Published var roiSummary: ROISummary?
   188→    @Published var allTimeStats: AllTimeStats?
   189→    @Published var recentRuns: [CCRun] = []
   190→    @Published var budgetConfig: BudgetConfig?
   191→
   192→    // Services
   193→    @Published var services: [ServiceStatus] = []
   194→
   195→    // Connection
   196→    @Published var isConnected: Bool = false
   197→    @Published var lastSyncDate: Date?
   198→}
   199→```
   200→
   201→## Requirements
   202→
   203→- **macOS**: 14.0+
   204→- **Xcode**: 16.0+
   205→- **Swift**: 5.9+
   206→
   207→### Backend Services (opcional)
   208→```bash
   209→# Log Server (CC ROI)
   210→python3 ~/Services/servers/log-server.py
   211→
   212→# HTTP Server (Web Apps)
   213→cd ~/Web && python3 -m http.server 8000
   214→```
   215→
   216→## Changelog
   217→
   218→### v1.0.0 (Dec 2025) - Initial Release
   219→- NavigationSplitView com 5 módulos
   220→- Dashboard com ROI cards
   221→- CC ROI Monitoring com lista de runs
   222→- Services status monitoring
   223→- Web Apps catalog (368 apps)
   224→- Global Search (Cmd+K)
   225→- Swift Charts para visualizações
   226→- Auto-refresh a cada 30 segundos
   227→
   228→### v1.1.0 (Dec 2025) - Real-time Updates & Menu Bar
   229→- **RealtimeService** - Polling adaptativo (3s ativo, 30s idle)
   230→- **Connection status** - Indicador visual de conexão
   231→- **Budget alerts** - Alertas de orçamento (80%, 100%)
   232→- **Force refresh** - Botão para atualização manual
   233→- **Event-driven updates** - ROI e runs via Combine
   234→- **Menu Bar Widget** - Acesso rápido sem abrir janela principal
   235→  - ROI summary (cost, value, ROI%)
   236→  - Budget usage com progress bar
   237→  - Services status com start/stop
   238→  - Quick actions (refresh, open dashboard)
   239→  - Toggle em Settings (Show Menu Bar Widget)
   240→  - Launch at Login option
   241→- **Service Manager** - Controle de serviços backend
   242→  - Start/Stop individual services
   243→  - Start All / Stop All
   244→  - Restart service
   245→  - Uptime tracking
   246→  - Process output capture
   247→  - Services: Log Server, System Monitor, WiFi API, Workspace API
   248→- **Keyboard Navigation** - Navegação completa via teclado
   249→  - ⌘1-4 para seções principais
   250→  - ⌘] e ⌘[ para próxima/anterior seção
   251→  - ⌘K para busca global
   252→  - ⌘R para refresh
   253→  - ⇧⌘S/X para start/stop all services
   254→  - ⌘/ para referência de atalhos
   255→  - Arrow keys para navegação em listas
   256→  - Enter para selecionar, Escape para fechar
   257→  - Focus management com @FocusState
   258→- **Native macOS Notifications** - Notificações nativas do sistema
   259→  - Budget alerts (customizable threshold: 50-100%)
   260→  - Run completed/failed notifications
   261→  - Service status changes (start/stop)
   262→  - Connection status changes
   263→  - Actionable notifications (View Details, Open Dashboard, Start/Stop Service)
   264→  - Notification settings in Settings view
   265→  - Test notification button
   266→  - Deep linking from notifications to app sections
   267→- **Service Logs Viewer** - Visualização de logs em tempo real
   268→  - Real-time log streaming from stdout/stderr
   269→  - Per-service log separation
   270→  - Log level filtering (All, Info, Warning, Error, Debug)
   271→  - Search within logs
   272→  - Auto-scroll toggle
   273→  - Timestamp toggle
   274→  - Export logs to file
   275→  - Unread log indicators
   276→  - Recent logs preview in service detail
   277→  - Max 1000 entries per service (auto-trim)
   278→
   279→### v1.2.0 (Dec 2025) - CC Live Tracker & Settings
   280→- **CC Live Tracker** - Real-time Claude Code session monitoring
   281→  - File watcher for ~/.claude/stats-cache.json
   282→  - Live session cost tracking
   283→  - Token consumption (input/output/cache)
   284→  - Session duration tracking
   285→  - Start/Stop controls in Settings
   286→- **Settings enhancements**
   287→  - CC Live Tracker status and controls
   288→  - Service ports reference
   289→  - Notification preferences
   290→- **Service auto-start**
   291→  - start-all-services.sh script
   292→  - LaunchAgent for login auto-start
   293→
   294→### v1.3.0 (Dec 2025) - Export & Data Analysis
   295→- **Export functionality** - Full data export capabilities
   296→  - Export as JSON (all run details)
   297→  - Export as CSV (spreadsheet format)
   298→  - Export Summary Report (formatted text)
   299→  - Copy to Clipboard support
   300→  - NSSavePanel integration
   301→- **Toolbar improvements**
   302→  - Fixed Menu rendering in toolbar (Button+popover)
   303→  - Export button with share icon
   304→- **Real-time Consumption View**
   305→  - Live session metrics
   306→  - Consumption over time chart
   307→  - Token rate calculations
   308→  - Budget progress tracking
   309→
   310→## Roadmap
   311→
   312→### v1.4.0
   313→- [ ] iOS data sync (CloudKit)
   314→- [ ] Productivity module (Tasks, Habits)
   315→- [ ] Finance module (FIIs)
   316→- [ ] LM Studio integration
   317→- [ ] Widgets para Desktop
   318→
   319→---
   320→
   321→**Created**: 2025-12-24
   322→**Location**: `~/Apps/macOS/NEOGHub/`
   323→**Bundle ID**: `com.neog.command`
   324→**Product Name**: NEOG Command
   325→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

# NEOG Command - macOS Control Center

App SwiftUI nativo macOS para controle unificado do ecossistema NEOG: 36 iOS apps, 368 web apps, e 16 serviços backend.

## Quick Start

```bash
# Abrir no Xcode
open ~/Apps/macOS/NEOGHub/NEOGCommand.xcodeproj

# Regenerar projeto (após adicionar arquivos)
cd ~/Apps/macOS/NEOGHub && ruby generate_project.rb

# Build via terminal
xcodebuild -project NEOGCommand.xcodeproj -scheme NEOGCommand -destination 'platform=macOS' build

# Rodar
xcodebuild -project NEOGCommand.xcodeproj -scheme NEOGCommand run
```

## Arquitetura

### Tech Stack
- **SwiftUI** - macOS 14+
- **Swift Charts** - Visualizações
- **URLSession** - Networking
- **Zero dependências externas**

### Estrutura
```
NEOGCommand/
├── NEOGCommandApp.swift          # Entry point
├── App/
│   ├── AppState.swift            # Estado global @MainActor
│   ├── ContentView.swift         # NavigationSplitView root
│   └── MenuBar/
│       └── MenuBarView.swift     # Menu bar widget
├── Core/
│   ├── Navigation/
│   │   ├── SidebarCategory.swift # Enum de categorias
│   │   └── SidebarView.swift     # Sidebar com status
│   └── Search/
│       └── SearchService.swift   # Busca global (Cmd+K)
├── Components/
│   └── Charts/
│       └── ROICharts.swift       # Swift Charts components
├── Models/
│   └── Domain/
│       └── CCModels.swift        # ROISummary, CCRun, etc.
├── Modules/
│   ├── Dashboard/
│   │   └── DashboardView.swift   # Cards de ROI, Budget, Services
│   ├── Monitoring/
│   │   └── MonitoringView.swift  # Lista de CC runs + detalhes
│   ├── Services/
│   │   └── ServicesView.swift    # Status dos backends
│   ├── WebApps/
│   │   └── WebAppsView.swift     # Catálogo de 368 web apps
│   └── Settings/
│       └── SettingsView.swift    # Configurações
└── Services/
    ├── Network/
    │   ├── APIClient.swift       # REST client genérico
    │   └── Endpoint.swift        # Endpoints API
    ├── Integration/
    │   └── CCTrackingService.swift # CC ROI API wrapper
    ├── Realtime/
    │   └── RealtimeService.swift  # Polling adaptativo + eventos
    └── ProcessManager/
        └── ServiceManager.swift   # Start/Stop backend services
```

## Features

### Dashboard
- **ROI Summary** - Custo, valor, profit, ROI% do dia
- **All-Time Stats** - Estatísticas totais
- **Budget Status** - Uso diário/mensal com progress bars
- **Services Status** - Status dos 4 backends principais
- **Recent Runs** - Últimas execuções CC
- **Quick Actions** - Ações rápidas

### Monitoring (CC ROI)
- Lista de runs com filtros por status
- Detalhes completos de cada run
- Métricas: tokens, custo, valor, ROI
- Tools usados e arquivos modificados
- Timeline de eventos

### Services
- Status em tempo real (ports 9001, 5555, 9002, 9004)
- Endpoints de cada serviço
- Copiar URLs para clipboard
- Start/Stop (TODO)

### Web Apps
- Catálogo de 368 apps
- Filtro por categoria
- Busca por nome
- Lançamento direto no browser

### Global Search (Cmd+K)
- Busca em runs, services, web apps
- Quick actions
- Navegação rápida

## Keyboard Shortcuts

### Navigation
| Shortcut | Action |
|----------|--------|
| `⌘1` | Dashboard |
| `⌘2` | Monitoring |
| `⌘3` | Services |
| `⌘4` | Web Apps |
| `⌘,` | Settings |
| `⌘]` | Next Section |
| `⌘[` | Previous Section |

### Search & Actions
| Shortcut | Action |
|----------|--------|
| `⌘K` | Global Search |
| `⌘R` | Refresh Data |
| `⇧⌘O` | Open ROI Dashboard |
| `⌘/` | Keyboard Shortcuts Help |

### Services
| Shortcut | Action |
|----------|--------|
| `⇧⌘S` | Start All Services |
| `⇧⌘X` | Stop All Services |

### Export (v1.3.0)
| Shortcut | Action |
|----------|--------|
| `⌘E` | Export as JSON |
| `⇧⌘E` | Export as CSV |
| `⌥⌘E` | Export Summary Report |

### Lists & Search Results
| Shortcut | Action |
|----------|--------|
| `↑/↓` | Navigate Items |
| `↵` (Enter) | Select/Open Item |
| `⎋` (Escape) | Cancel/Close |

## API Integration

### Log Server (Port 9001)
```
GET  /api/cc/roi/summary      # Stats do dia
GET  /api/cc/roi/all-time     # Stats totais
GET  /api/cc/runs             # Lista runs
GET  /api/cc/run/<id>         # Detalhes run
GET  /api/cc/budget           # Limites budget
GET  /api/cc/health           # Health check
```

### System Monitor (Port 5555)
```
GET  /api/system/all          # Métricas sistema
```

### WiFi API (Port 9002)
```
GET  /networks                # Lista redes
GET  /scan                    # Scan WiFi
```

### Workspace API (Port 9004)
```
GET  /api/disk/overview       # Uso de disco
GET  /api/projects/overview   # Lista projetos
```

## AppState

```swift
@MainActor
final class AppState: ObservableObject {
    // Navigation
    @Published var selectedCategory: SidebarCategory = .dashboard
    @Published var isSearchPresented: Bool = false

    // CC ROI Data
    @Published var roiSummary: ROISummary?
    @Published var allTimeStats: AllTimeStats?
    @Published var recentRuns: [CCRun] = []
    @Published var budgetConfig: BudgetConfig?

    // Services
    @Published var services: [ServiceStatus] = []

    // Connection
    @Published var isConnected: Bool = false
    @Published var lastSyncDate: Date?
}
```

## Requirements

- **macOS**: 14.0+
- **Xcode**: 16.0+
- **Swift**: 5.9+

### Backend Services (opcional)
```bash
# Log Server (CC ROI)
python3 ~/Services/servers/log-server.py

# HTTP Server (Web Apps)
cd ~/Web && python3 -m http.server 8000
```

## Changelog

### v1.0.0 (Dec 2025) - Initial Release
- NavigationSplitView com 5 módulos
- Dashboard com ROI cards
- CC ROI Monitoring com lista de runs
- Services status monitoring
- Web Apps catalog (368 apps)
- Global Search (Cmd+K)
- Swift Charts para visualizações
- Auto-refresh a cada 30 segundos

### v1.1.0 (Dec 2025) - Real-time Updates & Menu Bar
- **RealtimeService** - Polling adaptativo (3s ativo, 30s idle)
- **Connection status** - Indicador visual de conexão
- **Budget alerts** - Alertas de orçamento (80%, 100%)
- **Force refresh** - Botão para atualização manual
- **Event-driven updates** - ROI e runs via Combine
- **Menu Bar Widget** - Acesso rápido sem abrir janela principal
  - ROI summary (cost, value, ROI%)
  - Budget usage com progress bar
  - Services status com start/stop
  - Quick actions (refresh, open dashboard)
  - Toggle em Settings (Show Menu Bar Widget)
  - Launch at Login option
- **Service Manager** - Controle de serviços backend
  - Start/Stop individual services
  - Start All / Stop All
  - Restart service
  - Uptime tracking
  - Process output capture
  - Services: Log Server, System Monitor, WiFi API, Workspace API
- **Keyboard Navigation** - Navegação completa via teclado
  - ⌘1-4 para seções principais
  - ⌘] e ⌘[ para próxima/anterior seção
  - ⌘K para busca global
  - ⌘R para refresh
  - ⇧⌘S/X para start/stop all services
  - ⌘/ para referência de atalhos
  - Arrow keys para navegação em listas
  - Enter para selecionar, Escape para fechar
  - Focus management com @FocusState
- **Native macOS Notifications** - Notificações nativas do sistema
  - Budget alerts (customizable threshold: 50-100%)
  - Run completed/failed notifications
  - Service status changes (start/stop)
  - Connection status changes
  - Actionable notifications (View Details, Open Dashboard, Start/Stop Service)
  - Notification settings in Settings view
  - Test notification button
  - Deep linking from notifications to app sections
- **Service Logs Viewer** - Visualização de logs em tempo real
  - Real-time log streaming from stdout/stderr
  - Per-service log separation
  - Log level filtering (All, Info, Warning, Error, Debug)
  - Search within logs
  - Auto-scroll toggle
  - Timestamp toggle
  - Export logs to file
  - Unread log indicators
  - Recent logs preview in service detail
  - Max 1000 entries per service (auto-trim)

### v1.2.0 (Dec 2025) - CC Live Tracker & Settings
- **CC Live Tracker** - Real-time Claude Code session monitoring
  - File watcher for ~/.claude/stats-cache.json
  - Live session cost tracking
  - Token consumption (input/output/cache)
  - Session duration tracking
  - Start/Stop controls in Settings
- **Settings enhancements**
  - CC Live Tracker status and controls
  - Service ports reference
  - Notification preferences
- **Service auto-start**
  - start-all-services.sh script
  - LaunchAgent for login auto-start

### v1.3.0 (Dec 2025) - Export & Data Analysis
- **Export functionality** - Full data export capabilities
  - Export as JSON (all run details)
  - Export as CSV (spreadsheet format)
  - Export Summary Report (formatted text)
  - Copy to Clipboard support
  - NSSavePanel integration
- **Toolbar improvements**
  - Fixed Menu rendering in toolbar (Button+popover)
  - Export button with share icon
- **Real-time Consumption View**
  - Live session metrics
  - Consumption over time chart
  - Token rate calculations
  - Budget progress tracking

## Roadmap

### v1.4.0
- [ ] iOS data sync (CloudKit)
- [ ] Productivity module (Tasks, Habits)
- [ ] Finance module (FIIs)
- [ ] LM Studio integration
- [ ] Widgets para Desktop

---

**Created**: 2025-12-24
**Location**: `~/Apps/macOS/NEOGHub/`
**Bundle ID**: `com.neog.command`
**Product Name**: NEOG Command


     1→import Foundation
     2→import SwiftUI
     3→
     4→@MainActor
     5→class DataManager: ObservableObject {
     6→    static let shared = DataManager()
     7→
     8→    // MARK: - Published Properties
     9→    @Published var debts: [Debt] = []
    10→    @Published var transactions: [Transaction] = []
    11→    @Published var profile: FinancialProfile = .default
    12→    @Published var expectedIncome: Double = 40000 // Empréstimo Santander
    13→    @Published var leads: [Lead] = []
    14→    @Published var incomeTasks: [IncomeTask] = []
    15→    @Published var incomeGoal: IncomeGoal = .default
    16→
    17→    // MARK: - UserDefaults Keys
    18→    private let debtsKey = "neog_finance_debts"
    19→    private let transactionsKey = "neog_finance_transactions"
    20→    private let profileKey = "neog_finance_profile"
    21→    private let leadsKey = "neog_finance_leads"
    22→    private let incomeTasksKey = "neog_finance_income_tasks"
    23→    private let incomeGoalKey = "neog_finance_income_goal"
    24→
    25→    // MARK: - Init
    26→    private init() {
    27→        loadData()
    28→        if debts.isEmpty {
    29→            loadInitialData()
    30→        }
    31→    }
    32→
    33→    // MARK: - Computed Properties
    34→
    35→    var totalDebts: Double {
    36→        debts.filter { $0.status != .paid }.reduce(0) { $0 + $1.amount }
    37→    }
    38→
    39→    var totalRecurringDebts: Double {
    40→        debts.filter { $0.isRecurring && $0.status != .paid }
    41→            .reduce(0) { $0 + ($1.recurringAmount ?? 0) }
    42→    }
    43→
    44→    var overdueDebts: [Debt] {
    45→        debts.filter { $0.isOverdue }.sorted { $0.urgencyLevel > $1.urgencyLevel }
    46→    }
    47→
    48→    var pendingDebts: [Debt] {
    49→        debts.filter { $0.status == .pending && !$0.isOverdue }
    50→            .sorted { ($0.dueDate ?? .distantFuture) < ($1.dueDate ?? .distantFuture) }
    51→    }
    52→
    53→    var paidDebts: [Debt] {
    54→        debts.filter { $0.status == .paid }
    55→    }
    56→
    57→    var sortedDebtsByUrgency: [Debt] {
    58→        debts.filter { $0.status != .paid }.sorted { $0.urgencyLevel > $1.urgencyLevel }
    59→    }
    60→
    61→    var monthlyIncome: Double {
    62→        currentMonthTransactions
    63→            .filter { $0.type == .income }
    64→            .reduce(0) { $0 + $1.amount }
    65→    }
    66→
    67→    var monthlyExpenses: Double {
    68→        currentMonthTransactions
    69→            .filter { $0.type == .expense }
    70→            .reduce(0) { $0 + $1.amount }
    71→    }
    72→
    73→    var monthlyBalance: Double {
    74→        monthlyIncome - monthlyExpenses
    75→    }
    76→
    77→    var currentMonthTransactions: [Transaction] {
    78→        let calendar = Calendar.current
    79→        return transactions.filter {
    80→            calendar.isDate($0.date, equalTo: Date(), toGranularity: .month)
    81→        }
    82→    }
    83→
    84→    var recurringExpenses: [Transaction] {
    85→        transactions.filter { $0.type == .expense && $0.isRecurring }
    86→    }
    87→
    88→    var totalRecurringExpenses: Double {
    89→        recurringExpenses.reduce(0) { $0 + $1.amount }
    90→    }
    91→
    92→    var projectedMonthlyBalance: Double {
    93→        profile.monthlyIncomeAverage - totalRecurringExpenses - totalRecurringDebts
    94→    }
    95→
    96→    var balanceAfterLoan: Double {
    97→        expectedIncome - totalDebts
    98→    }
    99→
   100→    // MARK: - Leads Computed Properties
   101→
   102→    var totalLeadsValue: Double {
   103→        leads.reduce(0) { $0 + $1.value }
   104→    }
   105→
   106→    var closedLeadsValue: Double {
   107→        leads.filter { $0.status == .closed }.reduce(0) { $0 + $1.value }
   108→    }
   109→
   110→    var pendingLeadsValue: Double {
   111→        leads.filter { $0.status == .proposal || $0.status == .negotiating }.reduce(0) { $0 + $1.value }
   112→    }
   113→
   114→    var incomeGoalProgress: Double {
   115→        guard incomeGoal.targetAmount > 0 else { return 0 }
   116→        return min(closedLeadsValue / incomeGoal.targetAmount, 1.0)
   117→    }
   118→
   119→    var daysUntilGoalDeadline: Int {
   120→        Calendar.current.dateComponents([.day], from: Date(), to: incomeGoal.deadline).day ?? 0
   121→    }
   122→
   123→    // MARK: - CRUD Operations
   124→
   125→    func addDebt(_ debt: Debt) {
   126→        debts.append(debt)
   127→        saveData()
   128→    }
   129→
   130→    func updateDebt(_ debt: Debt) {
   131→        if let index = debts.firstIndex(where: { $0.id == debt.id }) {
   132→            debts[index] = debt
   133→            saveData()
   134→        }
   135→    }
   136→
   137→    func deleteDebt(_ debt: Debt) {
   138→        debts.removeAll { $0.id == debt.id }
   139→        saveData()
   140→    }
   141→
   142→    func markDebtAsPaid(_ debt: Debt) {
   143→        if let index = debts.firstIndex(where: { $0.id == debt.id }) {
   144→            debts[index].status = .paid
   145→            saveData()
   146→        }
   147→    }
   148→
   149→    func addTransaction(_ transaction: Transaction) {
   150→        transactions.append(transaction)
   151→        saveData()
   152→    }
   153→
   154→    func deleteTransaction(_ transaction: Transaction) {
   155→        transactions.removeAll { $0.id == transaction.id }
   156→        saveData()
   157→    }
   158→
   159→    // MARK: - Lead Operations
   160→
   161→    func addLead(_ lead: Lead) {
   162→        leads.append(lead)
   163→        saveData()
   164→    }
   165→
   166→    func updateLead(_ lead: Lead) {
   167→        if let index = leads.firstIndex(where: { $0.id == lead.id }) {
   168→            leads[index] = lead
   169→            saveData()
   170→        }
   171→    }
   172→
   173→    func updateLeadStatus(_ lead: Lead, to newStatus: LeadStatus) {
   174→        if let index = leads.firstIndex(where: { $0.id == lead.id }) {
   175→            leads[index].status = newStatus
   176→            saveData()
   177→        }
   178→    }
   179→
   180→    func deleteLead(_ lead: Lead) {
   181→        leads.removeAll { $0.id == lead.id }
   182→        saveData()
   183→    }
   184→
   185→    // MARK: - Income Task Operations
   186→
   187→    func addIncomeTask(_ task: IncomeTask) {
   188→        incomeTasks.append(task)
   189→        saveData()
   190→    }
   191→
   192→    func toggleTaskCompletion(_ task: IncomeTask) {
   193→        if let index = incomeTasks.firstIndex(where: { $0.id == task.id }) {
   194→            incomeTasks[index].isCompleted.toggle()
   195→            if incomeTasks[index].isCompleted {
   196→                incomeTasks[index].completedAt = Date()
   197→            } else {
   198→                incomeTasks[index].completedAt = nil
   199→            }
   200→            saveData()
   201→        }
   202→    }
   203→
   204→    func deleteIncomeTask(_ task: IncomeTask) {
   205→        incomeTasks.removeAll { $0.id == task.id }
   206→        saveData()
   207→    }
   208→
   209→    func resetDailyTasks() {
   210→        // Reset tasks that are daily and were completed yesterday
   211→        let calendar = Calendar.current
   212→        for index in incomeTasks.indices {
   213→            if incomeTasks[index].isDaily,
   214→               let completedAt = incomeTasks[index].completedAt,
   215→               !calendar.isDateInToday(completedAt) {
   216→                incomeTasks[index].isCompleted = false
   217→                incomeTasks[index].completedAt = nil
   218→            }
   219→        }
   220→        saveData()
   221→    }
   222→
   223→    func updateIncomeGoal(_ goal: IncomeGoal) {
   224→        incomeGoal = goal
   225→        saveData()
   226→    }
   227→
   228→    // MARK: - Persistence
   229→
   230→    private func saveData() {
   231→        if let encoded = try? JSONEncoder().encode(debts) {
   232→            UserDefaults.standard.set(encoded, forKey: debtsKey)
   233→        }
   234→        if let encoded = try? JSONEncoder().encode(transactions) {
   235→            UserDefaults.standard.set(encoded, forKey: transactionsKey)
   236→        }
   237→        if let encoded = try? JSONEncoder().encode(profile) {
   238→            UserDefaults.standard.set(encoded, forKey: profileKey)
   239→        }
   240→        if let encoded = try? JSONEncoder().encode(leads) {
   241→            UserDefaults.standard.set(encoded, forKey: leadsKey)
   242→        }
   243→        if let encoded = try? JSONEncoder().encode(incomeTasks) {
   244→            UserDefaults.standard.set(encoded, forKey: incomeTasksKey)
   245→        }
   246→        if let encoded = try? JSONEncoder().encode(incomeGoal) {
   247→            UserDefaults.standard.set(encoded, forKey: incomeGoalKey)
   248→        }
   249→    }
   250→
   251→    private func loadData() {
   252→        if let data = UserDefaults.standard.data(forKey: debtsKey),
   253→           let decoded = try? JSONDecoder().decode([Debt].self, from: data) {
   254→            debts = decoded
   255→        }
   256→        if let data = UserDefaults.standard.data(forKey: transactionsKey),
   257→           let decoded = try? JSONDecoder().decode([Transaction].self, from: data) {
   258→            transactions = decoded
   259→        }
   260→        if let data = UserDefaults.standard.data(forKey: profileKey),
   261→           let decoded = try? JSONDecoder().decode(FinancialProfile.self, from: data) {
   262→            profile = decoded
   263→        }
   264→        if let data = UserDefaults.standard.data(forKey: leadsKey),
   265→           let decoded = try? JSONDecoder().decode([Lead].self, from: data) {
   266→            leads = decoded
   267→        }
   268→        if let data = UserDefaults.standard.data(forKey: incomeTasksKey),
   269→           let decoded = try? JSONDecoder().decode([IncomeTask].self, from: data) {
   270→            incomeTasks = decoded
   271→        }
   272→        if let data = UserDefaults.standard.data(forKey: incomeGoalKey),
   273→           let decoded = try? JSONDecoder().decode(IncomeGoal.self, from: data) {
   274→            incomeGoal = decoded
   275→        }
   276→
   277→        // Add Mercado Pago debt if it doesn't exist
   278→        addMercadoPagoDebtIfNeeded()
   279→
   280→        // Reset daily tasks if needed
   281→        resetDailyTasks()
   282→
   283→        // Load default income tasks if empty
   284→        if incomeTasks.isEmpty {
   285→            loadDefaultIncomeTasks()
   286→        }
   287→
   288→        // Add test lead if needed
   289→        addBancoMasterLeadIfNeeded()
   290→    }
   291→
   292→    private func addBancoMasterLeadIfNeeded() {
   293→        // Add Luiz Mourão as Connector
   294→        let connectorName = "Luiz Mourao"
   295→        if !leads.contains(where: { $0.name == connectorName }) {
   296→            let luizConnector = Lead(
   297→                name: connectorName,
   298→                service: "Conector de Clientes",
   299→                value: 0, // Connector doesn't pay directly
   300→                status: .lost, // EM PAUSA - Crise pessoal grave (Dez/2025)
   301→                type: .connector,
   302→                notes: "⚠ EM PAUSA (Dez/2025): Crise pessoal grave - problemas de saude (cardiaco), luto (avo), questoes pessoais. Banco Master sob investigacao PF. Reavaliar em 30-60 dias. | Historico: Conector principal 2.5 anos, media R$35k/mes. Intermediario com Daniel Vorcaro (CEO Banco Master).",
   303→                contactInfo: "WhatsApp direto",
   304→                source: "Networking",
   305→                potentialMonthlyValue: 35000,
   306→                connectedClients: ["Daniel Vorcaro", "Banco Master"]
   307→            )
   308→            leads.append(luizConnector)
   309→        }
   310→
   311→        // Update existing Luiz entry if needed
   312→        if let index = leads.firstIndex(where: { $0.name == connectorName && $0.status != .lost }) {
   313→            leads[index].status = .lost
   314→            leads[index].notes = "⚠ EM PAUSA (Dez/2025): Crise pessoal grave - problemas de saude (cardiaco), luto (avo), questoes pessoais. Banco Master sob investigacao PF. Reavaliar em 30-60 dias. | Historico: Conector principal 2.5 anos, media R$35k/mes. Intermediario com Daniel Vorcaro (CEO Banco Master)."
   315→            saveData()
   316→        }
   317→
   318→        // Add Banco Master as Direct Lead (via Luiz)
   319→        let leadName = "Banco Master"
   320→        if !leads.contains(where: { $0.name == leadName }) {
   321→            let bancoMasterLead = Lead(
   322→                name: leadName,
   323→                service: "Consultoria Tech / Desenvolvimento",
   324→                value: 35000,
   325→                status: .lost, // EM PAUSA - Investigação PF
   326→                type: .direct,
   327→                notes: "⚠ EM PAUSA (Dez/2025): Banco Master sob investigacao da PF. Conector Luiz em crise pessoal. Reavaliar em 30-60 dias. | Historico: Cliente via Luiz Mourao. CEO: Daniel Vorcaro. 2.5 anos de contrato, R$35-50k/mes (pico R$85k).",
   328→                contactInfo: "Via Luiz Mourao",
   329→                source: "Conector: Luiz Mourao"
   330→            )
   331→            leads.append(bancoMasterLead)
   332→        }
   333→
   334→        // Update existing Banco Master entry if needed
   335→        if let index = leads.firstIndex(where: { $0.name == leadName && $0.status != .lost }) {
   336→            leads[index].status = .lost
   337→            leads[index].notes = "⚠ EM PAUSA (Dez/2025): Banco Master sob investigacao da PF. Conector Luiz em crise pessoal. Reavaliar em 30-60 dias. | Historico: Cliente via Luiz Mourao. CEO: Daniel Vorcaro. 2.5 anos de contrato, R$35-50k/mes (pico R$85k)."
   338→        }
   339→
   340→        saveData()
   341→    }
   342→
   343→    private func loadDefaultIncomeTasks() {
   344→        incomeTasks = [
   345→            IncomeTask(title: "Listar 10 contatos potenciais", subtitle: "Clientes antigos + novos", tag: "Prioritario", tagColor: "red", isDaily: false),
   346→            IncomeTask(title: "Criar post para LinkedIn", subtitle: "Sobre disponibilidade", tag: "Marketing", tagColor: "blue", isDaily: false),
   347→            IncomeTask(title: "Atualizar perfil em marketplaces", subtitle: "Workana, 99freelas", tag: "Marketing", tagColor: "blue", isDaily: false),
   348→            IncomeTask(title: "Enviar 5 mensagens de prospeccao", subtitle: "WhatsApp ou email", tag: "Vendas", tagColor: "green", isDaily: true),
   349→            IncomeTask(title: "Fazer follow-up com leads", subtitle: "Responder interessados", tag: "Vendas", tagColor: "green", isDaily: true)
   350→        ]
   351→        saveData()
   352→    }
   353→
   354→    private func addMercadoPagoDebtIfNeeded() {
   355→        let debtName = "Cartao Mercado Pago Mae"
   356→        if !debts.contains(where: { $0.name == debtName }) {
   357→            let dateFormatter = DateFormatter()
   358→            dateFormatter.dateFormat = "dd/MM/yyyy"
   359→
   360→            let mercadoPagoDebt = Debt(
   361→                name: debtName,
   362→                amount: 3749.53,
   363→                creditor: "Mercado Pago",
   364→                dueDate: dateFormatter.date(from: "22/12/2025"),
   365→                status: .overdue,
   366→                notes: "Fatura cartao da mae. Pagamento minimo: R$584,71. Preferencia: quitar tudo de uma vez."
   367→            )
   368→            debts.append(mercadoPagoDebt)
   369→            saveData()
   370→        }
   371→
   372→        // Update Santander loan notes if needed
   373→        updateSantanderLoanNotes()
   374→    }
   375→
   376→    private func updateSantanderLoanNotes() {
   377→        let updatedNotes = "Garantia de imovel (alienacao fiduciaria). Total a pagar: R$94.765,45. AGUARDANDO LIBERACAO: Documento final do cartorio fica pronto segunda-feira (29/12/2025). Apos isso, banco tem 5 dias uteis para depositar. Previsao de deposito: ~06/01/2026."
   378→
   379→        if let index = debts.firstIndex(where: { $0.name == "Emprestimo Santander" }) {
   380→            if debts[index].notes != updatedNotes {
   381→                debts[index].notes = updatedNotes
   382→                saveData()
   383→            }
   384→        }
   385→    }
   386→
   387→    func resetToInitialData() {
   388→        UserDefaults.standard.removeObject(forKey: debtsKey)
   389→        UserDefaults.standard.removeObject(forKey: transactionsKey)
   390→        debts = []
   391→        transactions = []
   392→        loadInitialData()
   393→    }
   394→
   395→    // MARK: - Initial Data (User's Financial Profile)
   396→
   397→    private func loadInitialData() {
   398→        let calendar = Calendar.current
   399→        let dateFormatter = DateFormatter()
   400→        dateFormatter.dateFormat = "dd/MM/yyyy"
   401→
   402→        // MARK: Dívidas Urgentes
   403→        debts = [
   404→            // 1. Empréstimo Nubank - VENCIDO E URGENTE
   405→            Debt(
   406→                name: "Emprestimo Nubank - URGENTE",
   407→                amount: 6000,
   408→                creditor: "Nubank",
   409→                dueDate: dateFormatter.date(from: "20/12/2024"),
   410→                interestRate: 10,
   411→                status: .overdue,
   412→                notes: "PRIORIDADE MAXIMA! Venceu em 20/12/2024. Aguardando emprestimo Santander para quitar. Ligar para negociar juros."
   413→            ),
   414→
   415→            // 2. Aluguel próprio
   416→            Debt(
   417→                name: "Aluguel Proprio",
   418→                amount: 4000,
   419→                creditor: "Proprietario",
   420→                dueDate: dateFormatter.date(from: "05/01/2026"),
   421→                status: .pending,
   422→                notes: "U$750 - inclui agua, luz, internet"
   423→            ),
   424→
   425→            // 3. Aluguel mãe
   426→            Debt(
   427→                name: "Aluguel Mae",
   428→                amount: 1300,
   429→                creditor: "Proprietario Mae",
   430→                dueDate: dateFormatter.date(from: "10/01/2026"),
   431→                status: .pending,
   432→                notes: "Aluguel da mae"
   433→            ),
   434→
   435→            // 4. Dívida Sogro - Marmitas
   436→            Debt(
   437→                name: "Marmitas do Mes",
   438→                amount: 3000,
   439→                creditor: "Sogro",
   440→                status: .pending,
   441→                notes: "Ajuda do sogro para marmitas"
   442→            ),
   443→
   444→            // 5. Dívida Sogro - Cartão C6
   445→            Debt(
   446→                name: "Cartao C6 Namorada",
   447→                amount: 5000,
   448→                creditor: "Sogro",
   449→                status: .pending,
   450→                notes: "Sogro ajudou a pagar cartao C6 da namorada"
   451→            ),
   452→
   453→            // 6. Cheque especial namorada
   454→            Debt(
   455→                name: "Cheque Especial",
   456→                amount: 4000,
   457→                creditor: "Namorada",
   458→                status: .pending,
   459→                notes: "Cheque especial da namorada que usei"
   460→            ),
   461→
   462→            // 7. Empréstimo Santander - Parcelado (Aguardando liberação)
   463→            Debt(
   464→                name: "Emprestimo Santander",
   465→                amount: 41379.56,
   466→                creditor: "Banco Santander",
   467→                interestRate: 1.65,
   468→                status: .pending,
   469→                notes: "Garantia de imovel (alienacao fiduciaria). Total a pagar: R$94.765,45. AGUARDANDO LIBERACAO: Documento final do cartorio fica pronto segunda-feira (29/12/2025). Apos isso, banco tem 5 dias uteis para depositar. Previsao de deposito: ~06/01/2026.",
   470→                isRecurring: true,
   471→                recurringAmount: 796.35,
   472→                totalInstallments: 120,
   473→                paidInstallments: 0
   474→            ),
   475→
   476→            // 8. Cartão Mercado Pago Mãe - VENCIDO
   477→            Debt(
   478→                name: "Cartao Mercado Pago Mae",
   479→                amount: 3749.53,
   480→                creditor: "Mercado Pago",
   481→                dueDate: dateFormatter.date(from: "22/12/2025"),
   482→                status: .overdue,
   483→                notes: "Fatura cartao da mae. Pagamento minimo: R$584,71. Preferencia: quitar tudo de uma vez."
   484→            )
   485→        ]
   486→
   487→        // MARK: Despesas Fixas Mensais
   488→        transactions = [
   489→            // Receitas
   490→            Transaction(
   491→                type: .income,
   492→                amount: 10000,
   493→                description: "Freelance/Servicos",
   494→                category: IncomeCategory.freelance.rawValue,
   495→                isRecurring: true,
   496→                notes: "Media atual apos sair do contrato PJ"
   497→            ),
   498→            Transaction(
   499→                type: .income,
   500→                amount: 1000,
   501→                description: "LOAS Irma",
   502→                category: IncomeCategory.benefit.rawValue,
   503→                isRecurring: true,
   504→                notes: "Auxilio LOAS da irma especial"
   505→            ),
   506→
   507→            // Despesas Fixas
   508→            Transaction(
   509→                type: .expense,
   510→                amount: 4000,
   511→                description: "Aluguel Proprio",
   512→                category: ExpenseCategory.housing.rawValue,
   513→                isRecurring: true,
   514→                notes: "U$750 - com utilities inclusos"
   515→            ),
   516→            Transaction(
   517→                type: .expense,
   518→                amount: 3000,
   519→                description: "Marmitas",
   520→                category: ExpenseCategory.food.rawValue,
   521→                isRecurring: true,
   522→                notes: "2 marmitas/dia para casal"
   523→            ),
   524→            Transaction(
   525→                type: .expense,
   526→                amount: 1300,
   527→                description: "Aluguel Mae",
   528→                category: ExpenseCategory.family.rawValue,
   529→                isRecurring: true
   530→            ),
   531→            Transaction(
   532→                type: .expense,
   533→                amount: 1500,
   534→                description: "Mercado Mae",
   535→                category: ExpenseCategory.family.rawValue,
   536→                isRecurring: true
   537→            ),
   538→            Transaction(
   539→                type: .expense,
   540→                amount: 125,
   541→                description: "Luz Mae",
   542→                category: ExpenseCategory.utilities.rawValue,
   543→                isRecurring: true,
   544→                notes: "Media R$100-150"
   545→            ),
   546→            Transaction(
   547→                type: .expense,
   548→                amount: 65,
   549→                description: "Agua Mae",
   550→                category: ExpenseCategory.utilities.rawValue,
   551→                isRecurring: true,
   552→                notes: "Media R$50-75"
   553→            ),
   554→            Transaction(
   555→                type: .expense,
   556→                amount: 100,
   557→                description: "Internet Mae",
   558→                category: ExpenseCategory.utilities.rawValue,
   559→                isRecurring: true
   560→            ),
   561→            Transaction(
   562→                type: .expense,
   563→                amount: 796.35,
   564→                description: "Parcela Santander",
   565→                category: ExpenseCategory.other.rawValue,
   566→                isRecurring: true,
   567→                notes: "Emprestimo com garantia de imovel - 120 parcelas"
   568→            )
   569→        ]
   570→
   571→        // Perfil atualizado
   572→        profile = FinancialProfile(
   573→            monthlyIncomeAverage: 10000,
   574→            previousContractIncome: 35000,
   575→            contractDuration: "2.5 anos",
   576→            monthsWithoutContract: 2,
   577→            emergencyFund: 0,
   578→            notes: "Contrato PJ B2B anterior de 2.5 anos (35-50k/mes, pico 85k). Saiu ha 2 meses. Cliente quer que volte mas prefere autonomia. Desenvolvendo software proprio."
   579→        )
   580→
   581→        saveData()
   582→    }
   583→}
   584→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import Foundation
import SwiftUI

@MainActor
class DataManager: ObservableObject {
    static let shared = DataManager()

    // MARK: - Published Properties
    @Published var debts: [Debt] = []
    @Published var transactions: [Transaction] = []
    @Published var profile: FinancialProfile = .default
    @Published var expectedIncome: Double = 40000 // Empréstimo Santander
    @Published var leads: [Lead] = []
    @Published var incomeTasks: [IncomeTask] = []
    @Published var incomeGoal: IncomeGoal = .default

    // MARK: - UserDefaults Keys
    private let debtsKey = "neog_finance_debts"
    private let transactionsKey = "neog_finance_transactions"
    private let profileKey = "neog_finance_profile"
    private let leadsKey = "neog_finance_leads"
    private let incomeTasksKey = "neog_finance_income_tasks"
    private let incomeGoalKey = "neog_finance_income_goal"

    // MARK: - Init
    private init() {
        loadData()
        if debts.isEmpty {
            loadInitialData()
        }
    }

    // MARK: - Computed Properties

    var totalDebts: Double {
        debts.filter { $0.status != .paid }.reduce(0) { $0 + $1.amount }
    }

    var totalRecurringDebts: Double {
        debts.filter { $0.isRecurring && $0.status != .paid }
            .reduce(0) { $0 + ($1.recurringAmount ?? 0) }
    }

    var overdueDebts: [Debt] {
        debts.filter { $0.isOverdue }.sorted { $0.urgencyLevel > $1.urgencyLevel }
    }

    var pendingDebts: [Debt] {
        debts.filter { $0.status == .pending && !$0.isOverdue }
            .sorted { ($0.dueDate ?? .distantFuture) < ($1.dueDate ?? .distantFuture) }
    }

    var paidDebts: [Debt] {
        debts.filter { $0.status == .paid }
    }

    var sortedDebtsByUrgency: [Debt] {
        debts.filter { $0.status != .paid }.sorted { $0.urgencyLevel > $1.urgencyLevel }
    }

    var monthlyIncome: Double {
        currentMonthTransactions
            .filter { $0.type == .income }
            .reduce(0) { $0 + $1.amount }
    }

    var monthlyExpenses: Double {
        currentMonthTransactions
            .filter { $0.type == .expense }
            .reduce(0) { $0 + $1.amount }
    }

    var monthlyBalance: Double {
        monthlyIncome - monthlyExpenses
    }

    var currentMonthTransactions: [Transaction] {
        let calendar = Calendar.current
        return transactions.filter {
            calendar.isDate($0.date, equalTo: Date(), toGranularity: .month)
        }
    }

    var recurringExpenses: [Transaction] {
        transactions.filter { $0.type == .expense && $0.isRecurring }
    }

    var totalRecurringExpenses: Double {
        recurringExpenses.reduce(0) { $0 + $1.amount }
    }

    var projectedMonthlyBalance: Double {
        profile.monthlyIncomeAverage - totalRecurringExpenses - totalRecurringDebts
    }

    var balanceAfterLoan: Double {
        expectedIncome - totalDebts
    }

    // MARK: - Leads Computed Properties

    var totalLeadsValue: Double {
        leads.reduce(0) { $0 + $1.value }
    }

    var closedLeadsValue: Double {
        leads.filter { $0.status == .closed }.reduce(0) { $0 + $1.value }
    }

    var pendingLeadsValue: Double {
        leads.filter { $0.status == .proposal || $0.status == .negotiating }.reduce(0) { $0 + $1.value }
    }

    var incomeGoalProgress: Double {
        guard incomeGoal.targetAmount > 0 else { return 0 }
        return min(closedLeadsValue / incomeGoal.targetAmount, 1.0)
    }

    var daysUntilGoalDeadline: Int {
        Calendar.current.dateComponents([.day], from: Date(), to: incomeGoal.deadline).day ?? 0
    }

    // MARK: - CRUD Operations

    func addDebt(_ debt: Debt) {
        debts.append(debt)
        saveData()
    }

    func updateDebt(_ debt: Debt) {
        if let index = debts.firstIndex(where: { $0.id == debt.id }) {
            debts[index] = debt
            saveData()
        }
    }

    func deleteDebt(_ debt: Debt) {
        debts.removeAll { $0.id == debt.id }
        saveData()
    }

    func markDebtAsPaid(_ debt: Debt) {
        if let index = debts.firstIndex(where: { $0.id == debt.id }) {
            debts[index].status = .paid
            saveData()
        }
    }

    func addTransaction(_ transaction: Transaction) {
        transactions.append(transaction)
        saveData()
    }

    func deleteTransaction(_ transaction: Transaction) {
        transactions.removeAll { $0.id == transaction.id }
        saveData()
    }

    // MARK: - Lead Operations

    func addLead(_ lead: Lead) {
        leads.append(lead)
        saveData()
    }

    func updateLead(_ lead: Lead) {
        if let index = leads.firstIndex(where: { $0.id == lead.id }) {
            leads[index] = lead
            saveData()
        }
    }

    func updateLeadStatus(_ lead: Lead, to newStatus: LeadStatus) {
        if let index = leads.firstIndex(where: { $0.id == lead.id }) {
            leads[index].status = newStatus
            saveData()
        }
    }

    func deleteLead(_ lead: Lead) {
        leads.removeAll { $0.id == lead.id }
        saveData()
    }

    // MARK: - Income Task Operations

    func addIncomeTask(_ task: IncomeTask) {
        incomeTasks.append(task)
        saveData()
    }

    func toggleTaskCompletion(_ task: IncomeTask) {
        if let index = incomeTasks.firstIndex(where: { $0.id == task.id }) {
            incomeTasks[index].isCompleted.toggle()
            if incomeTasks[index].isCompleted {
                incomeTasks[index].completedAt = Date()
            } else {
                incomeTasks[index].completedAt = nil
            }
            saveData()
        }
    }

    func deleteIncomeTask(_ task: IncomeTask) {
        incomeTasks.removeAll { $0.id == task.id }
        saveData()
    }

    func resetDailyTasks() {
        // Reset tasks that are daily and were completed yesterday
        let calendar = Calendar.current
        for index in incomeTasks.indices {
            if incomeTasks[index].isDaily,
               let completedAt = incomeTasks[index].completedAt,
               !calendar.isDateInToday(completedAt) {
                incomeTasks[index].isCompleted = false
                incomeTasks[index].completedAt = nil
            }
        }
        saveData()
    }

    func updateIncomeGoal(_ goal: IncomeGoal) {
        incomeGoal = goal
        saveData()
    }

    // MARK: - Persistence

    private func saveData() {
        if let encoded = try? JSONEncoder().encode(debts) {
            UserDefaults.standard.set(encoded, forKey: debtsKey)
        }
        if let encoded = try? JSONEncoder().encode(transactions) {
            UserDefaults.standard.set(encoded, forKey: transactionsKey)
        }
        if let encoded = try? JSONEncoder().encode(profile) {
            UserDefaults.standard.set(encoded, forKey: profileKey)
        }
        if let encoded = try? JSONEncoder().encode(leads) {
            UserDefaults.standard.set(encoded, forKey: leadsKey)
        }
        if let encoded = try? JSONEncoder().encode(incomeTasks) {
            UserDefaults.standard.set(encoded, forKey: incomeTasksKey)
        }
        if let encoded = try? JSONEncoder().encode(incomeGoal) {
            UserDefaults.standard.set(encoded, forKey: incomeGoalKey)
        }
    }

    private func loadData() {
        if let data = UserDefaults.standard.data(forKey: debtsKey),
           let decoded = try? JSONDecoder().decode([Debt].self, from: data) {
            debts = decoded
        }
        if let data = UserDefaults.standard.data(forKey: transactionsKey),
           let decoded = try? JSONDecoder().decode([Transaction].self, from: data) {
            transactions = decoded
        }
        if let data = UserDefaults.standard.data(forKey: profileKey),
           let decoded = try? JSONDecoder().decode(FinancialProfile.self, from: data) {
            profile = decoded
        }
        if let data = UserDefaults.standard.data(forKey: leadsKey),
           let decoded = try? JSONDecoder().decode([Lead].self, from: data) {
            leads = decoded
        }
        if let data = UserDefaults.standard.data(forKey: incomeTasksKey),
           let decoded = try? JSONDecoder().decode([IncomeTask].self, from: data) {
            incomeTasks = decoded
        }
        if let data = UserDefaults.standard.data(forKey: incomeGoalKey),
           let decoded = try? JSONDecoder().decode(IncomeGoal.self, from: data) {
            incomeGoal = decoded
        }

        // Add Mercado Pago debt if it doesn't exist
        addMercadoPagoDebtIfNeeded()

        // Reset daily tasks if needed
        resetDailyTasks()

        // Load default income tasks if empty
        if incomeTasks.isEmpty {
            loadDefaultIncomeTasks()
        }

        // Add test lead if needed
        addBancoMasterLeadIfNeeded()
    }

    private func addBancoMasterLeadIfNeeded() {
        // Add Luiz Mourão as Connector
        let connectorName = "Luiz Mourao"
        if !leads.contains(where: { $0.name == connectorName }) {
            let luizConnector = Lead(
                name: connectorName,
                service: "Conector de Clientes",
                value: 0, // Connector doesn't pay directly
                status: .lost, // EM PAUSA - Crise pessoal grave (Dez/2025)
                type: .connector,
                notes: "⚠ EM PAUSA (Dez/2025): Crise pessoal grave - problemas de saude (cardiaco), luto (avo), questoes pessoais. Banco Master sob investigacao PF. Reavaliar em 30-60 dias. | Historico: Conector principal 2.5 anos, media R$35k/mes. Intermediario com Daniel Vorcaro (CEO Banco Master).",
                contactInfo: "WhatsApp direto",
                source: "Networking",
                potentialMonthlyValue: 35000,
                connectedClients: ["Daniel Vorcaro", "Banco Master"]
            )
            leads.append(luizConnector)
        }

        // Update existing Luiz entry if needed
        if let index = leads.firstIndex(where: { $0.name == connectorName && $0.status != .lost }) {
            leads[index].status = .lost
            leads[index].notes = "⚠ EM PAUSA (Dez/2025): Crise pessoal grave - problemas de saude (cardiaco), luto (avo), questoes pessoais. Banco Master sob investigacao PF. Reavaliar em 30-60 dias. | Historico: Conector principal 2.5 anos, media R$35k/mes. Intermediario com Daniel Vorcaro (CEO Banco Master)."
            saveData()
        }

        // Add Banco Master as Direct Lead (via Luiz)
        let leadName = "Banco Master"
        if !leads.contains(where: { $0.name == leadName }) {
            let bancoMasterLead = Lead(
                name: leadName,
                service: "Consultoria Tech / Desenvolvimento",
                value: 35000,
                status: .lost, // EM PAUSA - Investigação PF
                type: .direct,
                notes: "⚠ EM PAUSA (Dez/2025): Banco Master sob investigacao da PF. Conector Luiz em crise pessoal. Reavaliar em 30-60 dias. | Historico: Cliente via Luiz Mourao. CEO: Daniel Vorcaro. 2.5 anos de contrato, R$35-50k/mes (pico R$85k).",
                contactInfo: "Via Luiz Mourao",
                source: "Conector: Luiz Mourao"
            )
            leads.append(bancoMasterLead)
        }

        // Update existing Banco Master entry if needed
        if let index = leads.firstIndex(where: { $0.name == leadName && $0.status != .lost }) {
            leads[index].status = .lost
            leads[index].notes = "⚠ EM PAUSA (Dez/2025): Banco Master sob investigacao da PF. Conector Luiz em crise pessoal. Reavaliar em 30-60 dias. | Historico: Cliente via Luiz Mourao. CEO: Daniel Vorcaro. 2.5 anos de contrato, R$35-50k/mes (pico R$85k)."
        }

        saveData()
    }

    private func loadDefaultIncomeTasks() {
        incomeTasks = [
            IncomeTask(title: "Listar 10 contatos potenciais", subtitle: "Clientes antigos + novos", tag: "Prioritario", tagColor: "red", isDaily: false),
            IncomeTask(title: "Criar post para LinkedIn", subtitle: "Sobre disponibilidade", tag: "Marketing", tagColor: "blue", isDaily: false),
            IncomeTask(title: "Atualizar perfil em marketplaces", subtitle: "Workana, 99freelas", tag: "Marketing", tagColor: "blue", isDaily: false),
            IncomeTask(title: "Enviar 5 mensagens de prospeccao", subtitle: "WhatsApp ou email", tag: "Vendas", tagColor: "green", isDaily: true),
            IncomeTask(title: "Fazer follow-up com leads", subtitle: "Responder interessados", tag: "Vendas", tagColor: "green", isDaily: true)
        ]
        saveData()
    }

    private func addMercadoPagoDebtIfNeeded() {
        let debtName = "Cartao Mercado Pago Mae"
        if !debts.contains(where: { $0.name == debtName }) {
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "dd/MM/yyyy"

            let mercadoPagoDebt = Debt(
                name: debtName,
                amount: 3749.53,
                creditor: "Mercado Pago",
                dueDate: dateFormatter.date(from: "22/12/2025"),
                status: .overdue,
                notes: "Fatura cartao da mae. Pagamento minimo: R$584,71. Preferencia: quitar tudo de uma vez."
            )
            debts.append(mercadoPagoDebt)
            saveData()
        }

        // Update Santander loan notes if needed
        updateSantanderLoanNotes()
    }

    private func updateSantanderLoanNotes() {
        let updatedNotes = "Garantia de imovel (alienacao fiduciaria). Total a pagar: R$94.765,45. AGUARDANDO LIBERACAO: Documento final do cartorio fica pronto segunda-feira (29/12/2025). Apos isso, banco tem 5 dias uteis para depositar. Previsao de deposito: ~06/01/2026."

        if let index = debts.firstIndex(where: { $0.name == "Emprestimo Santander" }) {
            if debts[index].notes != updatedNotes {
                debts[index].notes = updatedNotes
                saveData()
            }
        }
    }

    func resetToInitialData() {
        UserDefaults.standard.removeObject(forKey: debtsKey)
        UserDefaults.standard.removeObject(forKey: transactionsKey)
        debts = []
        transactions = []
        loadInitialData()
    }

    // MARK: - Initial Data (User's Financial Profile)

    private func loadInitialData() {
        let calendar = Calendar.current
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "dd/MM/yyyy"

        // MARK: Dívidas Urgentes
        debts = [
            // 1. Empréstimo Nubank - VENCIDO E URGENTE
            Debt(
                name: "Emprestimo Nubank - URGENTE",
                amount: 6000,
                creditor: "Nubank",
                dueDate: dateFormatter.date(from: "20/12/2024"),
                interestRate: 10,
                status: .overdue,
                notes: "PRIORIDADE MAXIMA! Venceu em 20/12/2024. Aguardando emprestimo Santander para quitar. Ligar para negociar juros."
            ),

            // 2. Aluguel próprio
            Debt(
                name: "Aluguel Proprio",
                amount: 4000,
                creditor: "Proprietario",
                dueDate: dateFormatter.date(from: "05/01/2026"),
                status: .pending,
                notes: "U$750 - inclui agua, luz, internet"
            ),

            // 3. Aluguel mãe
            Debt(
                name: "Aluguel Mae",
                amount: 1300,
                creditor: "Proprietario Mae",
                dueDate: dateFormatter.date(from: "10/01/2026"),
                status: .pending,
                notes: "Aluguel da mae"
            ),

            // 4. Dívida Sogro - Marmitas
            Debt(
                name: "Marmitas do Mes",
                amount: 3000,
                creditor: "Sogro",
                status: .pending,
                notes: "Ajuda do sogro para marmitas"
            ),

            // 5. Dívida Sogro - Cartão C6
            Debt(
                name: "Cartao C6 Namorada",
                amount: 5000,
                creditor: "Sogro",
                status: .pending,
                notes: "Sogro ajudou a pagar cartao C6 da namorada"
            ),

            // 6. Cheque especial namorada
            Debt(
                name: "Cheque Especial",
                amount: 4000,
                creditor: "Namorada",
                status: .pending,
                notes: "Cheque especial da namorada que usei"
            ),

            // 7. Empréstimo Santander - Parcelado (Aguardando liberação)
            Debt(
                name: "Emprestimo Santander",
                amount: 41379.56,
                creditor: "Banco Santander",
                interestRate: 1.65,
                status: .pending,
                notes: "Garantia de imovel (alienacao fiduciaria). Total a pagar: R$94.765,45. AGUARDANDO LIBERACAO: Documento final do cartorio fica pronto segunda-feira (29/12/2025). Apos isso, banco tem 5 dias uteis para depositar. Previsao de deposito: ~06/01/2026.",
                isRecurring: true,
                recurringAmount: 796.35,
                totalInstallments: 120,
                paidInstallments: 0
            ),

            // 8. Cartão Mercado Pago Mãe - VENCIDO
            Debt(
                name: "Cartao Mercado Pago Mae",
                amount: 3749.53,
                creditor: "Mercado Pago",
                dueDate: dateFormatter.date(from: "22/12/2025"),
                status: .overdue,
                notes: "Fatura cartao da mae. Pagamento minimo: R$584,71. Preferencia: quitar tudo de uma vez."
            )
        ]

        // MARK: Despesas Fixas Mensais
        transactions = [
            // Receitas
            Transaction(
                type: .income,
                amount: 10000,
                description: "Freelance/Servicos",
                category: IncomeCategory.freelance.rawValue,
                isRecurring: true,
                notes: "Media atual apos sair do contrato PJ"
            ),
            Transaction(
                type: .income,
                amount: 1000,
                description: "LOAS Irma",
                category: IncomeCategory.benefit.rawValue,
                isRecurring: true,
                notes: "Auxilio LOAS da irma especial"
            ),

            // Despesas Fixas
            Transaction(
                type: .expense,
                amount: 4000,
                description: "Aluguel Proprio",
                category: ExpenseCategory.housing.rawValue,
                isRecurring: true,
                notes: "U$750 - com utilities inclusos"
            ),
            Transaction(
                type: .expense,
                amount: 3000,
                description: "Marmitas",
                category: ExpenseCategory.food.rawValue,
                isRecurring: true,
                notes: "2 marmitas/dia para casal"
            ),
            Transaction(
                type: .expense,
                amount: 1300,
                description: "Aluguel Mae",
                category: ExpenseCategory.family.rawValue,
                isRecurring: true
            ),
            Transaction(
                type: .expense,
                amount: 1500,
                description: "Mercado Mae",
                category: ExpenseCategory.family.rawValue,
                isRecurring: true
            ),
            Transaction(
                type: .expense,
                amount: 125,
                description: "Luz Mae",
                category: ExpenseCategory.utilities.rawValue,
                isRecurring: true,
                notes: "Media R$100-150"
            ),
            Transaction(
                type: .expense,
                amount: 65,
                description: "Agua Mae",
                category: ExpenseCategory.utilities.rawValue,
                isRecurring: true,
                notes: "Media R$50-75"
            ),
            Transaction(
                type: .expense,
                amount: 100,
                description: "Internet Mae",
                category: ExpenseCategory.utilities.rawValue,
                isRecurring: true
            ),
            Transaction(
                type: .expense,
                amount: 796.35,
                description: "Parcela Santander",
                category: ExpenseCategory.other.rawValue,
                isRecurring: true,
                notes: "Emprestimo com garantia de imovel - 120 parcelas"
            )
        ]

        // Perfil atualizado
        profile = FinancialProfile(
            monthlyIncomeAverage: 10000,
            previousContractIncome: 35000,
            contractDuration: "2.5 anos",
            monthsWithoutContract: 2,
            emergencyFund: 0,
            notes: "Contrato PJ B2B anterior de 2.5 anos (35-50k/mes, pico 85k). Saiu ha 2 meses. Cliente quer que volte mas prefere autonomia. Desenvolvendo software proprio."
        )

        saveData()
    }
}


Now let me look at some key views from existing macOS apps to understand the patterns: