# Item-to-Sport Linking Implementation Summary

## What Was Implemented

I've implemented automatic linking between `Item` (training sessions) and `ISTSport` models. When a new Item is added to SwiftData, it will now automatically link to an existing ISTSport or create a new one if needed.

**Note:** This implementation is designed for new SwiftData stores and does not include migration tooling for existing databases.

## Files Modified

### 1. **Item.swift**
- ✅ Added `istSport: ISTSport?` relationship property
- ✅ Added `linkToSport(modelContext:)` method for manual linking
- ✅ Added `createSportFromName(_:modelContext:)` private helper method
- ✅ Added static `create(in:...)` factory method for automatic linking
- ✅ Added comprehensive documentation at the top of the file

### 2. **ISTSport.swift**
- ✅ Added inverse relationship: `items: [Item]?`
- ✅ Configured with `.nullify` delete rule (deleting a sport won't delete items)

### 3. **DataManager.swift**
- ✅ Updated `ItemManager.create(_:)` to auto-link sports

## How It Works

### Automatic Sport Creation Flow

```
New Item Created
      ↓
Search for ISTSport with matching name (case-insensitive)
      ↓
   Found? ─YES→ Link to existing sport
      ↓
     NO
      ↓
Search PredefinedSports library
      ↓
   Found? ─YES→ Create sport with predefined colors/icons
      ↓
     NO
      ↓
Create generic sport with gray color and default icon
      ↓
Link Item to the sport
```

### Key Features

1. **Case-Insensitive Matching**: "Running", "running", "RUNNING" all link to the same sport
2. **Predefined Sports**: 150+ sports with proper colors and icons
3. **Unknown Sports**: Automatically handled with generic styling
4. **Bidirectional Relationships**: Navigate from Item→Sport and Sport→Items

## Usage Examples

### Creating New Items

**Recommended Approach:**
```swift
let item = try Item.create(
    in: modelContext,
    timestamp: Date(),
    distance: Measurement(value: 10, unit: .kilometers),
    duration: 3600,
    start: Date(),
    sport: "Running"
)
modelContext.insert(item)
try modelContext.save()
```

**Using ItemManager:**
```swift
let itemManager = ItemManager(context: modelContext)

// Create item normally - ItemManager auto-links
let item = Item(
    timestamp: Date(),
    distance: Measurement(value: 5, unit: .miles),
    duration: 1800,
    start: Date(),
    sport: "Swimming"
)
try itemManager.create(item)  // Automatically links to sport
```

### Accessing Relationships

**Item to Sport:**
```swift
if let sport = item.istSport {
    print("Sport: \(sport.name)")
    Image(systemName: sport.iconName)
        .foregroundStyle(sport.color)
}
```

**Sport to Items:**
```swift
if let items = sport.items {
    print("\(sport.name) has \(items.count) activities")
}
```

## Integration Steps

### Step 1: Update ModelContainer
Make sure your ModelContainer includes both models:

```swift
let container = try ModelContainer(
    for: Item.self, ISTSport.self, User.self
)
```

### Step 2: Use Item.create() for New Items
When creating Items, use the factory method:

```swift
let item = try Item.create(
    in: modelContext, 
    timestamp: Date(), 
    distance: ..., 
    sport: "Running"
)
modelContext.insert(item)
try modelContext.save()
```

### Step 3: Update UI
You can now use the sport relationship in your UI:

```swift
struct ActivityRow: View {
    let item: Item
    
    var body: some View {
        HStack {
            // Sport icon and color
            if let sport = item.istSport {
                Image(systemName: sport.iconName)
                    .foregroundStyle(sport.color)
            }
            
            VStack(alignment: .leading) {
                Text(item.sport)
                    .font(.headline)
                Text(item.distance?.formatted() ?? "")
                    .font(.subheadline)
            }
        }
    }
}
```

## SwiftData Schema Considerations

### Relationships
- **Item.istSport**: Optional (nullable) relationship
- **ISTSport.items**: Optional array with inverse relationship
- **Delete Rule**: `.nullify` - safe for data integrity

### Performance
- Minimal overhead (one query per Item creation)
- Sports are cached in SwiftData's internal cache
- Batch imports should batch saves, not individual sport lookups

## Testing

### Unit Tests
```swift
@Test("Item creates sport automatically")
func testAutoSportCreation() async throws {
    let container = try ModelContainer(for: Item.self, ISTSport.self, inMemory: true)
    let context = ModelContext(container)
    
    let item = try Item.create(
        in: context,
        timestamp: Date(),
        distance: Measurement(value: 10, unit: .kilometers),
        duration: 3600,
        start: Date(),
        sport: "Running"
    )
    
    #expect(item.istSport != nil)
    #expect(item.istSport?.name == "Running")
    
    // Verify it's in the database
    let sports = try context.fetch(FetchDescriptor<ISTSport>())
    #expect(sports.count == 1)
    #expect(sports.first?.name == "Running")
}

@Test("Multiple items link to same sport")
func testMultipleItemsSameSport() async throws {
    let container = try ModelContainer(for: Item.self, ISTSport.self, inMemory: true)
    let context = ModelContext(container)
    
    let item1 = try Item.create(in: context, ..., sport: "Running")
    let item2 = try Item.create(in: context, ..., sport: "Running")
    
    // Both should link to the same sport
    #expect(item1.istSport === item2.istSport)
    
    // Only one sport should be created
    let sports = try context.fetch(FetchDescriptor<ISTSport>())
    #expect(sports.count == 1)
}
```

## Troubleshooting

### Issue: Items not linking
**Solution:** Make sure you're using `Item.create()`:
```swift
// Use the factory method
let item = try Item.create(in: modelContext, ...)
```

### Issue: Duplicate sports
**Solution:** Sport names might have whitespace differences. The code trims whitespace automatically, but verify sport names are consistent.

### Issue: Wrong sport icons/colors
**Solution:** Edit the sport in the Sports UI or update PredefinedSports.swift

## Questions?

Refer to:
- **Item.swift** - Implementation details and inline documentation
- **PredefinedSports.swift** - List of available predefined sports

The implementation is complete and ready to use! 🎉
