# Setup Logger (file rotation + console)

Fuente conceptual: MiroFish `backend/app/utils/logger.py` (AGPL-3.0)
Reimplementar desde cero. No copiar codigo.

## Funcion a implementar

### setup_logger

- **Dominio:** infra
- **Lang:** Python
- **Purity:** impure (crea archivos, modifica estado global de logging)
- **Signature:** `setup_logger(name: str = "app", log_dir: str = "logs", level: int = logging.DEBUG) -> logging.Logger`
- **Descripcion:** Configura un logger con dual output: archivo con rotacion diaria (detallado, DEBUG+) y consola (simple, INFO+). Maneja encoding UTF-8 en Windows.
- **Algoritmo:**
  1. Crear log_dir si no existe
  2. Crear logger con `logging.getLogger(name)`
  3. `propagate = False` (evitar duplicados en root logger)
  4. Si ya tiene handlers: retornar (idempotente)
  5. Formato detallado (archivo): `[%(asctime)s] %(levelname)s [%(name)s.%(funcName)s:%(lineno)d] %(message)s`
  6. Formato simple (consola): `[%(asctime)s] %(levelname)s: %(message)s`
  7. File handler: `RotatingFileHandler` con nombre `YYYY-MM-DD.log`, maxBytes=10MB, backupCount=5, encoding=utf-8
  8. Console handler: `StreamHandler(sys.stdout)`, level=INFO
  9. En Windows: `sys.stdout.reconfigure(encoding='utf-8', errors='replace')` para evitar mojibake
- **Deps:** `logging`, `logging.handlers`, `os`, `sys`, `datetime`
- **Tests:** logger se crea con 2 handlers, segundo call no duplica handlers, archivo se crea en log_dir
- **Companion:**
  ```python
  def get_logger(name: str = "app") -> logging.Logger:
      """Get or create logger."""
      logger = logging.getLogger(name)
      return logger if logger.handlers else setup_logger(name)
  ```
