# CRM Server API

Backend API pre email a kontaktný manažment s podporou viacerých JMAP účtov.

## Funkcie

### Autentifikácia
- **Login** - Session-based auth s JWT tokens (httpOnly cookies)
- **Onboarding** - 3-krokový flow (login → nastavenie hesla → pripojenie emailu)
- **Session management** - Automatický refresh tokenov
- **Role-based access** - Admin a Member

### Email účty (Multi-account)
- **Pridanie účtu** - Pripojenie viacerých JMAP účtov
- **Šifrovanie hesiel** - AES-256-GCM encryption pre JMAP heslá
- **Primárny účet** - Označenie hlavného účtu
- **Cascade delete** - Odstránenie účtu vymaže všetky jeho dáta

### JMAP Email integrácia
- **Sync emailov** - Stiahnutie emailov z Truemail.sk JMAP servera
- **Thread organizácia** - Emaily zoskupené do konverzácií
- **Full-text search** - Vyhľadávanie v predmete, tele, odosielateľovi
- **Posielanie odpovedí** - Odpoveď na emaily cez JMAP
- **Neprecítané správy** - Počítadlo per účet

### Kontakty
- **Objavovanie** - Automatické získanie odosielateľov z emailov
- **Auto-sync emailov** - Pri pridaní kontaktu sa stiahnu všetky jeho emaily
- **CRUD operácie** - Pridanie, úprava, odstránenie
- **Account filtering** - Kontakty izolované per email účet

### Správa používateľov (Admin)
- **Vytvorenie usera** - Auto-generovanie temporary hesla
- **Zmena rolí** - Admin/Member
- **Zoznam používateľov** - Len pre adminov

### Bezpečnosť
- **Password hashing** - Bcrypt (12 rounds)
- **Rate limiting** - Login, API, citlivé operácie
- **Helmet** - HTTP security headers (CSP, HSTS)
- **Input validation** - Zod schemas
- **SQL injection protection** - Drizzle ORM prepared statements
- **XSS protection** - Sanitizácia inputov
- **Audit logging** - Všetky dôležité akcie logované

## API Endpointy

### Autentifikácia `/api/auth`
- `POST /login` - Prihlásenie
- `POST /set-password` - Nastavenie hesla (onboarding)
- `POST /change-password` - Zmena hesla
- `POST /logout` - Odhlásenie
- `GET /session` - Získanie session info
- `GET /me` - Aktuálny používateľ

### Email účty `/api/email-accounts`
- `GET /` - Zoznam účtov
- `POST /` - Pridanie účtu
- `DELETE /:id` - Odstránenie účtu
- `PATCH /:id/primary` - Nastavenie primárneho

### Admin `/api/admin` (Admin only)
- `POST /users` - Vytvorenie používateľa
- `GET /users` - Zoznam používateľov
- `PATCH /users/:id/role` - Zmena role
- `DELETE /users/:id` - Zmazanie používateľa

### Kontakty `/api/contacts`
- `GET /` - Zoznam kontaktov (s accountId filtrom)
- `GET /discover` - Potenciálne kontakty z JMAP
- `POST /` - Pridať kontakt + auto-sync emailov
- `PATCH /:id` - Upraviť kontakt
- `DELETE /:id` - Odstrániť kontakt

### Emaily `/api/emails`
- `GET /` - Zoznam emailov (s accountId filtrom)
- `GET /search` - Vyhľadávanie v DB
- `GET /search-jmap` - JMAP full-text search
- `GET /thread/:id` - Thread konverzácie
- `POST /thread/:id/read` - Označiť thread ako prečítaný
- `POST /sync` - Manuálna synchronizácia
- `POST /reply` - Odpovedať na email
- `GET /unread-count` - Počet neprecítaných per účet

## Services

### auth.service.js
Správa autentifikácie a používateľov.

**Funkcie:**
- `getUserById(id)` - Získanie usera z DB podľa ID
- `getUserByUsername(username)` - Nájdenie usera podľa username
- `createUser(data)` - Vytvorenie nového usera s auto-generovaným temporary heslom
- `validatePassword(user, password)` - Validácia hesla (bcrypt compare s temp_password alebo password)
- `changePassword(userId, newPassword)` - Zmena hesla + audit log + update `changed_password = true`
- `updateLastLogin(userId)` - Update `last_login` timestamp

### email-account.service.js
Multi-account email management.

**Funkcie:**
- `getEmailAccounts(userId)` - Zoznam všetkých email účtov usera
- `addEmailAccount(userId, email, password)` - Pridanie JMAP účtu s validáciou credentials a šifrovaním hesla
- `getEmailAccountWithCredentials(accountId, userId)` - Účet s dešifrovaným heslom (pre JMAP operácie)
- `getPrimaryEmailAccount(userId)` - Vráti primárny účet usera
- `removeEmailAccount(accountId, userId)` - Odstránenie účtu + cascade delete kontaktov a emailov
- `setPrimaryAccount(accountId, userId)` - Nastavenie účtu ako primárneho (resetne ostatné)
- `verifyAccountOwnership(accountId, userId)` - Overenie že účet patrí userovi

### jmap.service.js
JMAP protokol integrácia s Truemail.sk.

**Core funkcie:**
- `jmapRequest(config, methodCalls)` - Low-level JMAP HTTP request (Basic Auth + JSON payload)
- `getJmapSession(config)` - Získanie JMAP session (capabilities, accountId, upload URL)
- `getJmapConfigFromAccount(accountId, userId)` - Vytvorenie JMAP config objektu z DB account

**Email operácie:**
- `syncEmailsFromJMAP(config, userId, accountId, filters)` - Stiahnutie emailov z JMAP a uloženie do DB
- `syncEmailsFromSender(config, userId, accountId, senderEmail, contactId)` - Sync všetkých emailov od konkrétneho odosielateľa
- `searchEmailsJMAP(config, query, limit, offset)` - Full-text search v JMAP serveri
- `sendEmail(config, emailAccountId, to, subject, body, inReplyTo)` - Vytvorenie a poslanie odpovede cez JMAP
- `markEmailAsRead(config, userId, jmapId, isRead)` - Update `$seen` keywordu na JMAP serveri

**Discovery:**
- `discoverContactsFromJMAP(config)` - Získanie všetkých unikátnych emailových adries z INBOX

**Helpers:**
- `parseJmapResponse(response)` - Parsovanie JMAP response a error handling
- `extractEmailAddress(emailObject)` - Extrahovanie email adresy z JMAP formátu `[{email: "..."}]`

### contact.service.js
Správa kontaktov s auto-sync funkciou.

**Funkcie:**
- `getUserContacts(userId, accountId?)` - Zoznam kontaktov usera (s voliteľným account filtrom)
- `getContactById(contactId, userId)` - Detail kontaktu s ownership validáciou
- `addContact(userId, accountId, email, name?, notes?)` - Pridanie kontaktu + **automatický sync emailov od tohto odosielateľa**
- `updateContact(contactId, userId, updates)` - Update mena alebo poznámok
- `removeContact(contactId, userId)` - Odstránenie kontaktu (emaily zostávajú, `contact_id = null`)
- `verifyContactOwnership(contactId, userId)` - Overenie ownership

### crm-email.service.js
Email CRUD operácie a thread management.

**Funkcie:**
- `getUserEmails(userId, accountId?, filters?)` - Zoznam emailov s pagination a filtrami (isRead, contactId, search)
- `getEmailById(emailId, userId)` - Detail emailu
- `getEmailThread(threadId, userId)` - Všetky emaily v konverzácii (sorted by date)
- `markThreadAsRead(threadId, userId, isRead)` - Označenie všetkých emailov v threade
- `searchEmails(userId, query, accountId?)` - DB full-text search (subject, body, from)
- `getUnreadCount(userId, accountId?)` - Počet neprecítaných emailov per účet
- `createEmail(data)` - Vytvorenie email záznamu v DB (používa jmap.service)
- `updateEmailReadStatus(emailId, userId, isRead)` - Update single email read status

### audit.service.js
Audit logging pre bezpečnostné účely.

**Funkcia:**
- `logAuditEvent(data)` - Zaloguje akciu do audit_logs tabuľky
  ```javascript
  {
    userId, action, resource, resourceId?,
    oldValue?, newValue?, success,
    errorMessage?, ipAddress?, userAgent?
  }
  ```

**Tracked events:**
- Login (success/fail)
- Password changes
- User creation/deletion
- Email account add/remove
- Role changes
- Contact add/remove

### email.service.js
(Legacy?) Basic email operácie - možno deprecated v prospech crm-email.service.js

## Middlewares

### Autentifikácia

**authenticate.js**
- Validuje JWT access token z httpOnly cookie
- Načíta usera z DB a priradí k `req.user`
- Ak token expiroval, vráti 401 Unauthorized
- Ak token chýba, vráti 401 Unauthorized

**roleMiddleware.js**

`requireAdmin`
- Overí že user má `role = 'admin'`
- Používa sa pred admin-only endpointmi
- Vráti 403 Forbidden ak nie je admin

`requireOwnerOrAdmin`
- Overí že user je vlastník resource alebo admin
- Používa sa napr. pri úprave vlastného profilu
- Parameter: `resourceUserId` z req.params alebo req.body

### Bezpečnosť

**rateLimiter.js**

`loginRateLimiter`
- Limit: 5 pokusov / 15 minút
- Scope: Per IP adresa
- Používa sa na `/api/auth/login`
- Ochrana proti brute force útokom

`apiRateLimiter`
- Limit: 100 requestov / 15 min (production)
- Limit: 1000 requestov / 15 min (development)
- Scope: Per IP adresa
- Aplikuje sa na všetky `/api/*` routes

`sensitiveOperationLimiter`
- Limit: 3 pokusy / 15 minút
- Používa sa na password change, user delete, atď.
- Extra ochrana pre kritické operácie

**validateInput.js**
- XSS sanitizácia vstupných dát
- Používa `xss-clean` knižnicu
- Automaticky aplikované cez `xss-clean` middleware

### Validácia

**validateBody.js**
- Middleware factory pre Zod schema validáciu
- Použitie: `validateBody(schema)`
- Pri validačnej chybe vráti 400 s detailmi

**validateParams.js**
- Validácia URL parametrov (napr. `:id`)
- Zod schemas pre params

**Príklad použitia:**
```javascript
router.post(
  '/login',
  validateBody(loginSchema),
  loginRateLimiter,
  loginController
);
```

### Global

**errorHandler.js**
- Centrálne spracovanie všetkých errorov
- Rozpoznáva custom error classes (`BadRequestError`, `UnauthorizedError`, ...)
- Production: Skryje stack traces
- Development: Full error details
- Loguje errory cez Winston

**notFound.js**
- 404 handler pre neexistujúce routes
- Musí byť zaregistrovaný **pred** errorHandler
- Vráti: `{ success: false, error: 'Route not found' }`

## Database Schema

### users
- id, username, role (admin/member)
- password, temp_password (bcrypt hash)
- changed_password, last_login
- created_at, updated_at

### email_accounts
- id, user_id (FK → users)
- email, email_password (AES-256 encrypted)
- jmap_account_id
- is_primary, is_active
- created_at, updated_at

### contacts
- id, user_id (FK → users)
- email_account_id (FK → email_accounts)
- email, name, notes
- added_at, created_at, updated_at

### emails
- id, user_id (FK → users)
- email_account_id (FK → email_accounts)
- contact_id (FK → contacts)
- jmap_id, message_id, thread_id
- from, to, subject, body
- is_read, date
- created_at, updated_at

### audit_logs
- id, user_id (FK → users)
- action, resource, resource_id
- old_value, new_value (JSON)
- ip_address, user_agent
- success, error_message
- created_at

## Konfigurácia

### Environment Variables (.env)

```env
# Server Configuration
PORT=5000                    # Port na ktorom beží Express server
NODE_ENV=development         # development | production (ovplyvňuje rate limits, error handling)

# Database Configuration
DB_HOST=localhost           # PostgreSQL host (docker-compose: 'postgres')
DB_PORT=5432               # PostgreSQL port
DB_USER=admin              # DB username
DB_PASSWORD=heslo123       # DB password
DB_NAME=crm                # Database name

# JWT Secrets (MUSIA byť dlhé a náhodné!)
JWT_SECRET=your-secret-key              # Pre access token (min 32 znakov)
JWT_REFRESH_SECRET=your-refresh-secret  # Pre refresh token (min 32 znakov)
JWT_EXPIRES_IN=1h                       # Access token expiration (1h = 1 hodina)

# JMAP Configuration
JMAP_SERVER=https://mail.truemail.sk/jmap/    # JMAP endpoint pre Truemail.sk

# Encryption (pre JMAP heslá)
ENCRYPTION_KEY=your-32-char-encryption-key    # PRESNE 32 znakov pre AES-256

# CORS
CORS_ORIGIN=http://localhost:5173    # Frontend URL (React dev server)

# Optional
BCRYPT_ROUNDS=12                     # Bcrypt cost factor (default: 12)
```

### Ako vygenerovať secrets

**JWT_SECRET a JWT_REFRESH_SECRET:**
```bash
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```

**ENCRYPTION_KEY (presne 32 znakov):**
```bash
node -e "console.log(require('crypto').randomBytes(32).toString('base64').slice(0, 32))"
```

### Docker Compose

**docker-compose.yml** obsahuje len PostgreSQL databázu:
```yaml
services:
  postgres:
    image: postgres:16
    container_name: postgres-db
    restart: "no"
    ports:
      - "5432:5432"
    volumes:
      - ./postgres:/var/lib/postgresql/data
```

**Spustenie:**
```bash
docker-compose up -d postgres    # Start databázy
docker-compose down              # Stop databázy (data zostanú)
docker-compose down -v           # Stop + vymazanie volumes (⚠️ stratíš dáta)
```

### Drizzle Configuration

**drizzle.config.js** - Konfigurácia pre Drizzle Kit (migrations tool):
```javascript
{
  schema: './src/db/schema.js',      // Kde je DB schema definovaná
  out: './src/db/migrations',        // Kam sa uložia migrračné SQL súbory
  dialect: 'postgresql',
  dbCredentials: { /* z .env */ },
  verbose: true,                     // Loguje SQL queries
  strict: true                       // Prísna validácia
}
```

**Používané príkazy:**
- `drizzle-kit generate` → vygeneruje SQL migrácie zo schémy
- `drizzle-kit push` → pushne schému priamo (skip migrations)
- `drizzle-kit studio` → otvorí DB GUI na http://localhost:4983

## Skripty

### NPM Skripty

```bash
# Development & Production
npm run dev              # Spustí vývojový server s nodemon (hot reload)
npm start               # Production server (bez reloadovania)

# Database management
npm run db:generate     # Vygeneruje SQL migračné súbory z Drizzle schémy
npm run db:migrate      # Aplikuje migrácie na databázu
npm run db:push         # Pushne schému priamo (bez migračných súborov)
npm run db:studio       # Otvorí Drizzle Studio - GUI pre databázu

# Seeding
npm run db:seed              # Vytvorí admin účet s náhodným heslom
npm run db:seed:testuser     # Vytvorí testovacieho usera (testuser/testuser123!)

# Testing
npm test                # Spustí Jest testy
```

### Utility Skripty

**check-tables.js** - Zoznam všetkých tabuliek v databáze
```bash
node check-tables.js
```

**test-search.js** - Test JMAP search endpointu (vyžaduje TEST_COOKIE env)
```bash
TEST_COOKIE='session=xyz...' node test-search.js
```

**mark-email-read-jmap.js** - Označí konkrétny email ako prečítaný cez JMAP
```bash
node mark-email-read-jmap.js
```

**scripts/encrypt-password.js** - Zašifruje heslo pre manuálne vloženie do DB
```bash
node scripts/encrypt-password.js 'your-password'
```

## Spustenie

### Prvý setup

1. **Nainštaluj dependencies**
   ```bash
   npm install
   ```

2. **Skopíruj a nastav .env**
   ```bash
   cp .env.example .env
   ```
   - Nastav `DB_*` credentials (default sú pre docker-compose)
   - Vygeneruj silný `JWT_SECRET` a `JWT_REFRESH_SECRET`
   - Vygeneruj 32-znakový `ENCRYPTION_KEY` (pre šifrovanie JMAP hesiel)
   - Nastav `CORS_ORIGIN` pre frontend (default: http://localhost:5173)

3. **Spusti PostgreSQL databázu**
   ```bash
   docker-compose up -d postgres
   ```

4. **Aplikuj databázové migrácie**
   ```bash
   npm run db:migrate
   ```

5. **Vytvor admin účet**
   ```bash
   npm run db:seed
   ```
   ⚠️ **DÔLEŽITÉ:** Skopíruj si vygenerované temporary heslo! Budeš ho potrebovať pri prvom prihlásení.

6. **Spusti server**
   ```bash
   npm run dev
   ```

7. **API beží na** `http://localhost:5000`
   - Health check: `GET /health`
   - API docs: Všetky endpointy sú popísané v sekcii "API Endpointy"

### Každodenný development

```bash
# Spusti databázu (ak nie je spustená)
docker-compose up -d postgres

# Spusti dev server
npm run dev

# Otvor DB GUI (voliteľné)
npm run db:studio
```

## Ako to funguje

### Architektúra

Aplikácia používa **layered architecture** so separáciou zodpovedností:

```
Client Request
    ↓
Routes (routing)
    ↓
Middlewares (auth, validation, rate limiting)
    ↓
Controllers (request handling, response formatting)
    ↓
Services (business logic)
    ↓
Database (Drizzle ORM)
```

### Flow autentifikácie a onboardingu

1. **Admin vytvorí nového usera**
   - `POST /api/admin/users` s username, firstName, lastName, role
   - Systém vygeneruje náhodné temporary heslo (16 znakov, mix uppercase/lowercase/numbers/symbols)
   - Heslo sa hashuje bcryptom (12 rounds) a uloží do `temp_password`
   - `changed_password = false`

2. **Prvé prihlásenie**
   - User sa prihlási s temporary heslom: `POST /api/auth/login`
   - Backend zistí že `changed_password = false` a vráti flag `mustChangePassword: true`
   - Frontend redirectne na "set password" screen

3. **Nastavenie vlastného hesla**
   - `POST /api/auth/set-password` s novým heslom
   - Validácia: min 8 znakov, uppercase, lowercase, number, symbol
   - Heslo sa hashuje a uloží do `password` fieldu
   - `temp_password = null`, `changed_password = true`

4. **Session management**
   - Pri login dostane user JWT access token (httpOnly cookie, 1h)
   - Refresh token (httpOnly cookie, 7 dní)
   - Pri expirácii access tokenu sa automaticky refreshne

### Email synchronizácia flow

1. **Pripojenie email účtu**
   - User pridá JMAP účet: `POST /api/email-accounts`
   - Backend overí JMAP credentials volaním `getJmapSession()`
   - Heslo sa zašifruje AES-256-GCM a uloží do DB
   - JMAP accountId sa uloží pre budúce requesty

2. **Prvý sync**
   - Automaticky sa stiahnu emaily z INBOX
   - `Email/query` + `Email/get` JMAP volania
   - Emaily sa uložia do DB s `thread_id` pre organizáciu konverzácií

3. **Nepretržitý sync**
   - Frontend pravidelne volá `GET /api/emails?accountId=X`
   - Backend volá JMAP a stiahne nové emaily od posledného syncu
   - Update-uje `is_read` status podľa JMAP

### Kontakty a auto-sync

1. **Discovery kontaktov**
   - `GET /api/contacts/discover?accountId=X`
   - Backend stiahne všetky emaily z JMAP
   - Extrahuje unikátne email adresy z `from` a `to` polí
   - Vráti zoznam emailov ktoré ešte nie sú v kontaktoch

2. **Pridanie kontaktu**
   - `POST /api/contacts` s `email` a `emailAccountId`
   - Backend uloží kontakt do DB
   - **Auto-sync:** Automaticky vyhľadá všetky emaily od/pre tento kontakt cez JMAP
   - Stiahnuť a uloží všetky nájdené emaily s linknutím na kontakt (`contact_id`)

3. **Email thread organizácia**
   - Emaily sa zoskupujú podľa `thread_id` (z JMAP)
   - `GET /api/emails/thread/:threadId` vráti chronologickú konverzáciu
   - Mark as read označí všetky emaily v threade

### Bezpečnostné mechanizmy

**Rate Limiting:**
- Login: 5 pokusov / 15 min (brute force ochrana)
- API: 100 requestov / 15 min (1000 v dev mode)
- Sensitive operations: 3 pokusy / 15 min

**Password Security:**
- Bcrypt hashing s 12 rounds (2^12 = 4096 iterations)
- Temporary passwords: 16 znakov, vysoká entropia
- Validácia: min 8 znakov, mix typov znakov

**Data Encryption:**
- JMAP heslá: AES-256-GCM (symetrické šifrovanie)
- Format: `iv:authTag:encryptedText`
- Kľúč derivovaný z `ENCRYPTION_KEY` cez scrypt

**Session Security:**
- JWT tokeny v httpOnly cookies (XSS ochrana)
- SameSite=Strict (CSRF ochrana)
- Krátka platnosť access tokenu (1h)
- Refresh token rotation

**Input Validation:**
- Zod schemas pre všetky endpointy
- XSS sanitizácia cez xss-clean
- SQL injection ochrana cez Drizzle ORM prepared statements

**Audit Logging:**
- Všetky dôležité akcie (login, password change, user creation, email account add/remove)
- Ukladá user_id, action, resource, old/new values, IP, user-agent
- `GET /api/admin/audit-logs` pre adminov

### Database Cascade Deletes

**User Delete:**
- Cascade vymaže: email_accounts → contacts → emails → audit_logs

**Email Account Delete:**
- Cascade vymaže: contacts → emails (pre tento účet)
- User si môže pridať ďalší účet

**Contact Delete:**
- Emaily od tohto kontaktu zostávajú (len `contact_id = null`)
- Možnosť filtrovať "orphaned" emaily

### JMAP Operácie

**Supported operations:**

1. **Email/query** - Vyhľadávanie emailov
   ```javascript
   {
     filter: { inMailbox: 'inbox' },
     sort: [{ property: 'receivedAt', isAscending: false }],
     limit: 50
   }
   ```

2. **Email/get** - Získanie detailov emailov
   ```javascript
   {
     ids: ['id1', 'id2'],
     properties: ['from', 'to', 'subject', 'bodyValues', 'threadId', ...]
   }
   ```

3. **Email/set** - Vytvorenie emailu (draft)
   ```javascript
   {
     create: {
       draft1: {
         mailboxIds: { drafts: true },
         from: [...], to: [...],
         subject: '...', bodyValues: { body: { value: '...' }}
       }
     }
   }
   ```

4. **EmailSubmission/set** - Poslanie emailu
   ```javascript
   {
     create: {
       sub1: {
         emailId: 'draft1',
         identityId: 'identity1'
       }
     }
   }
   ```

5. **Email/changes** - Incremental sync (delta updates)
   - Používa `sinceState` pre získanie len zmenených emailov
   - Optimalizované pre veľké mailboxy

### Šifrovanie JMAP hesiel

**Encryption flow:**
```javascript
// Encryption (pri pridaní účtu)
1. Vygeneruj náhodný IV (16 bytes)
2. Vytvor cipher s AES-256-GCM, key, IV
3. Zašifruj heslo
4. Získaj auth tag
5. Ulož: `${iv}:${authTag}:${encrypted}`

// Decryption (pri JMAP operáciách)
1. Split stored value na [iv, authTag, encrypted]
2. Vytvor decipher s AES-256-GCM, key, IV
3. Nastav auth tag
4. Dešifruj heslo
5. Použij pre JMAP request
```

### Multi-Account Management

Každý user môže mať **viacero email účtov**:
- Jeden je označený ako **primárny** (`is_primary = true`)
- Kontakty a emaily sú **izolované per účet** (accountId filter)
- Frontend prepína medzi účtami cez accountId parameter
- Každý účet má vlastný JMAP session a credentials

### Error Handling

**Centrálny error handler middleware:**
- Všetky chyby idú cez `errorHandler.js`
- Custom error classes: `BadRequestError`, `UnauthorizedError`, `NotFoundError`, `ConflictError`
- Production mode: Skryje stack traces
- Development mode: Full error details + stack trace
- Všetky errory sa logujú cez Winston logger

## Systém rolí

**Admin**
- Všetko čo Member
- `/api/admin/*` endpointy
- Vytvorenie/zmazanie používateľov
- Zmena rolí

**Member**
- Vlastný profil a nastavenia
- Správa vlastných email účtov
- Vlastné kontakty a emaily
- Inbox

## JMAP Integrácia

### Provider: Truemail.sk

**JMAP Endpoint:** `https://mail.truemail.sk/jmap/`

**Autentifikácia:** Basic Auth
- Username: email adresa (napr. `user@slovensko.ai`)
- Password: email heslo (uložené encrypted v DB)

### JMAP Session

Každý JMAP request začína získaním session:
```javascript
GET https://mail.truemail.sk/jmap/session/
Authorization: Basic base64(email:password)

Response:
{
  "capabilities": {
    "urn:ietf:params:jmap:core": { maxObjectsInGet: 500, ... },
    "urn:ietf:params:jmap:mail": { ... }
  },
  "accounts": {
    "account-id": {
      "name": "user@slovensko.ai",
      "isPersonal": true,
      "accountCapabilities": { ... }
    }
  },
  "primaryAccounts": {
    "urn:ietf:params:jmap:mail": "account-id"
  }
}
```

`accountId` sa ukladá do DB (`jmap_account_id`) a používa pre všetky ďalšie requesty.

### Supported JMAP Methods

**1. Email/query** - Vyhľadávanie emailov
```javascript
[
  "Email/query",
  {
    accountId: "account-id",
    filter: {
      inMailbox: "inbox",      // alebo "sent", "drafts"
      from: "email@domain.sk"  // voliteľný filter
    },
    sort: [{ property: "receivedAt", isAscending: false }],
    limit: 50,
    position: 0
  },
  "call-id"
]

Response: { list: ["emailId1", "emailId2", ...], total: 156 }
```

**2. Email/get** - Získanie detailov
```javascript
[
  "Email/get",
  {
    accountId: "account-id",
    ids: ["emailId1", "emailId2"],
    properties: [
      "id", "threadId", "mailboxIds", "keywords",
      "from", "to", "cc", "bcc",
      "subject", "receivedAt", "bodyValues",
      "textBody", "htmlBody"
    ],
    bodyProperties: ["partId", "type", "value"]
  },
  "call-id"
]

Response: {
  list: [{
    id: "emailId1",
    from: [{ email: "sender@domain.sk", name: "Sender Name" }],
    subject: "Email subject",
    bodyValues: { body: { value: "Email content..." } },
    ...
  }]
}
```

**3. Email/set** - Vytvorenie/Update/Delete
```javascript
// Vytvorenie draft emailu
[
  "Email/set",
  {
    accountId: "account-id",
    create: {
      "draft-1": {
        mailboxIds: { "drafts-mailbox-id": true },
        from: [{ email: "me@slovensko.ai" }],
        to: [{ email: "recipient@domain.sk" }],
        subject: "Reply subject",
        bodyValues: {
          body: {
            value: "Email content",
            type: "text/plain"
          }
        },
        textBody: [{ partId: "body", type: "text/plain" }],
        keywords: { "$draft": true }
      }
    }
  },
  "call-id"
]

// Update (napr. mark as read)
[
  "Email/set",
  {
    accountId: "account-id",
    update: {
      "emailId1": {
        "keywords/$seen": true    // mark as read
      }
    }
  },
  "call-id"
]
```

**4. EmailSubmission/set** - Poslanie emailu
```javascript
[
  "EmailSubmission/set",
  {
    accountId: "account-id",
    create: {
      "submission-1": {
        emailId: "draft-1",           // ID z Email/set create
        identityId: "identity-id",    // Z Identity/get
        envelope: {
          mailFrom: { email: "me@slovensko.ai" },
          rcptTo: [{ email: "recipient@domain.sk" }]
        }
      }
    }
  },
  "call-id"
]
```

**5. Mailbox/get** - Zoznam mailboxov (INBOX, Sent, Drafts, ...)
```javascript
[
  "Mailbox/get",
  {
    accountId: "account-id",
    ids: null  // null = všetky
  },
  "call-id"
]

Response: {
  list: [
    { id: "inbox-id", name: "Inbox", role: "inbox", ... },
    { id: "sent-id", name: "Sent", role: "sent", ... }
  ]
}
```

**6. Identity/get** - Email identity (pre sending)
```javascript
[
  "Identity/get",
  {
    accountId: "account-id",
    ids: null
  },
  "call-id"
]

Response: {
  list: [{
    id: "identity-id",
    email: "me@slovensko.ai",
    name: "My Name"
  }]
}
```

**7. Email/changes** - Delta sync (incremental updates)
```javascript
[
  "Email/changes",
  {
    accountId: "account-id",
    sinceState: "previous-state-token",
    maxChanges: 100
  },
  "call-id"
]

Response: {
  oldState: "previous-state",
  newState: "current-state",
  hasMoreChanges: false,
  created: ["emailId1"],
  updated: ["emailId2"],
  destroyed: ["emailId3"]
}
```

### JMAP Request Format

Všetky requesty používajú rovnaký formát:
```javascript
POST https://mail.truemail.sk/jmap/api/
Authorization: Basic base64(email:password)
Content-Type: application/json

{
  "using": [
    "urn:ietf:params:jmap:core",
    "urn:ietf:params:jmap:mail"
  ],
  "methodCalls": [
    ["Method/name", { params }, "call-id"],
    ...
  ]
}
```

### Error Handling

JMAP errory majú formát:
```javascript
{
  "methodResponses": [
    ["error", {
      "type": "invalidArguments",
      "description": "Invalid filter"
    }, "call-id"]
  ]
}
```

**Common error types:**
- `invalidArguments` - Zlé parametre
- `accountNotFound` - Neplatný accountId
- `notFound` - Email/mailbox nenájdený
- `forbidden` - Nedostatočné oprávnenia
- `serverFail` - Server error

### Optimalizácie

**Batching:**
- Jeden HTTP request môže obsahovať viacero method calls
- Príklad: Email/query + Email/get v jednom requeste

**Result References:**
- Výsledok jedného method callu môže byť použitý v ďalšom
- Príklad: Email/query → Email/get s `#ids` referenciou

**Incremental Sync:**
- Používaj `Email/changes` namiesto full Email/query
- Ukladaj `state` token pre ďalšie syncs
- Znižuje bandwidth a load

## Šifrovanie

**JMAP heslá** - AES-256-GCM
- Format: `iv:authTag:encryptedText`
- Kľúč: `ENCRYPTION_KEY` z .env (32 znakov)
- Funkcie: `encryptPassword()`, `decryptPassword()`

**User heslá** - Bcrypt
- 12 rounds (2^12 iterations)
- Funkcie: `hashPassword()`, `comparePassword()`
