Design a comprehensive implementation plan for "MassGainer2026" - a macOS + iOS (Mac Catalyst) app for muscle building focused on ectomorphs.

## User Profile
- Ectomorph body type
- Current weight: 64kg
- Height: 1.80m
- Goal: Gain muscle mass in 2026

## Requirements
1. **Platform:** iOS app with Mac Catalyst support (single codebase)
2. **Complexity:** Simple - daily checklist approach
3. **Modules:** Workout + Diet + Sleep + Supplements (complete tracking)
4. **Training Plan:** Pre-defined program for ectomorphs (3-4x/week, compound movements)

## Existing Patterns in Workspace (from exploration)
The user has several iOS apps with proven patterns:

1. **ProductivityHub-iOS:**
   - MVVM with @Observable (iOS 17+)
   - UserDefaults with 3-layer backup system
   - Singleton DataManager
   - 100% SwiftUI

2. **HabitTracker2026:**
   - SwiftData for persistence
   - CloudKit sync
   - iOS 18+ Liquid Glass design
   - Streak tracking algorithm

3. **200FlexoesDiarias:**
   - Simple fitness tracker
   - Daily reminder notifications
   - Streak milestones (7, 30, 100, 365 days)
   - Progress circles
   - Haptic feedback

## Key Features to Design

### 1. Workout Module
- Pre-defined ectomorph workout program (PPL or Upper/Lower split)
- Simple checklist: "Did you train today?"
- Which muscle group/day type
- Rest day detection

### 2. Diet Module
- Caloric goal for ectomorph (64kg → target ~2,800-3,200 cal/day)
- Simple checklist: "Did you eat enough today?"
- Meal tracking (5-6 meals for mass gain)
- Protein target (1.6-2.2g/kg = ~100-140g/day)

### 3. Sleep Module
- Target: 7-9 hours for recovery
- Simple tracking: hours slept
- Sleep quality rating (1-5)

### 4. Supplements Module
- Pre-defined stack for ectomorphs:
  - Creatine (5g daily)
  - Whey Protein (post-workout)
  - Multivitamin
  - Optional: Mass Gainer
- Checklist with reminders

### 5. Progress Tracking
- Weight tracking (weekly)
- Photo progress (optional, monthly)
- Streak tracking (consecutive training days)
- Body metrics (measurements optional)

### 6. Notifications & Reminders
- Morning: "What's today's workout?"
- Meal times: "Time to eat"
- Supplement reminders
- Evening: "Log your day"
- Weekly: "Weigh-in reminder"

## Technical Requirements
- iOS 17+ minimum (for @Observable, modern SwiftUI)
- SwiftData for persistence (modern approach)
- CloudKit for optional sync
- Local notifications
- Mac Catalyst support
- Dark mode

## Deliverables Expected
1. Project structure
2. Data models (SwiftData)
3. Services architecture
4. View hierarchy
5. Pre-defined workout program content
6. Notification scheduling strategy
7. Step-by-step implementation order

Please create a detailed implementation plan considering these requirements and the existing patterns in the workspace.


I'll explore the existing iOS apps in the workspace to understand the patterns and architecture used, then create a comprehensive implementation plan for MassGainer2026.


Bash

List iOS apps directory


total 64
drwxr-xr-x@ 38 neog  staff   1216 Dec 23 06:52 .
drwxr-xr-x@  5 neog  staff    160 Dec 21 21:47 ..
-rw-r--r--@  1 neog  staff  30724 Dec 21 22:38 .DS_Store
drwxr-xr-x@ 18 neog  staff    576 Dec 22 05:21 AI-KeywordMonitor
drwxr-xr-x@ 15 neog  staff    480 Dec 21 23:57 BIZ-BusinessPlan
drwxr-xr-x@  4 neog  staff    128 Dec 10 16:01 BIZ-NEOGBusiness
drwxr-xr-x@  6 neog  staff    192 Dec 15 15:48 BIZ-RevenueFlow30D
drwxr-xr-x@ 18 neog  staff    576 Dec 22 05:21 EDU-17Licoes
drwxr-xr-x@  8 neog  staff    256 Dec 21 23:41 EDU-BibliaEstudo
drwxr-xr-x@ 10 neog  staff    320 Dec 22 05:21 EDU-DailyVirtue
drwxr-xr-x@ 14 neog  staff    448 Dec 21 20:52 EMAIL-EmailAnalyzer
drwxr-xr-x@ 24 neog  staff    768 Dec 21 22:56 EMAIL-GmailAI
drwxr-xr-x@ 16 neog  staff    512 Dec 23 06:38 FIN-CashFlow
drwxr-xr-x@ 19 neog  staff    608 Dec 21 23:27 FIN-MeusFIIs
drwxr-xr-x@  2 neog  staff     64 Dec 23 06:52 ImageClassifier-iOS
drwxr-xr-x@  7 neog  staff    224 Dec 18 12:53 LOC-AroundMe
drwxr-xr-x@  6 neog  staff    192 Dec 20 23:10 LOC-CityExplorer
drwxr-xr-x@  9 neog  staff    288 Dec 23 05:39 LoanTracker-iOS
drwxr-xr-x@ 12 neog  staff    384 Dec 18 22:51 MEDIA-ObsidianViewer
drwxr-xr-x@ 12 neog  staff    384 Dec 21 16:06 MEDIA-YouTubeAudio
drwxr-xr-x@  6 neog  staff    192 Dec 13 12:56 MEDIA-YouTubeTranscripts
drwxr-xr-x@ 18 neog  staff    576 Dec 18 16:25 PROD-96Blocks
drwxr-xr-x@ 16 neog  staff    512 Dec 23 04:54 PROD-ActionPlans
drwxr-xr-x@ 10 neog  staff    320 Dec 21 20:52 PROD-HabitTracker2026
drwxr-xr-x@  7 neog  staff    224 Dec 23 02:07 PROD-LuizPlan
drwxr-xr-x@ 15 neog  staff    480 Dec 23 04:22 PROD-MoLove
drwxr-xr-x@  6 neog  staff    192 Dec 22 00:09 PROD-Planner2026
drwxr-xr-x@ 15 neog  staff    480 Dec 23 07:04 PROD-ProactiveAI
drwxr-xr-x@ 61 neog  staff   1952 Dec 21 20:52 PROD-ProductivityHub
drwxr-xr-x@ 16 neog  staff    512 Dec 23 04:29 PROD-ThomApp
drwxr-xr-x@ 12 neog  staff    384 Dec 10 17:18 SOC-NEOGListen
drwxr-xr-x@  7 neog  staff    224 Dec  6 20:36 SOC-XNEOG
drwxr-xr-x@ 10 neog  staff    320 Dec 19 20:06 SYS-KortexOS
drwxr-xr-x@ 18 neog  staff    576 Dec 21 16:04 TOOL-CleanShield
drwxr-xr-x@  6 neog  staff    192 Dec 10 22:06 TOOL-PaymentGateway
drwxr-xr-x@  5 neog  staff    160 Dec 21 20:52 TOOL-WorkspaceGuide
drwxr-xr-x@ 23 neog  staff    736 Dec 13 14:57 TOOL-WorkspaceManager
drwxr-xr-x@ 13 neog  staff    416 Dec 23 04:29 VectorCRM-iOS


No files found


Let me explore the most relevant apps for patterns - ProductivityHub, HabitTracker2026, and 200FlexoesDiarias:


find /Users/neog/Apps/iOS/PROD-ProductivityHub -name "*.swift" -type f 2>/dev/null | head -30

Find Swift files in ProductivityHub


find /Users/neog/Apps/iOS/PROD-HabitTracker2026 -name "*.swift" -type f 2>/dev/null

Find Swift files in HabitTracker2026


find /Users/neog/Projects -name "*200*" -o -name "*Flex*" 2>/dev/null | head -10

Find 200FlexoesDiarias project


TodoWrite

Explore ProductivityHub architecture and patterns

Exploring ProductivityHub architecture and patterns

Explore HabitTracker2026 SwiftData patterns

Exploring HabitTracker2026 SwiftData patterns

Explore 200FlexoesDiarias fitness tracking patterns

Exploring 200FlexoesDiarias fitness tracking patterns

Design MassGainer2026 data models

Design project structure and architecture

Designing project structure and architecture

Create comprehensive implementation plan

Creating comprehensive implementation plan


Todos have been modified successfully. Ensure that you continue to use the todo list to track your progress. Please proceed with the current tasks if applicable

Explore ProductivityHub architecture and patterns

Exploring ProductivityHub architecture and patterns

Explore HabitTracker2026 SwiftData patterns

Exploring HabitTracker2026 SwiftData patterns

Explore 200FlexoesDiarias fitness tracking patterns

Exploring 200FlexoesDiarias fitness tracking patterns

Design MassGainer2026 data models

Design project structure and architecture

Designing project structure and architecture

Create comprehensive implementation plan

Creating comprehensive implementation plan


     1→//
     2→//  DataManager.swift
     3→//  ProductivityHub-iOS
     4→//
     5→//  Unified data manager with 3-layer backup system (from ToDoMax)
     6→//  TODO: Consider migrating to SwiftData for better performance and automatic persistence
     7→//  See: https://developer.apple.com/documentation/swiftdata
     8→//
     9→
    10→import Foundation
    11→import Combine
    12→
    13→@MainActor
    14→class DataManager: ObservableObject {
    15→    static let shared = DataManager()
    16→
    17→    // Logger instance
    18→    private let logger = Logger.dataManager
    19→
    20→    // Track if data has been loaded to prevent duplicate loads
    21→    private var isDataLoaded = false
    22→
    23→    // MARK: - Debounce System
    24→    // Debounce saves to avoid excessive disk writes during rapid operations
    25→    private var saveDebounceTask: _Concurrency.Task<Void, Never>?
    26→    private let saveDebounceDelay: UInt64 = 500_000_000 // 500ms in nanoseconds
    27→    private var pendingSaves: Set<String> = [] // Track which data types need saving
    28→
    29→    // MARK: - Published Properties
    30→    @Published var tasks: [Task] = []
    31→    @Published var workSessions: [WorkSession] = []
    32→    @Published var journalEntries: [JournalEntry] = []
    33→    @Published var tags: [Tag] = []
    34→    @Published var templates: [Template] = []
    35→
    36→    // MARK: - UserDefaults Keys
    37→    private let tasksKey = "ProductivityHub_Tasks"
    38→    private let tasksBackup1Key = "ProductivityHub_Tasks_backup1"
    39→    private let tasksBackup2Key = "ProductivityHub_Tasks_backup2"
    40→
    41→    private let sessionsKey = "ProductivityHub_Sessions"
    42→    private let sessionsBackup1Key = "ProductivityHub_Sessions_backup1"
    43→    private let sessionsBackup2Key = "ProductivityHub_Sessions_backup2"
    44→
    45→    private let journalKey = "ProductivityHub_Journal"
    46→    private let journalBackup1Key = "ProductivityHub_Journal_backup1"
    47→    private let journalBackup2Key = "ProductivityHub_Journal_backup2"
    48→
    49→    private let tagsKey = "ProductivityHub_Tags"
    50→    private let tagsBackup1Key = "ProductivityHub_Tags_backup1"
    51→    private let tagsBackup2Key = "ProductivityHub_Tags_backup2"
    52→
    53→    private let templatesKey = "ProductivityHub_Templates"
    54→    private let templatesBackup1Key = "ProductivityHub_Templates_backup1"
    55→    private let templatesBackup2Key = "ProductivityHub_Templates_backup2"
    56→
    57→    // MARK: - Initialization
    58→    private init() {
    59→        loadAllData()
    60→    }
    61→
    62→    // MARK: - Load All Data
    63→    func loadAllData() {
    64→        // Prevent duplicate loading
    65→        guard !isDataLoaded else {
    66→            logger.debug("Data already loaded, skipping duplicate load", category: .load)
    67→            return
    68→        }
    69→
    70→        tasks = loadWithBackup(key: tasksKey, backup1: tasksBackup1Key, backup2: tasksBackup2Key) ?? []
    71→        workSessions = loadWithBackup(key: sessionsKey, backup1: sessionsBackup1Key, backup2: sessionsBackup2Key) ?? []
    72→        journalEntries = loadWithBackup(key: journalKey, backup1: journalBackup1Key, backup2: journalBackup2Key) ?? []
    73→        tags = loadWithBackup(key: tagsKey, backup1: tagsBackup1Key, backup2: tagsBackup2Key) ?? Tag.systemTags
    74→        templates = loadWithBackup(key: templatesKey, backup1: templatesBackup1Key, backup2: templatesBackup2Key) ?? Template.systemTemplates
    75→
    76→        // Populate sample data on first launch
    77→        if tasks.isEmpty && workSessions.isEmpty && journalEntries.isEmpty {
    78→            logger.info("First launch detected - populating sample data", category: .lifecycle)
    79→            populateSampleData()
    80→        }
    81→
    82→        isDataLoaded = true
    83→
    84→        logger.info("DataManager loaded successfully", category: .load, context: [
    85→            "tasks": tasks.count,
    86→            "workSessions": workSessions.count,
    87→            "journalEntries": journalEntries.count,
    88→            "tags": tags.count,
    89→            "templates": templates.count
    90→        ])
    91→    }
    92→
    93→    // MARK: - Save All Data
    94→    func saveAllData() {
    95→        saveWithBackup(data: tasks, key: tasksKey, backup1: tasksBackup1Key, backup2: tasksBackup2Key)
    96→        saveWithBackup(data: workSessions, key: sessionsKey, backup1: sessionsBackup1Key, backup2: sessionsBackup2Key)
    97→        saveWithBackup(data: journalEntries, key: journalKey, backup1: journalBackup1Key, backup2: journalBackup2Key)
    98→        saveWithBackup(data: tags, key: tagsKey, backup1: tagsBackup1Key, backup2: tagsBackup2Key)
    99→        saveWithBackup(data: templates, key: templatesKey, backup1: templatesBackup1Key, backup2: templatesBackup2Key)
   100→
   101→        logger.info("All data saved successfully", category: .save)
   102→
   103→        // Trigger CloudKit sync if enabled
   104→        triggerCloudSync()
   105→    }
   106→
   107→    // MARK: - CloudKit Sync Integration
   108→    private func triggerCloudSync() {
   109→        let cloudKitService = CloudKitSyncService.shared
   110→        guard cloudKitService.isSyncEnabled else { return }
   111→
   112→        // Debounced sync - CloudKitSyncService handles the debouncing
   113→        _Concurrency.Task {
   114→            await cloudKitService.syncAllData(dataManager: self)
   115→        }
   116→    }
   117→
   118→    // MARK: - 3-Layer Backup System (from ToDoMax)
   119→    private func loadWithBackup<T: Decodable>(key: String, backup1: String, backup2: String) -> T? {
   120→        // Try primary key
   121→        if let data = UserDefaults.standard.data(forKey: key),
   122→           let decoded = try? JSONDecoder().decode(T.self, from: data) {
   123→            logger.debug("Loaded from primary key", category: .load, context: ["key": key])
   124→            return decoded
   125→        }
   126→
   127→        // Try backup 1
   128→        if let data = UserDefaults.standard.data(forKey: backup1),
   129→           let decoded = try? JSONDecoder().decode(T.self, from: data) {
   130→            logger.warning("Primary key corrupted, loaded from backup1", category: .backup, context: ["key": backup1])
   131→            // Restore to primary
   132→            UserDefaults.standard.set(data, forKey: key)
   133→            return decoded
   134→        }
   135→
   136→        // Try backup 2
   137→        if let data = UserDefaults.standard.data(forKey: backup2),
   138→           let decoded = try? JSONDecoder().decode(T.self, from: data) {
   139→            logger.warning("Primary and backup1 corrupted, loaded from backup2", category: .backup, context: ["key": backup2])
   140→            // Restore to primary and backup1
   141→            UserDefaults.standard.set(data, forKey: key)
   142→            UserDefaults.standard.set(data, forKey: backup1)
   143→            return decoded
   144→        }
   145→
   146→        logger.info("No existing data found for key (first launch)", category: .load, context: ["key": key])
   147→        return nil
   148→    }
   149→
   150→    // MARK: - Debounced Save Methods
   151→
   152→    /// Schedule a debounced save for a specific data type
   153→    private func scheduleDebouncedSave(for dataType: String) {
   154→        pendingSaves.insert(dataType)
   155→
   156→        // Cancel any existing debounce task
   157→        saveDebounceTask?.cancel()
   158→
   159→        // Schedule new debounce task
   160→        saveDebounceTask = _Concurrency.Task { [weak self] in
   161→            do {
   162→                try await _Concurrency.Task.sleep(nanoseconds: self?.saveDebounceDelay ?? 500_000_000)
   163→                await self?.executePendingSaves()
   164→            } catch {
   165→                // Task was cancelled - new save scheduled
   166→            }
   167→        }
   168→    }
   169→
   170→    /// Execute all pending saves
   171→    private func executePendingSaves() {
   172→        guard !pendingSaves.isEmpty else { return }
   173→
   174→        let savesToExecute = pendingSaves
   175→        pendingSaves.removeAll()
   176→
   177→        for dataType in savesToExecute {
   178→            switch dataType {
   179→            case "tasks":
   180→                saveWithBackupImmediate(data: tasks, key: tasksKey, backup1: tasksBackup1Key, backup2: tasksBackup2Key)
   181→            case "sessions":
   182→                saveWithBackupImmediate(data: workSessions, key: sessionsKey, backup1: sessionsBackup1Key, backup2: sessionsBackup2Key)
   183→            case "journal":
   184→                saveWithBackupImmediate(data: journalEntries, key: journalKey, backup1: journalBackup1Key, backup2: journalBackup2Key)
   185→            case "tags":
   186→                saveWithBackupImmediate(data: tags, key: tagsKey, backup1: tagsBackup1Key, backup2: tagsBackup2Key)
   187→            case "templates":
   188→                saveWithBackupImmediate(data: templates, key: templatesKey, backup1: templatesBackup1Key, backup2: templatesBackup2Key)
   189→            default:
   190→                break
   191→            }
   192→        }
   193→
   194→        logger.debug("Debounced save executed", category: .save, context: ["types": savesToExecute.joined(separator: ", ")])
   195→
   196→        // Trigger CloudKit sync after debounced save
   197→        triggerCloudSync()
   198→    }
   199→
   200→    /// Force immediate save of all pending data (e.g., when app goes to background)
   201→    func flushPendingSaves() {
   202→        saveDebounceTask?.cancel()
   203→        saveDebounceTask = nil
   204→        executePendingSaves()
   205→    }
   206→
   207→    private func saveWithBackup<T: Codable>(data: T, key: String, backup1: String, backup2: String) {
   208→        // Use immediate save for backwards compatibility
   209→        saveWithBackupImmediate(data: data, key: key, backup1: backup1, backup2: backup2)
   210→    }
   211→
   212→    private func saveWithBackupImmediate<T: Codable>(data: T, key: String, backup1: String, backup2: String) {
   213→        // Attempt to encode data
   214→        let encoded: Data
   215→        do {
   216→            encoded = try JSONEncoder().encode(data)
   217→        } catch {
   218→            logger.error("Failed to encode data - attempting recovery from backup", category: .save, context: [
   219→                "key": key,
   220→                "error": error.localizedDescription
   221→            ])
   222→            // Don't corrupt existing backups - just return and keep current data
   223→            return
   224→        }
   225→
   226→        // Validate encoded data can be decoded (integrity check)
   227→        do {
   228→            _ = try JSONDecoder().decode(type(of: data).self, from: encoded)
   229→        } catch {
   230→            logger.critical("Data validation failed - corrupted data detected, preserving backups", category: .save, context: [
   231→                "key": key,
   232→                "error": error.localizedDescription
   233→            ])
   234→            // Data is corrupted - don't save to preserve existing backups
   235→            return
   236→        }
   237→
   238→        // Cascade backups: current → backup1, backup1 → backup2
   239→        // Only cascade if we're sure new data is valid
   240→        if let currentData = UserDefaults.standard.data(forKey: key) {
   241→            // Verify current data is valid before demoting to backup
   242→            if (try? JSONDecoder().decode(type(of: data).self, from: currentData)) != nil {
   243→                if let backup1Data = UserDefaults.standard.data(forKey: backup1) {
   244→                    UserDefaults.standard.set(backup1Data, forKey: backup2)
   245→                }
   246→                UserDefaults.standard.set(currentData, forKey: backup1)
   247→            } else {
   248→                logger.warning("Current data corrupted, not cascading to backup", category: .backup, context: ["key": key])
   249→            }
   250→        }
   251→
   252→        // Save new validated data
   253→        UserDefaults.standard.set(encoded, forKey: key)
   254→        logger.debug("Saved with 3-layer backup", category: .save, context: ["key": key, "size": "\(encoded.count) bytes"])
   255→    }
   256→
   257→    // MARK: - Task Operations
   258→    func addTask(_ task: Task) {
   259→        tasks.append(task)
   260→        scheduleDebouncedSave(for: "tasks")
   261→    }
   262→
   263→    func updateTask(_ task: Task) {
   264→        if let index = tasks.firstIndex(where: { $0.id == task.id }) {
   265→            tasks[index] = task
   266→            scheduleDebouncedSave(for: "tasks")
   267→        }
   268→    }
   269→
   270→    func deleteTask(_ task: Task) {
   271→        tasks.removeAll { $0.id == task.id }
   272→        scheduleDebouncedSave(for: "tasks")
   273→    }
   274→
   275→    func toggleTaskCompletion(_ task: Task) {
   276→        if let index = tasks.firstIndex(where: { $0.id == task.id }) {
   277→            tasks[index].isCompleted.toggle()
   278→            tasks[index].completedAt = tasks[index].isCompleted ? Date() : nil
   279→
   280→            // Haptic feedback
   281→            if tasks[index].isCompleted {
   282→                HapticManager.taskCompleted()
   283→            } else {
   284→                HapticManager.impact(.light)
   285→            }
   286→
   287→            scheduleDebouncedSave(for: "tasks")
   288→        }
   289→    }
   290→
   291→    // MARK: - WorkSession Operations
   292→    func addWorkSession(_ session: WorkSession) {
   293→        workSessions.append(session)
   294→        HapticManager.entryAdded()
   295→        scheduleDebouncedSave(for: "sessions")
   296→    }
   297→
   298→    func updateWorkSession(_ session: WorkSession) {
   299→        if let index = workSessions.firstIndex(where: { $0.id == session.id }) {
   300→            workSessions[index] = session
   301→            scheduleDebouncedSave(for: "sessions")
   302→        }
   303→    }
   304→
   305→    func deleteWorkSession(_ session: WorkSession) {
   306→        workSessions.removeAll { $0.id == session.id }
   307→        scheduleDebouncedSave(for: "sessions")
   308→    }
   309→
   310→    // MARK: - JournalEntry Operations
   311→    func addJournalEntry(_ entry: JournalEntry) {
   312→        journalEntries.append(entry)
   313→        scheduleDebouncedSave(for: "journal")
   314→    }
   315→
   316→    func updateJournalEntry(_ entry: JournalEntry) {
   317→        if let index = journalEntries.firstIndex(where: { $0.id == entry.id }) {
   318→            var updatedEntry = entry
   319→            updatedEntry.modifiedAt = Date()
   320→            journalEntries[index] = updatedEntry
   321→            scheduleDebouncedSave(for: "journal")
   322→        }
   323→    }
   324→
   325→    func deleteJournalEntry(_ entry: JournalEntry) {
   326→        journalEntries.removeAll { $0.id == entry.id }
   327→        scheduleDebouncedSave(for: "journal")
   328→    }
   329→
   330→    // MARK: - Tag Operations
   331→    func addTag(_ tag: Tag) {
   332→        tags.append(tag)
   333→        scheduleDebouncedSave(for: "tags")
   334→    }
   335→
   336→    func updateTag(_ tag: Tag) {
   337→        if let index = tags.firstIndex(where: { $0.id == tag.id }) {
   338→            tags[index] = tag
   339→            scheduleDebouncedSave(for: "tags")
   340→        }
   341→    }
   342→
   343→    func deleteTag(_ tag: Tag) {
   344→        tags.removeAll { $0.id == tag.id }
   345→        scheduleDebouncedSave(for: "tags")
   346→    }
   347→
   348→    // MARK: - Template Operations
   349→    func addTemplate(_ template: Template) {
   350→        templates.append(template)
   351→        scheduleDebouncedSave(for: "templates")
   352→    }
   353→
   354→    func updateTemplate(_ template: Template) {
   355→        if let index = templates.firstIndex(where: { $0.id == template.id }) {
   356→            templates[index] = template
   357→            scheduleDebouncedSave(for: "templates")
   358→        }
   359→    }
   360→
   361→    func deleteTemplate(_ template: Template) {
   362→        templates.removeAll { $0.id == template.id }
   363→        scheduleDebouncedSave(for: "templates")
   364→    }
   365→
   366→    // MARK: - Statistics & Insights
   367→    func getTaskStatistics() -> TaskStatistics {
   368→        let completed = tasks.filter { $0.isCompleted }.count
   369→        let pending = tasks.count - completed
   370→        let overdue = tasks.filter { $0.isOverdue }.count
   371→        let important = tasks.filter { $0.isImportant }.count
   372→
   373→        return TaskStatistics(
   374→            total: tasks.count,
   375→            completed: completed,
   376→            pending: pending,
   377→            overdue: overdue,
   378→            important: important
   379→        )
   380→    }
   381→
   382→    func getTodayWorkSessions() -> [WorkSession] {
   383→        let calendar = Calendar.current
   384→        return workSessions.filter { calendar.isDateInToday($0.startTime) }
   385→    }
   386→
   387→    func getTodayJournalEntries() -> [JournalEntry] {
   388→        let calendar = Calendar.current
   389→        return journalEntries.filter { calendar.isDateInToday($0.createdAt) }
   390→    }
   391→
   392→    func getTotalFocusTime() -> TimeInterval {
   393→        workSessions.reduce(0) { $0 + $1.duration }
   394→    }
   395→
   396→    func getStreakDays() -> Int {
   397→        // Calculate consecutive days with at least one completed task or journal entry
   398→        let calendar = Calendar.current
   399→        var currentDate = Date()
   400→        var streakDays = 0
   401→
   402→        while true {
   403→            let hasActivity = tasks.contains(where: { task in
   404→                guard let completedAt = task.completedAt else { return false }
   405→                return calendar.isDate(completedAt, inSameDayAs: currentDate)
   406→            }) || journalEntries.contains(where: { entry in
   407→                calendar.isDate(entry.createdAt, inSameDayAs: currentDate)
   408→            })
   409→
   410→            if hasActivity {
   411→                streakDays += 1
   412→                currentDate = calendar.date(byAdding: .day, value: -1, to: currentDate) ?? currentDate
   413→            } else {
   414→                break
   415→            }
   416→        }
   417→
   418→        return streakDays
   419→    }
   420→
   421→    // MARK: - Sample Data Population
   422→    func populateSampleData() {
   423→        let calendar = Calendar.current
   424→        let now = Date()
   425→
   426→        // Sample Tasks with variety of states
   427→        let sampleTasks: [Task] = [
   428→            // Completed tasks (for streak)
   429→            Task(
   430→                title: "Morning workout routine",
   431→                notes: "30 minutes of cardio + stretching",
   432→                isCompleted: true,
   433→                isImportant: false,
   434→                priority: .medium,
   435→                category: .health,
   436→                subtasks: [
   437→                    Subtask(title: "Warm up", isCompleted: true),
   438→                    Subtask(title: "Cardio", isCompleted: true),
   439→                    Subtask(title: "Cool down", isCompleted: true)
   440→                ],
   441→                estimatedDuration: 30 * 60,
   442→                dueDate: calendar.date(byAdding: .day, value: -1, to: now),
   443→                completedAt: calendar.date(byAdding: .day, value: -1, to: now)
   444→            ),
   445→
   446→            // Active urgent task
   447→            Task(
   448→                title: "Finish quarterly report",
   449→                notes: "Include Q3 financials and projections for Q4",
   450→                isCompleted: false,
   451→                isImportant: true,
   452→                priority: .urgent,
   453→                category: .work,
   454→                subtasks: [
   455→                    Subtask(title: "Gather data", isCompleted: true),
   456→                    Subtask(title: "Create charts", isCompleted: true),
   457→                    Subtask(title: "Write summary", isCompleted: false),
   458→                    Subtask(title: "Review with team", isCompleted: false)
   459→                ],
   460→                estimatedDuration: 120 * 60,
   461→                dueDate: calendar.date(byAdding: .day, value: 1, to: now)
   462→            ),
   463→
   464→            // Learning task
   465→            Task(
   466→                title: "Complete SwiftUI course chapter 5",
   467→                notes: "Focus on Charts framework and data visualization",
   468→                isCompleted: false,
   469→                isImportant: true,
   470→                priority: .high,
   471→                category: .learning,
   472→                subtasks: [
   473→                    Subtask(title: "Watch videos", isCompleted: true),
   474→                    Subtask(title: "Complete exercises", isCompleted: false)
   475→                ],
   476→                estimatedDuration: 90 * 60,
   477→                dueDate: calendar.date(byAdding: .day, value: 3, to: now)
   478→            ),
   479→
   480→            // Personal task
   481→            Task(
   482→                title: "Plan weekend trip",
   483→                notes: "Research destinations and book accommodation",
   484→                isCompleted: false,
   485→                isImportant: false,
   486→                priority: .low,
   487→                category: .personal,
   488→                subtasks: [],
   489→                estimatedDuration: 45 * 60,
   490→                dueDate: calendar.date(byAdding: .day, value: 5, to: now)
   491→            ),
   492→
   493→            // Overdue task
   494→            Task(
   495→                title: "Update portfolio website",
   496→                notes: "Add recent projects and testimonials",
   497→                isCompleted: false,
   498→                isImportant: false,
   499→                priority: .medium,
   500→                category: .creative,
   501→                subtasks: [
   502→                    Subtask(title: "Choose projects", isCompleted: false),
   503→                    Subtask(title: "Write descriptions", isCompleted: false),
   504→                    Subtask(title: "Update design", isCompleted: false)
   505→                ],
   506→                estimatedDuration: 180 * 60,
   507→                dueDate: calendar.date(byAdding: .day, value: -2, to: now)
   508→            ),
   509→
   510→            // Financial task
   511→            Task(
   512→                title: "Review monthly budget",
   513→                notes: "Track expenses and adjust savings goals",
   514→                isCompleted: false,
   515→                isImportant: true,
   516→                priority: .high,
   517→                category: .finance,
   518→                subtasks: [],
   519→                estimatedDuration: 30 * 60,
   520→                dueDate: calendar.date(byAdding: .day, value: 2, to: now)
   521→            )
   522→        ]
   523→
   524→        // Sample Work Sessions (last 7 days)
   525→        var sampleSessions: [WorkSession] = []
   526→        for daysAgo in 0..<7 {
   527→            let sessionDate = calendar.date(byAdding: .day, value: -daysAgo, to: now)!
   528→
   529→            // Deep work session
   530→            sampleSessions.append(WorkSession(
   531→                sessionType: .deepWork,
   532→                duration: 110 * 60, // 1h 50m (completed most of it)
   533→                targetDuration: 120 * 60,
   534→                linkedTaskIds: [],
   535→                notes: "Focused work on report",
   536→                startTime: calendar.date(bySettingHour: 9, minute: 0, second: 0, of: sessionDate)!,
   537→                endTime: calendar.date(bySettingHour: 10, minute: 50, second: 0, of: sessionDate)!,
   538→                wasCompleted: false
   539→            ))
   540→
   541→            // Pomodoro session
   542→            sampleSessions.append(WorkSession(
   543→                sessionType: .pomodoro,
   544→                duration: 25 * 60,
   545→                targetDuration: 25 * 60,
   546→                linkedTaskIds: [],
   547→                notes: "Code review",
   548→                startTime: calendar.date(bySettingHour: 14, minute: 0, second: 0, of: sessionDate)!,
   549→                endTime: calendar.date(bySettingHour: 14, minute: 25, second: 0, of: sessionDate)!,
   550→                wasCompleted: true
   551→            ))
   552→        }
   553→
   554→        // Sample Journal Entries
   555→        let sampleEntries: [JournalEntry] = [
   556→            JournalEntry(
   557→                content: "Today was incredibly productive! Completed the morning workout and made significant progress on the quarterly report. The new SwiftUI charting library is fascinating - spent 2 hours learning about data visualization patterns. Feeling energized and motivated for tomorrow.",
   558→                title: "Productive Monday",
   559→                category: .achievement,
   560→                mood: 5,
   561→                createdAt: calendar.date(byAdding: .day, value: -1, to: now)!,
   562→                isFavorite: true
   563→            ),
   564→
   565→            JournalEntry(
   566→                content: "Reflected on my career goals today. Realized I want to focus more on mobile development and less on web. The iOS projects bring me much more satisfaction. Going to have a conversation with my manager about shifting focus.",
   567→                title: "Career Reflection",
   568→                category: .reflection,
   569→                mood: 3,
   570→                createdAt: calendar.date(byAdding: .day, value: -2, to: now)!,
   571→                isFavorite: false
   572→            ),
   573→
   574→            JournalEntry(
   575→                content: "Three things I'm grateful for today:\n1. Supportive team members who helped with the complex bug\n2. Morning coffee that tasted perfect\n3. The sunset view from the office window\n\nIt's the small things that make the difference.",
   576→                title: "Gratitude Practice",
   577→                category: .gratitude,
   578→                mood: 4,
   579→                createdAt: calendar.date(byAdding: .day, value: -3, to: now)!,
   580→                isFavorite: true
   581→            ),
   582→
   583→            JournalEntry(
   584→                content: "Learned a valuable lesson about code architecture today. Sometimes the simplest solution is the best one. Spent 3 hours on a complex abstraction when a straightforward approach would have worked better. Note to self: avoid over-engineering.",
   585→                title: "Learning from Mistakes",
   586→                category: .learning,
   587→                mood: 3,
   588→                createdAt: calendar.date(byAdding: .day, value: -5, to: now)!,
   589→                isFavorite: false
   590→            )
   591→        ]
   592→
   593→        // Add all sample data
   594→        tasks = sampleTasks
   595→        workSessions = sampleSessions
   596→        journalEntries = sampleEntries
   597→
   598→        // Save everything
   599→        saveAllData()
   600→
   601→        logger.info("Sample data populated successfully", category: .create, context: [
   602→            "tasks": tasks.count,
   603→            "workSessions": workSessions.count,
   604→            "journalEntries": journalEntries.count
   605→        ])
   606→    }
   607→}
   608→
   609→// MARK: - Statistics Model
   610→struct TaskStatistics {
   611→    let total: Int
   612→    let completed: Int
   613→    let pending: Int
   614→    let overdue: Int
   615→    let important: Int
   616→
   617→    var completionRate: Double {
   618→        guard total > 0 else { return 0 }
   619→        return Double(completed) / Double(total) * 100
   620→    }
   621→}
   622→

<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>

//
//  DataManager.swift
//  ProductivityHub-iOS
//
//  Unified data manager with 3-layer backup system (from ToDoMax)
//  TODO: Consider migrating to SwiftData for better performance and automatic persistence
//  See: https://developer.apple.com/documentation/swiftdata
//

import Foundation
import Combine

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

    // Logger instance
    private let logger = Logger.dataManager

    // Track if data has been loaded to prevent duplicate loads
    private var isDataLoaded = false

    // MARK: - Debounce System
    // Debounce saves to avoid excessive disk writes during rapid operations
    private var saveDebounceTask: _Concurrency.Task<Void, Never>?
    private let saveDebounceDelay: UInt64 = 500_000_000 // 500ms in nanoseconds
    private var pendingSaves: Set<String> = [] // Track which data types need saving

    // MARK: - Published Properties
    @Published var tasks: [Task] = []
    @Published var workSessions: [WorkSession] = []
    @Published var journalEntries: [JournalEntry] = []
    @Published var tags: [Tag] = []
    @Published var templates: [Template] = []

    // MARK: - UserDefaults Keys
    private let tasksKey = "ProductivityHub_Tasks"
    private let tasksBackup1Key = "ProductivityHub_Tasks_backup1"
    private let tasksBackup2Key = "ProductivityHub_Tasks_backup2"

    private let sessionsKey = "ProductivityHub_Sessions"
    private let sessionsBackup1Key = "ProductivityHub_Sessions_backup1"
    private let sessionsBackup2Key = "ProductivityHub_Sessions_backup2"

    private let journalKey = "ProductivityHub_Journal"
    private let journalBackup1Key = "ProductivityHub_Journal_backup1"
    private let journalBackup2Key = "ProductivityHub_Journal_backup2"

    private let tagsKey = "ProductivityHub_Tags"
    private let tagsBackup1Key = "ProductivityHub_Tags_backup1"
    private let tagsBackup2Key = "ProductivityHub_Tags_backup2"

    private let templatesKey = "ProductivityHub_Templates"
    private let templatesBackup1Key = "ProductivityHub_Templates_backup1"
    private let templatesBackup2Key = "ProductivityHub_Templates_backup2"

    // MARK: - Initialization
    private init() {
        loadAllData()
    }

    // MARK: - Load All Data
    func loadAllData() {
        // Prevent duplicate loading
        guard !isDataLoaded else {
            logger.debug("Data already loaded, skipping duplicate load", category: .load)
            return
        }

        tasks = loadWithBackup(key: tasksKey, backup1: tasksBackup1Key, backup2: tasksBackup2Key) ?? []
        workSessions = loadWithBackup(key: sessionsKey, backup1: sessionsBackup1Key, backup2: sessionsBackup2Key) ?? []
        journalEntries = loadWithBackup(key: journalKey, backup1: journalBackup1Key, backup2: journalBackup2Key) ?? []
        tags = loadWithBackup(key: tagsKey, backup1: tagsBackup1Key, backup2: tagsBackup2Key) ?? Tag.systemTags
        templates = loadWithBackup(key: templatesKey, backup1: templatesBackup1Key, backup2: templatesBackup2Key) ?? Template.systemTemplates

        // Populate sample data on first launch
        if tasks.isEmpty && workSessions.isEmpty && journalEntries.isEmpty {
            logger.info("First launch detected - populating sample data", category: .lifecycle)
            populateSampleData()
        }

        isDataLoaded = true

        logger.info("DataManager loaded successfully", category: .load, context: [
            "tasks": tasks.count,
            "workSessions": workSessions.count,
            "journalEntries": journalEntries.count,
            "tags": tags.count,
            "templates": templates.count
        ])
    }

    // MARK: - Save All Data
    func saveAllData() {
        saveWithBackup(data: tasks, key: tasksKey, backup1: tasksBackup1Key, backup2: tasksBackup2Key)
        saveWithBackup(data: workSessions, key: sessionsKey, backup1: sessionsBackup1Key, backup2: sessionsBackup2Key)
        saveWithBackup(data: journalEntries, key: journalKey, backup1: journalBackup1Key, backup2: journalBackup2Key)
        saveWithBackup(data: tags, key: tagsKey, backup1: tagsBackup1Key, backup2: tagsBackup2Key)
        saveWithBackup(data: templates, key: templatesKey, backup1: templatesBackup1Key, backup2: templatesBackup2Key)

        logger.info("All data saved successfully", category: .save)

        // Trigger CloudKit sync if enabled
        triggerCloudSync()
    }

    // MARK: - CloudKit Sync Integration
    private func triggerCloudSync() {
        let cloudKitService = CloudKitSyncService.shared
        guard cloudKitService.isSyncEnabled else { return }

        // Debounced sync - CloudKitSyncService handles the debouncing
        _Concurrency.Task {
            await cloudKitService.syncAllData(dataManager: self)
        }
    }

    // MARK: - 3-Layer Backup System (from ToDoMax)
    private func loadWithBackup<T: Decodable>(key: String, backup1: String, backup2: String) -> T? {
        // Try primary key
        if let data = UserDefaults.standard.data(forKey: key),
           let decoded = try? JSONDecoder().decode(T.self, from: data) {
            logger.debug("Loaded from primary key", category: .load, context: ["key": key])
            return decoded
        }

        // Try backup 1
        if let data = UserDefaults.standard.data(forKey: backup1),
           let decoded = try? JSONDecoder().decode(T.self, from: data) {
            logger.warning("Primary key corrupted, loaded from backup1", category: .backup, context: ["key": backup1])
            // Restore to primary
            UserDefaults.standard.set(data, forKey: key)
            return decoded
        }

        // Try backup 2
        if let data = UserDefaults.standard.data(forKey: backup2),
           let decoded = try? JSONDecoder().decode(T.self, from: data) {
            logger.warning("Primary and backup1 corrupted, loaded from backup2", category: .backup, context: ["key": backup2])
            // Restore to primary and backup1
            UserDefaults.standard.set(data, forKey: key)
            UserDefaults.standard.set(data, forKey: backup1)
            return decoded
        }

        logger.info("No existing data found for key (first launch)", category: .load, context: ["key": key])
        return nil
    }

    // MARK: - Debounced Save Methods

    /// Schedule a debounced save for a specific data type
    private func scheduleDebouncedSave(for dataType: String) {
        pendingSaves.insert(dataType)

        // Cancel any existing debounce task
        saveDebounceTask?.cancel()

        // Schedule new debounce task
        saveDebounceTask = _Concurrency.Task { [weak self] in
            do {
                try await _Concurrency.Task.sleep(nanoseconds: self?.saveDebounceDelay ?? 500_000_000)
                await self?.executePendingSaves()
            } catch {
                // Task was cancelled - new save scheduled
            }
        }
    }

    /// Execute all pending saves
    private func executePendingSaves() {
        guard !pendingSaves.isEmpty else { return }

        let savesToExecute = pendingSaves
        pendingSaves.removeAll()

        for dataType in savesToExecute {
            switch dataType {
            case "tasks":
                saveWithBackupImmediate(data: tasks, key: tasksKey, backup1: tasksBackup1Key, backup2: tasksBackup2Key)
            case "sessions":
                saveWithBackupImmediate(data: workSessions, key: sessionsKey, backup1: sessionsBackup1Key, backup2: sessionsBackup2Key)
            case "journal":
                saveWithBackupImmediate(data: journalEntries, key: journalKey, backup1: journalBackup1Key, backup2: journalBackup2Key)
            case "tags":
                saveWithBackupImmediate(data: tags, key: tagsKey, backup1: tagsBackup1Key, backup2: tagsBackup2Key)
            case "templates":
                saveWithBackupImmediate(data: templates, key: templatesKey, backup1: templatesBackup1Key, backup2: templatesBackup2Key)
            default:
                break
            }
        }

        logger.debug("Debounced save executed", category: .save, context: ["types": savesToExecute.joined(separator: ", ")])

        // Trigger CloudKit sync after debounced save
        triggerCloudSync()
    }

    /// Force immediate save of all pending data (e.g., when app goes to background)
    func flushPendingSaves() {
        saveDebounceTask?.cancel()
        saveDebounceTask = nil
        executePendingSaves()
    }

    private func saveWithBackup<T: Codable>(data: T, key: String, backup1: String, backup2: String) {
        // Use immediate save for backwards compatibility
        saveWithBackupImmediate(data: data, key: key, backup1: backup1, backup2: backup2)
    }

    private func saveWithBackupImmediate<T: Codable>(data: T, key: String, backup1: String, backup2: String) {
        // Attempt to encode data
        let encoded: Data
        do {
            encoded = try JSONEncoder().encode(data)
        } catch {
            logger.error("Failed to encode data - attempting recovery from backup", category: .save, context: [
                "key": key,
                "error": error.localizedDescription
            ])
            // Don't corrupt existing backups - just return and keep current data
            return
        }

        // Validate encoded data can be decoded (integrity check)
        do {
            _ = try JSONDecoder().decode(type(of: data).self, from: encoded)
        } catch {
            logger.critical("Data validation failed - corrupted data detected, preserving backups", category: .save, context: [
                "key": key,
                "error": error.localizedDescription
            ])
            // Data is corrupted - don't save to preserve existing backups
            return
        }

        // Cascade backups: current → backup1, backup1 → backup2
        // Only cascade if we're sure new data is valid
        if let currentData = UserDefaults.standard.data(forKey: key) {
            // Verify current data is valid before demoting to backup
            if (try? JSONDecoder().decode(type(of: data).self, from: currentData)) != nil {
                if let backup1Data = UserDefaults.standard.data(forKey: backup1) {
                    UserDefaults.standard.set(backup1Data, forKey: backup2)
                }
                UserDefaults.standard.set(currentData, forKey: backup1)
            } else {
                logger.warning("Current data corrupted, not cascading to backup", category: .backup, context: ["key": key])
            }
        }

        // Save new validated data
        UserDefaults.standard.set(encoded, forKey: key)
        logger.debug("Saved with 3-layer backup", category: .save, context: ["key": key, "size": "\(encoded.count) bytes"])
    }

    // MARK: - Task Operations
    func addTask(_ task: Task) {
        tasks.append(task)
        scheduleDebouncedSave(for: "tasks")
    }

    func updateTask(_ task: Task) {
        if let index = tasks.firstIndex(where: { $0.id == task.id }) {
            tasks[index] = task
            scheduleDebouncedSave(for: "tasks")
        }
    }

    func deleteTask(_ task: Task) {
        tasks.removeAll { $0.id == task.id }
        scheduleDebouncedSave(for: "tasks")
    }

    func toggleTaskCompletion(_ task: Task) {
        if let index = tasks.firstIndex(where: { $0.id == task.id }) {
            tasks[index].isCompleted.toggle()
            tasks[index].completedAt = tasks[index].isCompleted ? Date() : nil

            // Haptic feedback
            if tasks[index].isCompleted {
                HapticManager.taskCompleted()
            } else {
                HapticManager.impact(.light)
            }

            scheduleDebouncedSave(for: "tasks")
        }
    }

    // MARK: - WorkSession Operations
    func addWorkSession(_ session: WorkSession) {
        workSessions.append(session)
        HapticManager.entryAdded()
        scheduleDebouncedSave(for: "sessions")
    }

    func updateWorkSession(_ session: WorkSession) {
        if let index = workSessions.firstIndex(where: { $0.id == session.id }) {
            workSessions[index] = session
            scheduleDebouncedSave(for: "sessions")
        }
    }

    func deleteWorkSession(_ session: WorkSession) {
        workSessions.removeAll { $0.id == session.id }
        scheduleDebouncedSave(for: "sessions")
    }

    // MARK: - JournalEntry Operations
    func addJournalEntry(_ entry: JournalEntry) {
        journalEntries.append(entry)
        scheduleDebouncedSave(for: "journal")
    }

    func updateJournalEntry(_ entry: JournalEntry) {
        if let index = journalEntries.firstIndex(where: { $0.id == entry.id }) {
            var updatedEntry = entry
            updatedEntry.modifiedAt = Date()
            journalEntries[index] = updatedEntry
            scheduleDebouncedSave(for: "journal")
        }
    }

    func deleteJournalEntry(_ entry: JournalEntry) {
        journalEntries.removeAll { $0.id == entry.id }
        scheduleDebouncedSave(for: "journal")
    }

    // MARK: - Tag Operations
    func addTag(_ tag: Tag) {
        tags.append(tag)
        scheduleDebouncedSave(for: "tags")
    }

    func updateTag(_ tag: Tag) {
        if let index = tags.firstIndex(where: { $0.id == tag.id }) {
            tags[index] = tag
            scheduleDebouncedSave(for: "tags")
        }
    }

    func deleteTag(_ tag: Tag) {
        tags.removeAll { $0.id == tag.id }
        scheduleDebouncedSave(for: "tags")
    }

    // MARK: - Template Operations
    func addTemplate(_ template: Template) {
        templates.append(template)
        scheduleDebouncedSave(for: "templates")
    }

    func updateTemplate(_ template: Template) {
        if let index = templates.firstIndex(where: { $0.id == template.id }) {
            templates[index] = template
            scheduleDebouncedSave(for: "templates")
        }
    }

    func deleteTemplate(_ template: Template) {
        templates.removeAll { $0.id == template.id }
        scheduleDebouncedSave(for: "templates")
    }

    // MARK: - Statistics & Insights
    func getTaskStatistics() -> TaskStatistics {
        let completed = tasks.filter { $0.isCompleted }.count
        let pending = tasks.count - completed
        let overdue = tasks.filter { $0.isOverdue }.count
        let important = tasks.filter { $0.isImportant }.count

        return TaskStatistics(
            total: tasks.count,
            completed: completed,
            pending: pending,
            overdue: overdue,
            important: important
        )
    }

    func getTodayWorkSessions() -> [WorkSession] {
        let calendar = Calendar.current
        return workSessions.filter { calendar.isDateInToday($0.startTime) }
    }

    func getTodayJournalEntries() -> [JournalEntry] {
        let calendar = Calendar.current
        return journalEntries.filter { calendar.isDateInToday($0.createdAt) }
    }

    func getTotalFocusTime() -> TimeInterval {
        workSessions.reduce(0) { $0 + $1.duration }
    }

    func getStreakDays() -> Int {
        // Calculate consecutive days with at least one completed task or journal entry
        let calendar = Calendar.current
        var currentDate = Date()
        var streakDays = 0

        while true {
            let hasActivity = tasks.contains(where: { task in
                guard let completedAt = task.completedAt else { return false }
                return calendar.isDate(completedAt, inSameDayAs: currentDate)
            }) || journalEntries.contains(where: { entry in
                calendar.isDate(entry.createdAt, inSameDayAs: currentDate)
            })

            if hasActivity {
                streakDays += 1
                currentDate = calendar.date(byAdding: .day, value: -1, to: currentDate) ?? currentDate
            } else {
                break
            }
        }

        return streakDays
    }

    // MARK: - Sample Data Population
    func populateSampleData() {
        let calendar = Calendar.current
        let now = Date()

        // Sample Tasks with variety of states
        let sampleTasks: [Task] = [
            // Completed tasks (for streak)
            Task(
                title: "Morning workout routine",
                notes: "30 minutes of cardio + stretching",
                isCompleted: true,
                isImportant: false,
                priority: .medium,
                category: .health,
                subtasks: [
                    Subtask(title: "Warm up", isCompleted: true),
                    Subtask(title: "Cardio", isCompleted: true),
                    Subtask(title: "Cool down", isCompleted: true)
                ],
                estimatedDuration: 30 * 60,
                dueDate: calendar.date(byAdding: .day, value: -1, to: now),
                completedAt: calendar.date(byAdding: .day, value: -1, to: now)
            ),

            // Active urgent task
            Task(
                title: "Finish quarterly report",
                notes: "Include Q3 financials and projections for Q4",
                isCompleted: false,
                isImportant: true,
                priority: .urgent,
                category: .work,
                subtasks: [
                    Subtask(title: "Gather data", isCompleted: true),
                    Subtask(title: "Create charts", isCompleted: true),
                    Subtask(title: "Write summary", isCompleted: false),
                    Subtask(title: "Review with team", isCompleted: false)
                ],
                estimatedDuration: 120 * 60,
                dueDate: calendar.date(byAdding: .day, value: 1, to: now)
            ),

            // Learning task
            Task(
                title: "Complete SwiftUI course chapter 5",
                notes: "Focus on Charts framework and data visualization",
                isCompleted: false,
                isImportant: true,
                priority: .high,
                category: .learning,
                subtasks: [
                    Subtask(title: "Watch videos", isCompleted: true),
                    Subtask(title: "Complete exercises", isCompleted: false)
                ],
                estimatedDuration: 90 * 60,
                dueDate: calendar.date(byAdding: .day, value: 3, to: now)
            ),

            // Personal task
            Task(
                title: "Plan weekend trip",
                notes: "Research destinations and book accommodation",
                isCompleted: false,
                isImportant: false,
                priority: .low,
                category: .personal,
                subtasks: [],
                estimatedDuration: 45 * 60,
                dueDate: calendar.date(byAdding: .day, value: 5, to: now)
            ),

            // Overdue task
            Task(
                title: "Update portfolio website",
                notes: "Add recent projects and testimonials",
                isCompleted: false,
                isImportant: false,
                priority: .medium,
                category: .creative,
                subtasks: [
                    Subtask(title: "Choose projects", isCompleted: false),
                    Subtask(title: "Write descriptions", isCompleted: false),
                    Subtask(title: "Update design", isCompleted: false)
                ],
                estimatedDuration: 180 * 60,
                dueDate: calendar.date(byAdding: .day, value: -2, to: now)
            ),

            // Financial task
            Task(
                title: "Review monthly budget",
                notes: "Track expenses and adjust savings goals",
                isCompleted: false,
                isImportant: true,
                priority: .high,
                category: .finance,
                subtasks: [],
                estimatedDuration: 30 * 60,
                dueDate: calendar.date(byAdding: .day, value: 2, to: now)
            )
        ]

        // Sample Work Sessions (last 7 days)
        var sampleSessions: [WorkSession] = []
        for daysAgo in 0..<7 {
            let sessionDate = calendar.date(byAdding: .day, value: -daysAgo, to: now)!

            // Deep work session
            sampleSessions.append(WorkSession(
                sessionType: .deepWork,
                duration: 110 * 60, // 1h 50m (completed most of it)
                targetDuration: 120 * 60,
                linkedTaskIds: [],
                notes: "Focused work on report",
                startTime: calendar.date(bySettingHour: 9, minute: 0, second: 0, of: sessionDate)!,
                endTime: calendar.date(bySettingHour: 10, minute: 50, second: 0, of: sessionDate)!,
                wasCompleted: false
            ))

            // Pomodoro session
            sampleSessions.append(WorkSession(
                sessionType: .pomodoro,
                duration: 25 * 60,
                targetDuration: 25 * 60,
                linkedTaskIds: [],
                notes: "Code review",
                startTime: calendar.date(bySettingHour: 14, minute: 0, second: 0, of: sessionDate)!,
                endTime: calendar.date(bySettingHour: 14, minute: 25, second: 0, of: sessionDate)!,
                wasCompleted: true
            ))
        }

        // Sample Journal Entries
        let sampleEntries: [JournalEntry] = [
            JournalEntry(
                content: "Today was incredibly productive! Completed the morning workout and made significant progress on the quarterly report. The new SwiftUI charting library is fascinating - spent 2 hours learning about data visualization patterns. Feeling energized and motivated for tomorrow.",
                title: "Productive Monday",
                category: .achievement,
                mood: 5,
                createdAt: calendar.date(byAdding: .day, value: -1, to: now)!,
                isFavorite: true
            ),

            JournalEntry(
                content: "Reflected on my career goals today. Realized I want to focus more on mobile development and less on web. The iOS projects bring me much more satisfaction. Going to have a conversation with my manager about shifting focus.",
                title: "Career Reflection",
                category: .reflection,
                mood: 3,
                createdAt: calendar.date(byAdding: .day, value: -2, to: now)!,
                isFavorite: false
            ),

            JournalEntry(
                content: "Three things I'm grateful for today:\n1. Supportive team members who helped with the complex bug\n2. Morning coffee that tasted perfect\n3. The sunset view from the office window\n\nIt's the small things that make the difference.",
                title: "Gratitude Practice",
                category: .gratitude,
                mood: 4,
                createdAt: calendar.date(byAdding: .day, value: -3, to: now)!,
                isFavorite: true
            ),

            JournalEntry(
                content: "Learned a valuable lesson about code architecture today. Sometimes the simplest solution is the best one. Spent 3 hours on a complex abstraction when a straightforward approach would have worked better. Note to self: avoid over-engineering.",
                title: "Learning from Mistakes",
                category: .learning,
                mood: 3,
                createdAt: calendar.date(byAdding: .day, value: -5, to: now)!,
                isFavorite: false
            )
        ]

        // Add all sample data
        tasks = sampleTasks
        workSessions = sampleSessions
        journalEntries = sampleEntries

        // Save everything
        saveAllData()

        logger.info("Sample data populated successfully", category: .create, context: [
            "tasks": tasks.count,
            "workSessions": workSessions.count,
            "journalEntries": journalEntries.count
        ])
    }
}

// MARK: - Statistics Model
struct TaskStatistics {
    let total: Int
    let completed: Int
    let pending: Int
    let overdue: Int
    let important: Int

    var completionRate: Double {
        guard total > 0 else { return 0 }
        return Double(completed) / Double(total) * 100
    }
}


     1→//
     2→//  Task.swift
     3→//  ProductivityHub-iOS
     4→//
     5→//  Unified task model merging ToDoMax + FocusWriter features
     6→//
     7→
     8→import Foundation
     9→import SwiftUI
    10→
    11→enum TaskPriority: String, Codable, CaseIterable {
    12→    case low = "Low"
    13→    case medium = "Medium"
    14→    case high = "High"
    15→    case urgent = "Urgent"
    16→
    17→    var color: String {
    18→        switch self {
    19→        case .low: return "gray"
    20→        case .medium: return "blue"
    21→        case .high: return "orange"
    22→        case .urgent: return "red"
    23→        }
    24→    }
    25→
    26→    var swiftUIColor: Color {
    27→        switch self {
    28→        case .low: return .gray
    29→        case .medium: return .blue
    30→        case .high: return .orange
    31→        case .urgent: return .red
    32→        }
    33→    }
    34→}
    35→
    36→enum TaskCategory: String, Codable, CaseIterable {
    37→    case work = "Work"
    38→    case personal = "Personal"
    39→    case health = "Health"
    40→    case learning = "Learning"
    41→    case creative = "Creative"
    42→    case finance = "Finance"
    43→    case social = "Social"
    44→    case other = "Other"
    45→
    46→    var icon: String {
    47→        switch self {
    48→        case .work: return "briefcase.fill"
    49→        case .personal: return "person.fill"
    50→        case .health: return "heart.fill"
    51→        case .learning: return "book.fill"
    52→        case .creative: return "paintbrush.fill"
    53→        case .finance: return "dollarsign.circle.fill"
    54→        case .social: return "person.2.fill"
    55→        case .other: return "folder.fill"
    56→        }
    57→    }
    58→}
    59→
    60→struct Subtask: Identifiable, Codable, Hashable {
    61→    var id: UUID = UUID()
    62→    var title: String
    63→    var isCompleted: Bool = false
    64→    var createdAt: Date = Date()
    65→
    66→    /// Validated initializer that ensures title is not empty
    67→    init(id: UUID = UUID(), title: String, isCompleted: Bool = false, createdAt: Date = Date()) {
    68→        self.id = id
    69→        self.title = title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
    70→            ? "Untitled Subtask"
    71→            : title.trimmingCharacters(in: .whitespacesAndNewlines)
    72→        self.isCompleted = isCompleted
    73→        self.createdAt = createdAt
    74→    }
    75→}
    76→
    77→struct Task: Identifiable, Codable, Hashable {
    78→    var id: UUID = UUID()
    79→    var title: String
    80→    var notes: String = ""
    81→    var isCompleted: Bool = false
    82→    var isImportant: Bool = false
    83→    var priority: TaskPriority = .medium
    84→    var category: TaskCategory = .personal
    85→    var subtasks: [Subtask] = []
    86→    var linkedSessionIds: [UUID] = [] // Link to WorkSessions
    87→    var tags: [UUID] = [] // Link to Tags
    88→    var estimatedDuration: TimeInterval? = nil
    89→    var dueDate: Date? = nil
    90→    var createdAt: Date = Date()
    91→    var completedAt: Date? = nil
    92→
    93→    /// Validated initializer that ensures title is not empty
    94→    init(
    95→        id: UUID = UUID(),
    96→        title: String,
    97→        notes: String = "",
    98→        isCompleted: Bool = false,
    99→        isImportant: Bool = false,
   100→        priority: TaskPriority = .medium,
   101→        category: TaskCategory = .personal,
   102→        subtasks: [Subtask] = [],
   103→        linkedSessionIds: [UUID] = [],
   104→        tags: [UUID] = [],
   105→        estimatedDuration: TimeInterval? = nil,
   106→        dueDate: Date? = nil,
   107→        createdAt: Date = Date(),
   108→        completedAt: Date? = nil
   109→    ) {
   110→        self.id = id
   111→        self.title = title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
   112→            ? "Untitled Task"
   113→            : title.trimmingCharacters(in: .whitespacesAndNewlines)
   114→        self.notes = notes.trimmingCharacters(in: .whitespacesAndNewlines)
   115→        self.isCompleted = isCompleted
   116→        self.isImportant = isImportant
   117→        self.priority = priority
   118→        self.category = category
   119→        self.subtasks = subtasks
   120→        self.linkedSessionIds = linkedSessionIds
   121→        self.tags = tags
   122→        self.estimatedDuration = estimatedDuration
   123→        self.dueDate = dueDate
   124→        self.createdAt = createdAt
   125→        self.completedAt = completedAt
   126→    }
   127→
   128→    // MARK: - Computed properties
   129→    var progress: Double {
   130→        guard !subtasks.isEmpty else { return isCompleted ? 1.0 : 0.0 }
   131→        let completed = subtasks.filter { $0.isCompleted }.count
   132→        return Double(completed) / Double(subtasks.count)
   133→    }
   134→
   135→    var totalSubtasks: Int {
   136→        subtasks.count
   137→    }
   138→
   139→    var completedSubtasks: Int {
   140→        subtasks.filter { $0.isCompleted }.count
   141→    }
   142→
   143→    var isOverdue: Bool {
   144→        guard let dueDate = dueDate, !isCompleted else { return false }
   145→        return dueDate < Date()
   146→    }
   147→}
   148→

<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>

//
//  Task.swift
//  ProductivityHub-iOS
//
//  Unified task model merging ToDoMax + FocusWriter features
//

import Foundation
import SwiftUI

enum TaskPriority: String, Codable, CaseIterable {
    case low = "Low"
    case medium = "Medium"
    case high = "High"
    case urgent = "Urgent"

    var color: String {
        switch self {
        case .low: return "gray"
        case .medium: return "blue"
        case .high: return "orange"
        case .urgent: return "red"
        }
    }

    var swiftUIColor: Color {
        switch self {
        case .low: return .gray
        case .medium: return .blue
        case .high: return .orange
        case .urgent: return .red
        }
    }
}

enum TaskCategory: String, Codable, CaseIterable {
    case work = "Work"
    case personal = "Personal"
    case health = "Health"
    case learning = "Learning"
    case creative = "Creative"
    case finance = "Finance"
    case social = "Social"
    case other = "Other"

    var icon: String {
        switch self {
        case .work: return "briefcase.fill"
        case .personal: return "person.fill"
        case .health: return "heart.fill"
        case .learning: return "book.fill"
        case .creative: return "paintbrush.fill"
        case .finance: return "dollarsign.circle.fill"
        case .social: return "person.2.fill"
        case .other: return "folder.fill"
        }
    }
}

struct Subtask: Identifiable, Codable, Hashable {
    var id: UUID = UUID()
    var title: String
    var isCompleted: Bool = false
    var createdAt: Date = Date()

    /// Validated initializer that ensures title is not empty
    init(id: UUID = UUID(), title: String, isCompleted: Bool = false, createdAt: Date = Date()) {
        self.id = id
        self.title = title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
            ? "Untitled Subtask"
            : title.trimmingCharacters(in: .whitespacesAndNewlines)
        self.isCompleted = isCompleted
        self.createdAt = createdAt
    }
}

struct Task: Identifiable, Codable, Hashable {
    var id: UUID = UUID()
    var title: String
    var notes: String = ""
    var isCompleted: Bool = false
    var isImportant: Bool = false
    var priority: TaskPriority = .medium
    var category: TaskCategory = .personal
    var subtasks: [Subtask] = []
    var linkedSessionIds: [UUID] = [] // Link to WorkSessions
    var tags: [UUID] = [] // Link to Tags
    var estimatedDuration: TimeInterval? = nil
    var dueDate: Date? = nil
    var createdAt: Date = Date()
    var completedAt: Date? = nil

    /// Validated initializer that ensures title is not empty
    init(
        id: UUID = UUID(),
        title: String,
        notes: String = "",
        isCompleted: Bool = false,
        isImportant: Bool = false,
        priority: TaskPriority = .medium,
        category: TaskCategory = .personal,
        subtasks: [Subtask] = [],
        linkedSessionIds: [UUID] = [],
        tags: [UUID] = [],
        estimatedDuration: TimeInterval? = nil,
        dueDate: Date? = nil,
        createdAt: Date = Date(),
        completedAt: Date? = nil
    ) {
        self.id = id
        self.title = title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
            ? "Untitled Task"
            : title.trimmingCharacters(in: .whitespacesAndNewlines)
        self.notes = notes.trimmingCharacters(in: .whitespacesAndNewlines)
        self.isCompleted = isCompleted
        self.isImportant = isImportant
        self.priority = priority
        self.category = category
        self.subtasks = subtasks
        self.linkedSessionIds = linkedSessionIds
        self.tags = tags
        self.estimatedDuration = estimatedDuration
        self.dueDate = dueDate
        self.createdAt = createdAt
        self.completedAt = completedAt
    }

    // MARK: - Computed properties
    var progress: Double {
        guard !subtasks.isEmpty else { return isCompleted ? 1.0 : 0.0 }
        let completed = subtasks.filter { $0.isCompleted }.count
        return Double(completed) / Double(subtasks.count)
    }

    var totalSubtasks: Int {
        subtasks.count
    }

    var completedSubtasks: Int {
        subtasks.filter { $0.isCompleted }.count
    }

    var isOverdue: Bool {
        guard let dueDate = dueDate, !isCompleted else { return false }
        return dueDate < Date()
    }
}


     1→//
     2→//  MainTabView.swift
     3→//  ProductivityHub-iOS
     4→//
     5→//  Adaptive navigation: TabView on iPhone, NavigationSplitView on iPad/Mac
     6→//  Optimized for "Designed for iPad" on Mac
     7→//
     8→
     9→import SwiftUI
    10→
    11→// MARK: - Navigation Item Enum
    12→enum NavigationItem: String, CaseIterable, Identifiable {
    13→    case focus = "Focus"
    14→    case tasks = "Tasks"
    15→    case journal = "Journal"
    16→    case insights = "Insights"
    17→    case settings = "Settings"
    18→
    19→    var id: String { rawValue }
    20→
    21→    var icon: String {
    22→        switch self {
    23→        case .focus: return "timer"
    24→        case .tasks: return "checklist"
    25→        case .journal: return "book.fill"
    26→        case .insights: return "chart.bar.fill"
    27→        case .settings: return "gearshape.fill"
    28→        }
    29→    }
    30→
    31→    var subtitle: String {
    32→        switch self {
    33→        case .focus: return "Deep work & Pomodoro"
    34→        case .tasks: return "Manage your tasks"
    35→        case .journal: return "Daily reflections"
    36→        case .insights: return "Track your progress"
    37→        case .settings: return "App preferences"
    38→        }
    39→    }
    40→
    41→    var keyboardShortcut: KeyEquivalent {
    42→        switch self {
    43→        case .focus: return "1"
    44→        case .tasks: return "2"
    45→        case .journal: return "3"
    46→        case .insights: return "4"
    47→        case .settings: return "5"
    48→        }
    49→    }
    50→}
    51→
    52→// MARK: - Main Tab View
    53→struct MainTabView: View {
    54→    @EnvironmentObject var dataManager: DataManager
    55→    @EnvironmentObject var quickActionManager: QuickActionManager
    56→    @StateObject private var toastManager = ToastManager.shared
    57→    @State private var selectedTab = 0
    58→    @State private var selectedItem: NavigationItem? = .focus
    59→    @State private var columnVisibility: NavigationSplitViewVisibility = .all
    60→
    61→    @Environment(\.horizontalSizeClass) private var horizontalSizeClass
    62→
    63→    var body: some View {
    64→        Group {
    65→            if horizontalSizeClass == .regular {
    66→                // iPad / Mac: NavigationSplitView with Sidebar
    67→                iPadNavigationView
    68→            } else {
    69→                // iPhone: Traditional TabView
    70→                iPhoneTabView
    71→            }
    72→        }
    73→        .toastView(toast: $toastManager.toast)
    74→        .environmentObject(toastManager)
    75→        // Handle quick actions from home screen
    76→        .onReceive(quickActionManager.$selectedTab) { tab in
    77→            selectedTab = tab
    78→            selectedItem = NavigationItem.allCases[safe: tab] ?? .focus
    79→        }
    80→    }
    81→
    82→    // MARK: - iPhone TabView
    83→    private var iPhoneTabView: some View {
    84→        TabView(selection: $selectedTab) {
    85→            FocusView()
    86→                .tabItem { Label("Focus", systemImage: "timer") }
    87→                .tag(0)
    88→
    89→            TasksView()
    90→                .tabItem { Label("Tasks", systemImage: "checklist") }
    91→                .tag(1)
    92→
    93→            JournalView()
    94→                .tabItem { Label("Journal", systemImage: "book.fill") }
    95→                .tag(2)
    96→
    97→            InsightsView()
    98→                .tabItem { Label("Insights", systemImage: "chart.bar.fill") }
    99→                .tag(3)
   100→
   101→            SettingsView()
   102→                .tabItem { Label("Settings", systemImage: "gearshape.fill") }
   103→                .tag(4)
   104→        }
   105→        .accentColor(.blue)
   106→        .background {
   107→            KeyboardShortcutsView(selectedTab: $selectedTab)
   108→        }
   109→    }
   110→
   111→    // MARK: - iPad/Mac NavigationSplitView
   112→    private var iPadNavigationView: some View {
   113→        NavigationSplitView(columnVisibility: $columnVisibility) {
   114→            // Sidebar with enhanced styling for Mac
   115→            List(NavigationItem.allCases, selection: $selectedItem) { item in
   116→                NavigationLink(value: item) {
   117→                    SidebarItemView(item: item, isSelected: selectedItem == item)
   118→                }
   119→                .keyboardShortcut(item.keyboardShortcut, modifiers: .command)
   120→            }
   121→            .navigationTitle("ProductivityHub")
   122→            .listStyle(.sidebar)
   123→            .navigationSplitViewColumnWidth(min: 220, ideal: 260, max: 320)
   124→        } detail: {
   125→            // Detail View with responsive container
   126→            NavigationStack {
   127→                GeometryReader { geometry in
   128→                    detailView(for: selectedItem ?? .focus)
   129→                        .frame(maxWidth: min(geometry.size.width, 900))
   130→                        .frame(maxWidth: .infinity)
   131→                }
   132→            }
   133→        }
   134→        .navigationSplitViewStyle(.balanced)
   135→    }
   136→
   137→    // MARK: - Sidebar Item View
   138→    struct SidebarItemView: View {
   139→        let item: NavigationItem
   140→        let isSelected: Bool
   141→
   142→        var body: some View {
   143→            HStack(spacing: 12) {
   144→                Image(systemName: item.icon)
   145→                    .font(.system(size: 18, weight: .medium))
   146→                    .foregroundColor(isSelected ? .accentColor : .secondary)
   147→                    .frame(width: 24)
   148→
   149→                VStack(alignment: .leading, spacing: 2) {
   150→                    Text(item.rawValue)
   151→                        .font(.body)
   152→                        .fontWeight(isSelected ? .semibold : .regular)
   153→
   154→                    Text(item.subtitle)
   155→                        .font(.caption)
   156→                        .foregroundColor(.secondary)
   157→                }
   158→
   159→                Spacer()
   160→
   161→                // Keyboard shortcut hint
   162→                Text("⌘\(item.keyboardShortcut.character)")
   163→                    .font(.caption2)
   164→                    .foregroundColor(Color(UIColor.tertiaryLabel))
   165→                    .padding(.horizontal, 6)
   166→                    .padding(.vertical, 2)
   167→                    .background(Color.secondary.opacity(0.1))
   168→                    .cornerRadius(4)
   169→            }
   170→            .padding(.vertical, 6)
   171→            .contentShape(Rectangle())
   172→        }
   173→    }
   174→
   175→    // MARK: - Detail View Router
   176→    @ViewBuilder
   177→    private func detailView(for item: NavigationItem) -> some View {
   178→        switch item {
   179→        case .focus:
   180→            FocusView()
   181→        case .tasks:
   182→            TasksView()
   183→        case .journal:
   184→            JournalView()
   185→        case .insights:
   186→            InsightsView()
   187→        case .settings:
   188→            SettingsView()
   189→        }
   190→    }
   191→}
   192→
   193→// MARK: - Keyboard Shortcuts (iPhone fallback)
   194→struct KeyboardShortcutsView: View {
   195→    @Binding var selectedTab: Int
   196→
   197→    var body: some View {
   198→        Group {
   199→            Button("") { selectedTab = 0 }
   200→                .keyboardShortcut("1", modifiers: .command)
   201→            Button("") { selectedTab = 1 }
   202→                .keyboardShortcut("2", modifiers: .command)
   203→            Button("") { selectedTab = 2 }
   204→                .keyboardShortcut("3", modifiers: .command)
   205→            Button("") { selectedTab = 3 }
   206→                .keyboardShortcut("4", modifiers: .command)
   207→            Button("") { selectedTab = 4 }
   208→                .keyboardShortcut("5", modifiers: .command)
   209→        }
   210→        .frame(width: 0, height: 0)
   211→        .opacity(0)
   212→    }
   213→}
   214→
   215→// MARK: - Safe Array Access
   216→extension Array {
   217→    subscript(safe index: Int) -> Element? {
   218→        indices.contains(index) ? self[index] : nil
   219→    }
   220→}
   221→
   222→#Preview("iPhone") {
   223→    MainTabView()
   224→        .environmentObject(DataManager.shared)
   225→        .environmentObject(QuickActionManager())
   226→}
   227→
   228→#Preview("iPad") {
   229→    MainTabView()
   230→        .environmentObject(DataManager.shared)
   231→        .environmentObject(QuickActionManager())
   232→        .previewDevice("iPad Pro (12.9-inch)")
   233→}
   234→

<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>

//
//  MainTabView.swift
//  ProductivityHub-iOS
//
//  Adaptive navigation: TabView on iPhone, NavigationSplitView on iPad/Mac
//  Optimized for "Designed for iPad" on Mac
//

import SwiftUI

// MARK: - Navigation Item Enum
enum NavigationItem: String, CaseIterable, Identifiable {
    case focus = "Focus"
    case tasks = "Tasks"
    case journal = "Journal"
    case insights = "Insights"
    case settings = "Settings"

    var id: String { rawValue }

    var icon: String {
        switch self {
        case .focus: return "timer"
        case .tasks: return "checklist"
        case .journal: return "book.fill"
        case .insights: return "chart.bar.fill"
        case .settings: return "gearshape.fill"
        }
    }

    var subtitle: String {
        switch self {
        case .focus: return "Deep work & Pomodoro"
        case .tasks: return "Manage your tasks"
        case .journal: return "Daily reflections"
        case .insights: return "Track your progress"
        case .settings: return "App preferences"
        }
    }

    var keyboardShortcut: KeyEquivalent {
        switch self {
        case .focus: return "1"
        case .tasks: return "2"
        case .journal: return "3"
        case .insights: return "4"
        case .settings: return "5"
        }
    }
}

// MARK: - Main Tab View
struct MainTabView: View {
    @EnvironmentObject var dataManager: DataManager
    @EnvironmentObject var quickActionManager: QuickActionManager
    @StateObject private var toastManager = ToastManager.shared
    @State private var selectedTab = 0
    @State private var selectedItem: NavigationItem? = .focus
    @State private var columnVisibility: NavigationSplitViewVisibility = .all

    @Environment(\.horizontalSizeClass) private var horizontalSizeClass

    var body: some View {
        Group {
            if horizontalSizeClass == .regular {
                // iPad / Mac: NavigationSplitView with Sidebar
                iPadNavigationView
            } else {
                // iPhone: Traditional TabView
                iPhoneTabView
            }
        }
        .toastView(toast: $toastManager.toast)
        .environmentObject(toastManager)
        // Handle quick actions from home screen
        .onReceive(quickActionManager.$selectedTab) { tab in
            selectedTab = tab
            selectedItem = NavigationItem.allCases[safe: tab] ?? .focus
        }
    }

    // MARK: - iPhone TabView
    private var iPhoneTabView: some View {
        TabView(selection: $selectedTab) {
            FocusView()
                .tabItem { Label("Focus", systemImage: "timer") }
                .tag(0)

            TasksView()
                .tabItem { Label("Tasks", systemImage: "checklist") }
                .tag(1)

            JournalView()
                .tabItem { Label("Journal", systemImage: "book.fill") }
                .tag(2)

            InsightsView()
                .tabItem { Label("Insights", systemImage: "chart.bar.fill") }
                .tag(3)

            SettingsView()
                .tabItem { Label("Settings", systemImage: "gearshape.fill") }
                .tag(4)
        }
        .accentColor(.blue)
        .background {
            KeyboardShortcutsView(selectedTab: $selectedTab)
        }
    }

    // MARK: - iPad/Mac NavigationSplitView
    private var iPadNavigationView: some View {
        NavigationSplitView(columnVisibility: $columnVisibility) {
            // Sidebar with enhanced styling for Mac
            List(NavigationItem.allCases, selection: $selectedItem) { item in
                NavigationLink(value: item) {
                    SidebarItemView(item: item, isSelected: selectedItem == item)
                }
                .keyboardShortcut(item.keyboardShortcut, modifiers: .command)
            }
            .navigationTitle("ProductivityHub")
            .listStyle(.sidebar)
            .navigationSplitViewColumnWidth(min: 220, ideal: 260, max: 320)
        } detail: {
            // Detail View with responsive container
            NavigationStack {
                GeometryReader { geometry in
                    detailView(for: selectedItem ?? .focus)
                        .frame(maxWidth: min(geometry.size.width, 900))
                        .frame(maxWidth: .infinity)
                }
            }
        }
        .navigationSplitViewStyle(.balanced)
    }

    // MARK: - Sidebar Item View
    struct SidebarItemView: View {
        let item: NavigationItem
        let isSelected: Bool

        var body: some View {
            HStack(spacing: 12) {
                Image(systemName: item.icon)
                    .font(.system(size: 18, weight: .medium))
                    .foregroundColor(isSelected ? .accentColor : .secondary)
                    .frame(width: 24)

                VStack(alignment: .leading, spacing: 2) {
                    Text(item.rawValue)
                        .font(.body)
                        .fontWeight(isSelected ? .semibold : .regular)

                    Text(item.subtitle)
                        .font(.caption)
                        .foregroundColor(.secondary)
                }

                Spacer()

                // Keyboard shortcut hint
                Text("⌘\(item.keyboardShortcut.character)")
                    .font(.caption2)
                    .foregroundColor(Color(UIColor.tertiaryLabel))
                    .padding(.horizontal, 6)
                    .padding(.vertical, 2)
                    .background(Color.secondary.opacity(0.1))
                    .cornerRadius(4)
            }
            .padding(.vertical, 6)
            .contentShape(Rectangle())
        }
    }

    // MARK: - Detail View Router
    @ViewBuilder
    private func detailView(for item: NavigationItem) -> some View {
        switch item {
        case .focus:
            FocusView()
        case .tasks:
            TasksView()
        case .journal:
            JournalView()
        case .insights:
            InsightsView()
        case .settings:
            SettingsView()
        }
    }
}

// MARK: - Keyboard Shortcuts (iPhone fallback)
struct KeyboardShortcutsView: View {
    @Binding var selectedTab: Int

    var body: some View {
        Group {
            Button("") { selectedTab = 0 }
                .keyboardShortcut("1", modifiers: .command)
            Button("") { selectedTab = 1 }
                .keyboardShortcut("2", modifiers: .command)
            Button("") { selectedTab = 2 }
                .keyboardShortcut("3", modifiers: .command)
            Button("") { selectedTab = 3 }
                .keyboardShortcut("4", modifiers: .command)
            Button("") { selectedTab = 4 }
                .keyboardShortcut("5", modifiers: .command)
        }
        .frame(width: 0, height: 0)
        .opacity(0)
    }
}

// MARK: - Safe Array Access
extension Array {
    subscript(safe index: Int) -> Element? {
        indices.contains(index) ? self[index] : nil
    }
}

#Preview("iPhone") {
    MainTabView()
        .environmentObject(DataManager.shared)
        .environmentObject(QuickActionManager())
}

#Preview("iPad") {
    MainTabView()
        .environmentObject(DataManager.shared)
        .environmentObject(QuickActionManager())
        .previewDevice("iPad Pro (12.9-inch)")
}