# CANIFA Chatbot API Documentation

API hệ thống chatbot tư vấn thời trang CANIFA - CiCi Assistant.

## Base URL
```
http://localhost:8000
```

---

## API Endpoints

### 1. Chat với Chatbot

**Endpoint:** `POST /chat`

**Mô tả:** Gửi tin nhắn tới chatbot và nhận phản hồi tư vấn thời trang cùng danh sách sản phẩm liên quan.

#### Request Body

```json
{
  "user_id": "string",
  "user_query": "string"
}
```

**Parameters:**
| Field | Type | Required | Mô tả |
|-------|------|----------|-------|
| `user_id` | string | ✅ | ID định danh người dùng (dùng để lưu lịch sử chat) |
| `user_query` | string | ✅ | Nội dung tin nhắn của người dùng |

**Ví dụ Request:**
```json
{
  "user_id": "user_12345",
  "user_query": "Cho em xem áo sơ mi nam dưới 5a00k"
}
```

#### Response

**Success Response (200 OK):**

```json
{
  "status": "success",
  "ai_response": "string",
  "product_ids": ["string"]
}
```

**Response Fields:**
| Field | Type | Mô tả |
|-------|------|-------|
| `status` | string | Trạng thái xử lý request (`"success"` hoặc `"error"`) |
| `ai_response` | string | Câu trả lời của chatbot (văn bản tư vấn) |
| `product_ids` | array[string] | Danh sách mã sản phẩm được đề xuất (internal_ref_code) |

**Ví dụ Response:**
```json
{
  "status": "success",
  "ai_response": "Em chào anh! Em đã tìm thấy một số mẫu áo sơ mi nam đẹp trong tầm giá dưới 500k:\n\n1. Áo Sơ Mi Nam Cotton - 399.000đ\n2. Áo Sơ Mi Slim Fit - 449.000đ\n\nCác sản phẩm này đều là chất liệu cotton thoáng mát, phù hợp cho mùa hè ạ!",
  "product_ids": ["SM12345", "SM12346"]
}
```

**Error Response (500 Internal Server Error):**
```json
{
  "status": "error",
  "ai_response": "Xin lỗi, đã có lỗi xảy ra. Vui lòng thử lại sau.",
  "product_ids": []
}
```

---

### 2. Lấy Lịch Sử Chat

**Endpoint:** `GET /history/{user_id}`

**Mô tả:** Lấy lịch sử chat của người dùng với phân trang cursor-based.

#### Path Parameters

| Parameter | Type | Required | Mô tả |
|-----------|------|----------|-------|
| `user_id` | string | ✅ | ID người dùng cần lấy lịch sử |

#### Query Parameters

| Parameter | Type | Required | Default | Mô tả |
|-----------|------|----------|---------|-------|
| `limit` | integer | ❌ | 50 | Số lượng tin nhắn tối đa mỗi trang (1-100) |
| `before_id` | integer | ❌ | null | ID của tin nhắn để lấy các tin nhắn trước đó (dùng cho phân trang) |

**Ví dụ Request:**
```
GET /history/user_12345?limit=20&before_id=150
```

#### Response

**Success Response (200 OK):**

```json
{
  "data": [
    {
      "id": 149,
      "user_id": "user_12345",
      "message": "Cho em xem áo sơ mi nam",
      "is_human": true,
      "timestamp": "2025-12-25T14:30:00"
    },
    {
      "id": 148,
      "user_id": "user_12345",
      "message": "Em đã tìm thấy một số mẫu áo sơ mi nam đẹp...",
      "is_human": false,
      "timestamp": "2025-12-25T14:30:02"
    }
  ],
  "next_cursor": 130
}
```

**Response Fields:**
| Field | Type | Mô tả |
|-------|------|-------|
| `data` | array[object] | Danh sách tin nhắn chat (sắp xếp từ mới → cũ) |
| `data[].id` | integer | ID duy nhất của tin nhắn |
| `data[].user_id` | string | ID người dùng |
| `data[].message` | string | Nội dung tin nhắn |
| `data[].is_human` | boolean | `true` = tin nhắn của người dùng, `false` = tin nhắn của bot |
| `data[].timestamp` | string | Thời gian gửi tin nhắn (ISO 8601 format) |
| `next_cursor` | integer \| null | ID của tin nhắn cuối cùng (dùng làm `before_id` cho request tiếp theo). `null` nếu hết dữ liệu |

---

## Phân Trang (Pagination)

API sử dụng **cursor-based pagination** để lấy lịch sử chat:

### Cách hoạt động:

1. **Request đầu tiên** - Lấy 20 tin nhắn mới nhất:
   ```
   GET /history/user_12345?limit=20
   ```
   Response:
   ```json
   {
     "data": [...], // 20 tin nhắn (ID: 200 → 181)
     "next_cursor": 181
   }
   ```

2. **Request tiếp theo** - Lấy 20 tin nhắn cũ hơn:
   ```
   GET /history/user_12345?limit=20&before_id=181
   ```
   Response:
   ```json
   {
     "data": [...], // 20 tin nhắn (ID: 180 → 161)
     "next_cursor": 161
   }
   ```

3. **Request cuối cùng** - Khi hết dữ liệu:
   ```json
   {
     "data": [...], // 5 tin nhắn còn lại
     "next_cursor": null
   }
   ```

### Logic phân trang:
- `next_cursor` luôn là **ID của tin nhắn cuối cùng** trong `data`
- Dùng `next_cursor` làm `before_id` cho request tiếp theo
- Khi `next_cursor = null` → đã hết dữ liệu

---

## Chat Workflow

```mermaid
graph LR
    A[User gửi message] --> B[POST /chat]
    B --> C{Agent xử lý}
    C --> D[Tìm kiếm sản phẩm]
    C --> E[Trả lời tư vấn]
    D --> F[Trích xuất product_ids]
    E --> F
    F --> G[Response: ai_response + product_ids]
    G --> H[Lưu vào PostgreSQL]
    H --> I[Trả về client]
```

### Quy trình xử lý:
1. User gửi tin nhắn qua API `/chat`
2. Hệ thống agent phân tích intent
3. Nếu cần tìm sản phẩm → Gọi `data_retrieval_tool` với tham số phù hợp
4. Agent tổng hợp thông tin → Trả lời tư vấn
5. Trích xuất `product_ids` từ kết quả tìm kiếm
6. Lưu lịch sử chat vào PostgreSQL (background task)
7. Trả về JSON với `ai_response` và `product_ids`

---

## Error Handling

### Error Response Format

```json
{
  "status": "error",
  "ai_response": "Mô tả lỗi hoặc thông báo fallback",
  "product_ids": []
}
```

### HTTP Status Codes

| Code | Ý nghĩa | Khi nào xảy ra |
|------|---------|----------------|
| 200 | OK | Request thành công |
| 400 | Bad Request | Thiếu `user_id` hoặc `user_query` |
| 500 | Internal Server Error | Lỗi hệ thống (database, LLM, ...) |

---

## Ví Dụ Sử Dụng

### Python
```python
import requests

# Chat với bot
response = requests.post("http://localhost:8000/chat", json={
    "user_id": "user_12345",
    "user_query": "Cho em xem váy đầm dự tiệc dưới 1 triệu"
})

data = response.json()
print(f"Bot: {data['ai_response']}")
print(f"Sản phẩm: {data['product_ids']}")

# Lấy lịch sử chat
history = requests.get("http://localhost:8000/history/user_12345?limit=10")
messages = history.json()["data"]
for msg in messages:
    sender = "User" if msg["is_human"] else "Bot"
    print(f"{sender}: {msg['message']}")
```

### JavaScript (Fetch API)
```javascript
// Chat với bot
const response = await fetch('http://localhost:8000/chat', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    user_id: 'user_12345',
    user_query: 'Cho em xem áo khoác nữ'
  })
});

const data = await response.json();
console.log('Bot:', data.ai_response);
console.log('Products:', data.product_ids);

// Lấy lịch sử chat (phân trang)
let cursor = null;
const allMessages = [];

do {
  const url = cursor 
    ? `http://localhost:8000/history/user_12345?limit=50&before_id=${cursor}`
    : `http://localhost:8000/history/user_12345?limit=50`;
  
  const historyResponse = await fetch(url);
  const { data: messages, next_cursor } = await historyResponse.json();
  
  allMessages.push(...messages);
  cursor = next_cursor;
} while (cursor !== null);

console.log(`Tổng số tin nhắn: ${allMessages.length}`);
```

### cURL
```bash
# Chat với bot
curl -X POST "http://localhost:8000/chat" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "user_12345",
    "user_query": "Cho em xem giày thể thao nam"
  }'

# Lấy lịch sử chat
curl "http://localhost:8000/history/user_12345?limit=20"

# Lấy trang tiếp theo
curl "http://localhost:8000/history/user_12345?limit=20&before_id=150"
```

---

## Notes

### 1. Product IDs
- `product_ids` trả về danh sách `internal_ref_code` (mã sản phẩm nội bộ)
- Frontend có thể dùng để hiển thị carousel sản phẩm hoặc link đến trang chi tiết
- Nếu không tìm thấy sản phẩm → `product_ids = []`

### 2. Conversation History
- Lịch sử chat được lưu tự động sau mỗi cuộc hội thoại (background task)
- Dữ liệu lưu trong PostgreSQL với index trên `user_id` và `id`
- Sắp xếp theo thứ tự mới nhất → cũ nhất

### 3. Rate Limiting
- Hiện tại chưa có rate limiting
- Khuyến nghị implement rate limit khi deploy production

### 4. Authentication
- Hiện tại API không yêu cầu authentication
- `user_id` do client tự generate và gửi lên
- Khuyến nghị: Tích hợp Clerk Auth hoặc JWT token cho production

---

## Environment Variables

For detailed documentation on all environment variables, see [ENV_VARIABLES.md](./ENV_VARIABLES.md).

### Quick Setup

1. Copy environment variables template:
```bash
# See ENV_VARIABLES.md for complete list
```

2. Required variables:
```bash
# MongoDB (required)
MONGODB_URI=mongodb://localhost:27017
MONGODB_DB_NAME=cucu_note

# Clerk Authentication (required for production)
CLERK_SECRET_KEY=sk_test_...
CLERK_JWKS_URL=https://your-clerk-instance.clerk.accounts.dev/.well-known/jwks.json
CLERK_ISSUER=https://your-clerk-instance.clerk.accounts.dev

# OpenAI (required for AI features)
OPENAI_API_KEY=sk-...

# Server
PORT=5000
```

3. Optional but recommended:
```bash
# Redis for caching and rate limiting
REDIS_HOST=localhost
REDIS_PORT=6379

# CORS (restrict in production)
CORS_ORIGINS=http://localhost:3001,https://yourdomain.com
```

### Performance Optimization

The backend includes several performance optimizations:

- **MongoDB Connection Pooling**: Configurable via `MONGODB_MAX_POOL_SIZE`, `MONGODB_MIN_POOL_SIZE`
- **Database Indexes**: Automatically created on startup for common queries
- **Redis Caching**: For response and embedding caching
- **Rate Limiting**: Uses Redis for distributed rate limiting in production

See [ENV_VARIABLES.md](./ENV_VARIABLES.md) for all configuration options.

---

## Testing

Truy cập `http://localhost:8000/static/index.html` để test chatbot qua UI đơn giản.
