# Документация модуля Profiles (Профили пользователей)

## Введение

Модуль `Knot.Modules.Profiles` отвечает за управление публичными данными пользователей, их аватарами и настройками отображения в мессенджере Knot Messager. 

### Разделение ответственности (Auth vs Profiles)
В соответствии с принципами **DDD (Domain-Driven Design)** и **Чистой Архитектуры**, модуль Profiles отделен от модуля Auth:
*   **Auth (Postgres):** Занимается идентификацией (логин, пароль, токены, email).
*   **Profiles (MongoDB + S3):** Занимается представлением пользователя (имя, био, аватар, настройки видимости). 

Это разделение позволяет изменять структуру профиля (добавлять новые социальные ссылки, поля "О себе") без выполнения миграций в основной реляционной БД.

---

## Архитектура хранения данных (Гибридный подход)

Модуль использует **гибридную схему хранения**, оптимизированную для производительности и гибкости:

1.  **Metadata (MongoDB):** Документ `ProfileDocument` содержит все текстовые данные профиля. Использование NoSQL позволяет легко расширять схему данных.
2.  **Media (S3/MinIO):** Файлы аватаров хранятся во внешнем объектном хранилище. В MongoDB хранится только `AvatarUrl` (ссылка на файл).
3.  **Identity Link (UserId):** Поле `Id` в MongoDB-документе совпадает с `UserId` из PostgreSQL. Это единственный ключ для связи модулей.

---

## Доменная модель

### ProfileDocument (Aggregate Root)
Основная сущность в модуле. Находится в слое `Domain`.
*   **Username:** Уникальный хендл пользователя.
*   **DisplayName:** Публичное имя (может меняться).
*   **Bio:** Короткая биографическая справка.
*   **AvatarUrl:** Путь к файлу в формате `/api/files/{fileId}`.
*   **HideStoryViews:** Флаг приватности (скрывать просмотр сторис от других).

### Доменные события
Модуль генерирует и слушает события для обеспечения согласованности:
*   `UserRegisteredDomainEvent`: Слушается модулем Profiles (от Auth). При получении создается начальный документ профиля в MongoDB.
*   `ProfileAvatarChangedDomainEvent`: Генерируется при смене аватара (для потенциальной очистки кэша).

---

## Ключевые возможности

### 1. Управление аватарами
Модуль предоставляет эндпоинты для загрузки и удаления аватаров:
*   **Автоматическое кадрирование:** При вызове `/avatar/crop` используется библиотека `ImageSharp` для вырезания области изображения и ресайза до `400x400` пикселей в формате JPEG.
*   **Авто-очистка:** При загрузке нового аватара модуль автоматически удаляет старый файл из S3, предотвращая появление "файлов-сирот".

### 2. Поиск пользователей
Реализован через `ProfileRepository` с использованием регулярных выражений MongoDB (case-insensitive) по полям `Username` и `DisplayName`.

### 3. Настройки приватности
Пользователь может управлять отображением своей активности (например, `HideStoryViews`), что сохраняется непосредственно в документе профиля.

---

## Структура проекта

```text
Knot.Modules.Profiles/
├── Application/
│   ├── Abstractions/             # Интерфейсы IProfileRepository, IAvatarStorageService
│   ├── Profiles/                 # Case-обработчики (Handlers)
│   │   ├── Avatar/               # Загрузка, обрезка, удаление аватара
│   │   ├── GetUser/              # Получение данных профиля
│   │   ├── Search/               # Поиск по базе профилей
│   │   └── UpdateProfile/        # Обновление текстовых данных
│   └── Integration/              # Обработчики событий от других модулей
├── Domain/
│   ├── ProfileDocument.cs        # Корень агрегата (Mongo Document)
│   └── Events/                   # Доменные события
├── Infrastructure/
│   └── Database/                 # Реализация репозиториев для MongoDB и S3
├── Presentation/
│   └── Endpoints/                # Carter-модули (API эндпоинты)
└── DependencyInjection.cs        # Регистрация сервисов и MongoDB клиента
```

---

## Технические детали реализации

### Интеграция с S3 (MinIO)
В модуле реализован адаптер `AvatarStorageService`, который инкапсулирует работу с `IFileStorageService`. Он отвечает за:
1.  Генерацию уникальных ключей файлов.
2.  Шифрование контента (через Shared Infrastructure).
3.  Очистку путей (преобразование URL в ID файла для удаления).

### Настройка MongoDB
Репозиторий `ProfileRepository` использует типизированную коллекцию `IMongoCollection<ProfileDocument>`. Первичный ключ `Id` мапится как строка (BsonType.String) для совместимости с `Guid` из .NET.

---

## API Эндпоинты (Примеры)

| Метод | Путь | Описание |
| :--- | :--- | :--- |
| `GET` | `/api/profiles/{id}` | Получить данные профиля пользователя. |
| `GET` | `/api/profiles/search?q=text` | Найти пользователей по имени или никнейму. |
| `PUT` | `/api/profiles/profile` | Обновить DisplayName, Bio, Birthday. |
| `POST` | `/api/profiles/avatar` | Простая загрузка аватара (FormFile). |
| `POST` | `/api/profiles/avatar/crop` | Загрузка с указанием координат обрезки (x, y, w, h). |
| `DELETE` | `/api/profiles/avatar` | Удаление текущего аватара и файла из S3. |
| `PUT` | `/api/profiles/settings` | Обновить настройки приватности профиля. |
