# Follow Team Mode Design

## Overview

Add a 4th trip planning mode called "Follow Team" where users select a team, regions, and date range to build trips around that team's schedule (both home and away games).

## User Flow

1. Select "Follow Team" mode
2. Pick a team (grouped by sport for browsing)
3. Select regions (East/Central/West)
4. Pick date range
5. Choose whether to start/end from home location or fly-in/fly-out
6. Plan trip

## Scope

**Included:**
- Single team selection
- Both home and away games
- Region filtering (same as existing modes)
- Date range filtering
- Flexible start/end: home location OR first-game-to-last-game
- Respect `allowRepeatCities` toggle

**Not included (future):**
- Multiple teams (rivalry trips)
- Opponent filtering
- Win/loss context display

## Data Model Changes

### PlanningMode Extension

```swift
enum PlanningMode: String, Codable, CaseIterable, Identifiable {
    case dateRange      // Scenario A - dates first
    case gameFirst      // Scenario B - pick games
    case locations      // Scenario C - start/end cities
    case followTeam     // Scenario D - follow one team

    var displayName: String {
        switch self {
        case .dateRange: return "By Dates"
        case .gameFirst: return "By Games"
        case .locations: return "By Route"
        case .followTeam: return "Follow Team"
        }
    }

    var description: String {
        switch self {
        case .dateRange: return "Shows a curated sample of possible routes"
        case .gameFirst: return "Build trip around specific games"
        case .locations: return "Plan route between locations"
        case .followTeam: return "Follow your team on the road"
        }
    }

    var iconName: String {
        switch self {
        case .dateRange: return "calendar"
        case .gameFirst: return "sportscourt"
        case .locations: return "map"
        case .followTeam: return "person.3.fill"
        }
    }
}
```

### TripPreferences Addition

```swift
struct TripPreferences {
    // ... existing properties ...

    /// Team to follow (for Follow Team mode)
    var followTeamId: UUID?

    /// Whether to start/end from a home location (vs fly-in/fly-out)
    var useHomeLocation: Bool = true
}
```

### PlanningScenario Extension

```swift
enum PlanningScenario: Equatable {
    case scenarioA  // Date range
    case scenarioB  // Selected games
    case scenarioC  // Start/end locations
    case scenarioD  // Follow team
}
```

## ScenarioDPlanner Logic

### Core Algorithm

```swift
actor ScenarioDPlanner {
    func plan(request: PlanningRequest) async throws -> ItineraryResult {
        // 1. Filter games to selected team only
        let teamGames = filterToTeam(
            request.allGames,
            teamId: request.preferences.followTeamId
        )

        // 2. Apply region filter
        let regionalGames = filterByRegion(
            teamGames,
            regions: request.preferences.selectedRegions,
            stadiums: request.stadiums
        )

        // 3. Apply date range
        let dateFilteredGames = filterByDateRange(
            regionalGames,
            start: request.preferences.startDate,
            end: request.preferences.endDate
        )

        // 4. Apply repeat city constraint
        let finalGames = applyRepeatCityFilter(
            dateFilteredGames,
            allowRepeat: request.preferences.allowRepeatCities,
            stadiums: request.stadiums
        )

        // 5. Build route (with or without home location)
        if request.preferences.useHomeLocation,
           let startLocation = request.startLocation {
            // Round-trip from home
            return buildRouteFromHome(finalGames, start: startLocation)
        } else {
            // Fly-in / fly-out (first game to last game)
            return buildPointToPointRoute(finalGames)
        }
    }
}
```

### Team Game Filtering

A game belongs to the followed team if they're home OR away:

```swift
func filterToTeam(_ games: [Game], teamId: UUID?) -> [Game] {
    guard let teamId else { return [] }
    return games.filter { game in
        game.homeTeamId == teamId || game.awayTeamId == teamId
    }
}
```

### Repeat City Handling

When `allowRepeatCities = false`, keep only one game per city:

```swift
func applyRepeatCityFilter(_ games: [Game], allowRepeat: Bool, stadiums: [UUID: Stadium]) -> [Game] {
    guard !allowRepeat else { return games }

    var seenCities: Set<String> = []
    return games.filter { game in
        guard let stadium = stadiums[game.stadiumId] else { return false }
        if seenCities.contains(stadium.city) { return false }
        seenCities.insert(stadium.city)
        return true
    }
}
```

## UI Changes

### Mode Selector

Expand to 4 modes in a 2x2 grid:

```swift
var planningModeSection: some View {
    LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 12) {
        ForEach(PlanningMode.allCases) { mode in
            PlanningModeCard(
                mode: mode,
                isSelected: viewModel.planningMode == mode,
                action: { viewModel.planningMode = mode }
            )
        }
    }
}
```

### Follow Team Mode Sections

```swift
case .followTeam:
    teamPickerSection      // Select team (grouped by sport)
    regionSection          // East/Central/West
    datesSection           // Start/end dates
    homeLocationToggle     // "Start from home?" toggle
    locationSection        // Conditional: Only if toggle is on
```

### Team Picker Section

```swift
var teamPickerSection: some View {
    Section("Select Team") {
        Picker("Team", selection: $viewModel.followTeamId) {
            Text("Choose a team").tag(nil as UUID?)
            ForEach(teamsByLeague) { league in
                Section(league.name) {
                    ForEach(league.teams) { team in
                        Text(team.name).tag(team.id as UUID?)
                    }
                }
            }
        }
    }
}
```

### Home Location Toggle

```swift
var homeLocationToggle: some View {
    Toggle("Start and end from home", isOn: $viewModel.useHomeLocation)
        .toggleStyle(.switch)
}
```

## Validation Rules

```swift
var followTeamValidation: String? {
    guard viewModel.followTeamId != nil else {
        return "Select a team to follow"
    }

    guard viewModel.endDate > viewModel.startDate else {
        return "End date must be after start date"
    }

    if viewModel.useHomeLocation && viewModel.startLocation == nil {
        return "Enter your home location"
    }

    return nil
}
```

## Edge Cases

| Case | Behavior |
|------|----------|
| No games in range | Show: "No [Team] games found in [Region] between [dates]" |
| All games in one city | Valid single-stop trip |
| Repeat city + toggle off | Keep first game in each city, skip duplicates |
| Back-to-back different cities | Existing driving constraints handle feasibility |
| No start location but toggle on | Block submission with validation message |

## Planning Failures

Reuse existing `PlanningFailure` reasons:
- `.noGamesInRange` — No team games in date/region
- `.noValidRoutes` — Can't build feasible route
- `.repeatCityViolation` — Would require repeat city but toggle is off

## Implementation Plan

### Files to Create

```
SportsTime/Planning/Engine/ScenarioDPlanner.swift
SportsTimeTests/Planning/ScenarioDPlannerTests.swift
```

### Files to Modify

```
SportsTime/Core/Models/Domain/TripPreferences.swift
SportsTime/Planning/Models/PlanningModels.swift
SportsTime/Planning/Engine/TripPlanningEngine.swift
SportsTime/Features/Trip/Views/TripCreationView.swift
SportsTime/Features/Trip/ViewModels/TripCreationViewModel.swift
```

### Implementation Order

1. Data model — Add properties to `TripPreferences`, add `scenarioD`
2. Planner — Create `ScenarioDPlanner`
3. Engine routing — Update `TripPlanningEngine` to route to Scenario D
4. ViewModel — Add state and validation
5. UI — Add team picker, toggle, mode card
6. Tests — Cover all edge cases

### Test Cases

- Happy path: Team with 5 games in region → valid route
- No games: Team has no games in range → proper failure
- Single city: All home games, repeat allowed → valid single-stop
- Repeat city blocked: Multiple home games, repeat off → keeps one
- With home location: Round-trip from user's city
- Without home location: Point-to-point first to last game
