# OOTD POC Server

## Quick Reference
- Python 3.10, FastAPI, SQLAlchemy 2.0 (async), PostgreSQL 14, pgvector
- Virtual env: `.venv/` (activate with `source .venv/bin/activate`)
- DB: `ootd_poc` on localhost:5432, user `postgres`
- Run server: `uvicorn app.main:app --reload --host 0.0.0.0 --port 8000`
- Run tests: `pytest tests/ -v`
- Run linter: `ruff check app/ tests/`
- Run migrations: `alembic upgrade head`

## Architecture
- `app/` - FastAPI application
  - `routers/` - Route handlers (thin, delegate to services)
    - `garment.py` - Unified garment endpoints (analyze, style-analyze, save, ghost, ghost-preview, list, CRUD, bulk)
    - `face.py` - Face register/identify/delete
    - `user.py` - User listing + deletion (cascade)
    - `vton.py` - Virtual try-on (composite garments onto a person image)
    - `segmentation.py` - Background removal (누끼)
    - `admin.py` - Full reset + orphan file cleanup
    - `health.py` - Health check
  - `models/` - SQLAlchemy ORM models (async, Mapped style)
  - `schemas/` - Pydantic v2 request/response models
  - `services/` - Business logic layer
    - `llm/` - LLM provider abstraction (Gemini / OpenAI, switchable via LLM_PROVIDER env)
    - `user_service.py` - get_or_create_user (shared by user router + face_service)
    - `garment_service.py` - analyze_only / analyze_and_save / save_garments / generate_ghost / generate_ghost_preview / analyze_style
    - `vton_service.py` - Virtual try-on pipeline (face check → DB fetch → multi-image LLM → save)
    - `wardrobe_service.py` - list with optional user_id (cross-user queries)
  - `utils/` - Utilities (image handling, face analyzer)
- `frontend/` - Demo web app (vanilla HTML/CSS/JS, served at `/`)
- `storage/` - Local image storage (faces/, originals/, ghost_mannequin/, segmentation/, vton/)
- `alembic/` - Database migrations
- `tests/http/` - VS Code REST Client test files
- `tests/fixtures/` - Test images
- `tests/` - pytest tests

## Key Conventions
- All DB operations use async SQLAlchemy sessions
- Face embeddings stored as VECTOR(512) via pgvector, searched with cosine distance (<=>)
- Clothing tags stored as JSONB (English values), filtered via PostgreSQL @> operator
- LLM provider selected by `LLM_PROVIDER` env var ("gemini" or "openai")
- Ghost mannequin mode selected by `MANNEQUIN_MODE` env var ("edit" or "generate")
- Image paths stored as relative paths in DB, served via FastAPI static mount at `/storage`
- Garment description in Korean, tag values in English
- UUID primary keys on all tables
- "unknown" user (UUID 00000000-...) used as fallback when FaceID is off or fails — identified by fixed UUID, not a flag
- face_status values: "known" (매칭 성공), "unknown" (미등록 얼굴), "not_detected" (얼굴 없음), "not_used" (FaceID 미사용)
- Tests use transaction rollback for DB isolation — test data is never persisted

## Commands
- `sudo -u postgres psql ootd_poc` - connect to database
- `alembic revision --autogenerate -m "description"` - create migration
- `alembic upgrade head` - apply migrations
- `pip install -r requirements.txt` - install dependencies

## Environment Variables (.env)
- DATABASE_URL, LLM_PROVIDER, MANNEQUIN_MODE
- GEMINI_API_KEY, OPENAI_API_KEY
- OPENAI_IMAGE_MODEL (default "gpt-image-2") — default image model for ghost/VTON; per-request override via `image_model` param
- FACE_MATCH_THRESHOLD (default 0.5)
- UPLOAD_DIR (default "storage")

## LLM Models
- Gemini: `gemini-3.1-flash-image-preview` (Vision/Analysis + Image Generation)
- OpenAI: `gpt-5.4` (Chat Completions for Vision) + `gpt-5.4` (Responses API image_generation for Ghost)
- Ghost mannequin: 원본 이미지를 전달하여 옷만 추출 (edit mode)
- Style analysis: 동일 Vision 모델로 코디 스타일 평가 (색상/핏/디테일 점수)

## API Endpoints
- `GET  /api/v1/users` - List users with garment counts
- `POST /api/v1/users` - Get-or-create user by name (unique, returns user_id)
- `DELETE /api/v1/users/{id}` - Delete user + cascade all data + files
- `POST /api/v1/faces/register` - Register face (name required, face match priority → get-or-create fallback)
- `POST /api/v1/faces/identify` - Identify user from face
- `DELETE /api/v1/faces/{user_id}` - Delete all face embeddings + images for user
- `POST /api/v1/garments/analyze` - Upload + LLM analysis + tagging (unified: user_id, use_face_id, face_status, auto_save)
  - `auto_save=true` (default): analyze + save to DB (기존 동작)
  - `auto_save=false`: analyze only, returns source_image_path for /save and /ghost-preview
- `POST /api/v1/garments/style-analyze` - Style analysis (color palette, silhouette, detail scores + overall evaluation)
- `POST /api/v1/garments/save` - Save analyzed garments to DB (after analyze with auto_save=false)
- `POST /api/v1/garments/ghost-preview` - Ghost mannequin preview without DB record (stateless)
- `POST /api/v1/garments/{id}/ghost` - Generate ghost mannequin (slow, requires DB record)
- `GET  /api/v1/garments` - List garments (optional user_id filter for cross-user queries)
- `GET  /api/v1/garments/{id}` - Garment detail
- `PATCH /api/v1/garments/bulk` - Bulk reassign garments to user
- `PATCH /api/v1/garments/{id}` - Reassign single garment to user
- `DELETE /api/v1/garments/{id}` - Delete garment
- `POST /api/v1/vton/generate` - Virtual try-on: 인물 이미지 + 옷장 garment_ids → 합성 결과 URL (얼굴 필수, ghost_image_path 필수, 상반신 이미지에 하의 포함 시 LLM이 자동 skip)
- `DELETE /api/v1/admin/reset` - Full reset (DB + storage, keeps unknown user)
- `POST /api/v1/admin/cleanup` - Find/delete orphaned files (dry_run=true by default)

## User Creation & Identification
- User creation goes through a single get-or-create path (user_service.get_or_create_user)
- Both POST /users and POST /faces/register use this same path to prevent duplicate users
- Face register: face match takes priority → if no match, falls back to get-or-create by name
- Frontend api.js exposes name-based high-level functions; UUID is internal only

## Implementation Status
- [x] Phase 1: Skeleton + DB (models, migrations, global user seed, health check)
- [x] Phase 2: Face endpoints (insightface buffalo_l + pgvector cosine search)
- [x] Phase 3: LLM + Analysis (Gemini 2.5 Flash / GPT-5.4 + Gemini 2.0 Flash / GPT-5.4 Responses API)
- [x] Phase 4: Wardrobe CRUD (list/filter/pagination with JSONB tag filtering)
- [x] Phase 5: Polish (error handling middleware, structured logging, pytest 17 tests, E2E HTTP tests)
- [x] Phase 6: API redesign (unified analyze with face_status, separate ghost generation, cross-user queries, PATCH reassign, frontend demo app)
- [x] Phase 7: Simplification (is_global 제거 → unknown user by UUID, face_status 값 통일, 프론트엔드 name 기반 API, 테스트 트랜잭션 격리)
- [x] Phase 8: Style analysis (LLM 기반 코디 스타일 평가 API + v5 프론트엔드 with FaceID 분석 탭)
- [x] Phase 9: VTON (멀티-이미지 LLM 기반 가상 피팅, stateless + v7 프론트엔드 with VTON 탭)
