# Media Reference Migration Guide

This guide explains how to migrate existing seeded data from old URL formats to the new `MediaReference` format.

## Problem

Old seeded data stores media references as URL strings:
- `/api/avatar/{driverId}`
- `/api/media/teams/{teamId}/logo`
- `/api/media/leagues/{leagueId}/logo`

New format uses `MediaReference` objects:
```json
{
  "type": "system-default",
  "variant": "avatar",
  "avatarVariant": "male"
}
```

## Solutions

### Option 1: Migration Script (Preserve Data)

**Best for:** Production databases or when you need to preserve existing data

```bash
# Test what would change (dry run)
npm run migrate:media:test

# Execute the migration
npm run migrate:media:exec
```

**What it does:**
- Converts `/api/avatar/{id}` → `system-default` with deterministic variant
- Converts `/api/media/teams/{id}/logo` → `generated`
- Converts `/api/media/leagues/{id}/logo` → `generated`
- Handles unknown formats → `none`
- Skips already-migrated entries

**Environment variables:**
- `GRIDPILOT_API_PERSISTENCE=postgres|inmemory` (default: postgres)
- `DATABASE_URL` (required for postgres)

### Option 2: Wipe and Reseed (Clean Slate)

**Best for:** Development/testing when you don't care about existing data

```bash
# Stop services and remove all volumes
npm run docker:dev:clean

# Rebuild and start fresh
npm run docker:dev:build
```

**What it does:**
- Deletes all existing data
- Runs fresh seed with correct `MediaReference` format
- No migration needed

## Migration Script Details

### Supported Old Formats

| Old Format | New Reference | Example |
|------------|---------------|---------|
| `/api/avatar/{id}` | `system-default` (deterministic) | `/api/avatar/driver-1` → `male`/`female`/`neutral` |
| `/api/media/teams/{id}/logo` | `generated` | `/api/media/teams/team-1/logo` → `generated:team-team-1` |
| `/api/media/leagues/{id}/logo` | `generated` | `/api/media/leagues/league-1/logo` → `generated:league-league-1` |
| `/images/avatars/male-default-avatar.jpg` | `system-default` (male) | Static files → `system-default` |
| `https://external.com/...` | `none` | External URLs → `none` |
| Empty/null | `none` | Missing values → `none` |

### Deterministic Avatar Selection

Driver avatars use a hash-based selection for consistency:
```typescript
const hash = hashCode(driverId);
const variantIndex = Math.abs(hash) % 3;
// 0 → male, 1 → female, 2 → neutral
```

This ensures the same driver ID always gets the same avatar variant.

### What Gets Updated

**Driver entities:**
- `avatarRef` field (JSONB column)

**Team entities:**
- `logoRef` field (JSONB column)

**League entities:**
- `logoRef` field (JSONB column)

### Safety Features

1. **Dry Run Mode:** Default behavior shows changes without applying them
2. **Validation:** Only updates entries with invalid or missing references
3. **Error Handling:** Continues on individual errors, reports all failures
4. **Idempotent:** Safe to run multiple times

## Testing the Migration

Test the migration logic without touching real data:

```bash
# Run test script
npm run migrate:media:test
```

This will show you:
- How each URL format is parsed
- What MediaReference it becomes
- Deterministic avatar variants for sample IDs

## When to Use Each Option

### Use Migration Script When:
- ✅ You have production data to preserve
- ✅ You want to see what changes will be made
- ✅ You need a controlled, reversible process
- ✅ You're migrating a live database

### Use Wipe and Reseed When:
- ✅ You're in development/testing
- ✅ You don't care about existing data
- ✅ You want the fastest path to a clean state
- ✅ You're setting up a new environment

## Troubleshooting

### Migration fails with "DATABASE_URL required"
Set the environment variable:
```bash
export DATABASE_URL=postgresql://user:pass@localhost:5432/dbname
```

### Some entries weren't migrated
Check the error output. Common issues:
- Invalid URL format (will be converted to `none`)
- Already valid MediaReference (skipped)
- Database connection issues

### Want to rollback
The migration only updates entries that need it. To rollback:
1. Restore from database backup
2. Or manually revert the `avatarRef`/`logoRef` fields

## Example Migration Output

```
[INFO] Starting media reference migration in DRY RUN mode
[INFO] Persistence mode: postgres
[INFO] Connecting to PostgreSQL database...
[INFO] Database connection established
[INFO] Found 150 drivers to migrate
[INFO] Found 25 teams to migrate
[INFO] Found 5 leagues to migrate
[INFO] Migration completed: 150 drivers, 25 teams, 5 leagues updated

=== Migration Summary ===
Mode: DRY RUN
Processed: 150 drivers, 25 teams, 5 leagues
Updated: 150 drivers, 25 teams, 5 leagues

✅ Dry run completed successfully. Run with --execute to apply changes.
```

## Next Steps

After migration:
1. Verify data integrity in the database
2. Test that avatars and logos render correctly
3. Update any hardcoded URL references in the frontend
4. Remove any legacy URL construction code