# Models (app/models/)

## OVERVIEW
SQLModel/Pydantic models combining database tables (SQLModel) and API schemas (Pydantic). Each domain has a Base → Table → Schema pattern.

## STRUCTURE
```
models/
├── __init__.py        # Core: DownloadStatus, DownloadTask, DownloadRequest, AnimeMetadata, AnimeSearchResult
├── auth.py            # User, UserCreate, UserLogin, Token, UserTable, UserInDB
├── watchlist.py       # WatchlistItem, WatchlistSettings, AutoDownloadResult (+ Table variants)
├── sonarr.py          # SonarrWebhookPayload, SonarrMapping, SonarrConfig, SonarrSeries (+ Table variants)
├── favorites.py       # Favorites-related models
└── settings.py        # AppSettings, AppSettingsUpdate (+ Table variant)
```

## WHERE TO LOOK

| Need | File | Key Classes |
|------|------|-------------|
| Download task | `__init__.py` | `DownloadTask`, `DownloadStatus`, `DownloadRequest` |
| Anime metadata | `__init__.py` | `AnimeMetadata`, `AnimeSearchResult` |
| User/auth | `auth.py` | `User`, `UserCreate`, `UserLogin`, `Token`, `UserTable` |
| Watchlist | `watchlist.py` | `WatchlistItem`, `WatchlistSettings`, `WatchlistItemTable` |
| Sonarr | `sonarr.py` | `SonarrWebhookPayload`, `SonarrMapping`, `SonarrConfig`, `SonarrSeries` |
| App settings | `settings.py` | `AppSettings`, `AppSettingsUpdate` |

## CONVENTIONS

**Triple-class pattern** (for DB-backed models):
1. `*Base` — Pydantic base with shared fields
2. `*Table` — SQLModel table class (`__tablename__`, `id`, FK columns)
3. Final class — API schema (inherits from both, adds Config)

**Enums**: PascalCase class, UPPER_SNAKE values (e.g., `DownloadStatus.PENDING`, `WatchlistStatus.ACTIVE`).

**JSON columns**: Stored as JSON strings in SQLite, accessed via `@property` methods (e.g., `WatchlistItemTable.genres` parses `genres_json`).

**Config classes**: Each API schema has `class Config: from_attributes = True` for ORM mode.

## ANTI-PATTERNS

- Do NOT add new fields to `*Base` without updating corresponding `*Table` and schema classes
- Do NOT use `Optional` for required API fields — use Pydantic defaults
- Empty `except:` in `settings.py:22` — known tech debt
