# DramaLing 詞卡管理 API 規格書

## 1. API 概覽

### 1.1 基本資訊
- **基礎 URL**: `http://localhost:5008/api` (開發環境)
- **控制器**: `FlashcardsController`
- **路由前綴**: `/api/flashcards`
- **認證方式**: JWT Bearer Token (開發階段暫時關閉)
- **資料格式**: JSON (UTF-8)

### 1.2 架構依賴

> 📋 **技術架構參考文檔**
>
> 本 API 規格書依賴以下文檔，建議閱讀順序：
>
> **🏗️ 系統架構文檔**
> - [系統架構總覽](../../04_technical/system-architecture.md) - 了解整體架構設計
> - [後端架構詳細說明](../../04_technical/backend-architecture.md) - 了解 ASP.NET Core 架構細節
>
> **📋 需求規格文檔**
> - [詞卡管理功能產品需求規格](../../01_requirement/詞卡管理功能產品需求規格.md) - 了解功能需求和用戶故事

## 2. 資料模型定義

### 2.1 詞卡實體 (Flashcard Entity)

#### C# 實體模型
```csharp
public class Flashcard
{
    // 基本識別
    public Guid Id { get; set; }
    public Guid UserId { get; set; }
    public Guid? CardSetId { get; set; }

    // 詞卡內容
    [Required, MaxLength(255)]
    public string Word { get; set; }
    [Required]
    public string Translation { get; set; }
    [Required]
    public string Definition { get; set; }
    [MaxLength(50)]
    public string? PartOfSpeech { get; set; }
    [MaxLength(255)]
    public string? Pronunciation { get; set; }
    public string? Example { get; set; }
    public string? ExampleTranslation { get; set; }

    // SM-2 學習算法參數
    public float EasinessFactor { get; set; } = 2.5f;
    public int Repetitions { get; set; } = 0;
    public int IntervalDays { get; set; } = 1;
    public DateTime NextReviewDate { get; set; }

    // 學習統計
    [Range(0, 100)]
    public int MasteryLevel { get; set; } = 0;
    public int TimesReviewed { get; set; } = 0;
    public int TimesCorrect { get; set; } = 0;
    public DateTime? LastReviewedAt { get; set; }

    // 狀態管理
    public bool IsFavorite { get; set; } = false;
    public bool IsArchived { get; set; } = false;
    [MaxLength(10)]
    public string? DifficultyLevel { get; set; } // A1-C2

    // 時間戳記
    public DateTime CreatedAt { get; set; }
    public DateTime UpdatedAt { get; set; }
}
```

#### TypeScript 前端型別定義
```typescript
interface Flashcard {
  id: string;
  word: string;
  translation: string;
  definition: string;
  partOfSpeech: string;
  pronunciation: string;
  example: string;
  exampleTranslation?: string;
  masteryLevel: number;        // 0-100
  timesReviewed: number;
  isFavorite: boolean;
  nextReviewDate: string;      // ISO Date
  difficultyLevel: string;     // A1, A2, B1, B2, C1, C2
  createdAt: string;          // ISO Date
  updatedAt?: string;         // ISO Date
}

interface CreateFlashcardRequest {
  word: string;
  translation: string;
  definition: string;
  pronunciation: string;
  partOfSpeech: string;
  example: string;
  exampleTranslation?: string;
}
```

### 2.2 API 回應格式標準

#### 成功回應格式
```json
{
  "success": true,
  "data": {
    // 實際資料內容
  },
  "message": "操作成功描述" // 可選
}
```

#### 錯誤回應格式
```json
{
  "success": false,
  "error": "錯誤描述",
  "isDuplicate": true, // 特殊情況：重複資料
  "existingCard": { /* 現有詞卡資料 */ } // 重複時的現有資料
}
```

## 3. API 端點規格

### 3.1 端點清單

| 方法 | 端點 | 描述 | 狀態 |
|------|------|------|------|
| GET | `/api/flashcards` | 取得詞卡列表 | ✅ 已實現 |
| GET | `/api/flashcards/{id}` | 取得單一詞卡 | ✅ 已實現 |
| POST | `/api/flashcards` | 創建新詞卡 | ✅ 已實現 |
| PUT | `/api/flashcards/{id}` | 更新詞卡 | ✅ 已實現 |
| DELETE | `/api/flashcards/{id}` | 刪除詞卡 | ✅ 已實現 |
| POST | `/api/flashcards/{id}/favorite` | 切換收藏狀態 | ✅ 已實現 |

### 3.2 詳細 API 規格

#### 📖 GET /api/flashcards
**功能**: 取得用戶的詞卡列表，支援搜尋和篩選

**查詢參數**:
```typescript
interface GetFlashcardsParams {
  search?: string;        // 搜尋關鍵字，搜尋範圍：詞彙、翻譯、定義
  favoritesOnly?: boolean; // 僅顯示收藏詞卡 (預設: false)
}
```

**實際實現邏輯**:
```csharp
// 搜尋篩選邏輯
if (!string.IsNullOrEmpty(search))
{
    query = query.Where(f =>
        f.Word.Contains(search) ||
        f.Translation.Contains(search) ||
        (f.Definition != null && f.Definition.Contains(search)));
}

// 收藏篩選
if (favoritesOnly)
{
    query = query.Where(f => f.IsFavorite);
}

// 排序：按創建時間降序
var flashcards = await query.OrderByDescending(f => f.CreatedAt).ToListAsync();
```

**成功回應**:
```json
{
  "success": true,
  "data": {
    "flashcards": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "word": "sophisticated",
        "translation": "精密的",
        "definition": "Highly developed or complex",
        "partOfSpeech": "adjective",
        "pronunciation": "/səˈfɪstɪkeɪtɪd/",
        "example": "A sophisticated system",
        "exampleTranslation": "一個精密的系統",
        "masteryLevel": 75,
        "timesReviewed": 12,
        "isFavorite": true,
        "nextReviewDate": "2025-09-25T00:00:00Z",
        "difficultyLevel": "C1",
        "createdAt": "2025-09-20T08:30:00Z",
        "updatedAt": "2025-09-24T10:15:00Z"
      }
    ],
    "count": 1
  }
}
```

**請求範例**:
```bash
# 取得所有詞卡
curl "http://localhost:5008/api/flashcards"

# 搜尋包含 "sophisticated" 的詞卡
curl "http://localhost:5008/api/flashcards?search=sophisticated"

# 僅取得收藏詞卡
curl "http://localhost:5008/api/flashcards?favoritesOnly=true"

# 組合搜尋：搜尋收藏詞卡中包含 "精密" 的詞卡
curl "http://localhost:5008/api/flashcards?search=精密&favoritesOnly=true"
```

#### 📖 GET /api/flashcards/{id}
**功能**: 取得單一詞卡的完整資訊

**路徑參數**:
- `id`: 詞卡唯一識別碼 (GUID 格式)

**成功回應**:
```json
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "word": "sophisticated",
    // ... 完整詞卡資料，格式同列表 API
    "createdAt": "2025-09-20T08:30:00Z",
    "updatedAt": "2025-09-24T10:15:00Z"
  }
}
```

**錯誤回應**:
```json
{
  "success": false,
  "error": "詞卡不存在"
}
```

#### ✏️ POST /api/flashcards
**功能**: 創建新的詞卡

**請求體**:
```json
{
  "word": "elaborate",
  "translation": "詳細說明",
  "definition": "To explain in detail",
  "pronunciation": "/ɪˈlæbərət/",
  "partOfSpeech": "verb",
  "example": "Please elaborate on your idea",
  "exampleTranslation": "請詳細說明你的想法"
}
```

**實際實現邏輯**:
```csharp
// 1. 自動創建測試用戶 (開發階段)
var testUser = await _context.Users.FirstOrDefaultAsync(u => u.Id == userId);
if (testUser == null) {
    // 自動創建測試用戶邏輯
}

// 2. 重複詞卡檢測
var existing = await _context.Flashcards
    .FirstOrDefaultAsync(f => f.UserId == userId &&
        f.Word.ToLower() == request.Word.ToLower() &&
        !f.IsArchived);

// 3. 創建新詞卡
var flashcard = new Flashcard
{
    Id = Guid.NewGuid(),
    UserId = userId,
    Word = request.Word,
    Translation = request.Translation,
    // ... 其他欄位
    CreatedAt = DateTime.UtcNow,
    UpdatedAt = DateTime.UtcNow
};
```

**成功回應**:
```json
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "word": "elaborate",
    // ... 完整創建的詞卡資料
    "createdAt": "2025-09-24T10:30:00Z"
  },
  "message": "詞卡創建成功"
}
```

**重複詞卡回應**:
```json
{
  "success": false,
  "error": "詞卡已存在",
  "isDuplicate": true,
  "existingCard": {
    "id": "existing-id",
    "word": "elaborate",
    // ... 現有詞卡資料
  }
}
```

#### ✏️ PUT /api/flashcards/{id}
**功能**: 更新現有詞卡

**路徑參數**:
- `id`: 詞卡唯一識別碼 (GUID)

**請求體**: 與 POST 相同格式

**實際實現邏輯**:
```csharp
// 1. 查找現有詞卡
var flashcard = await _context.Flashcards
    .FirstOrDefaultAsync(f => f.Id == id && f.UserId == userId && !f.IsArchived);

if (flashcard == null)
{
    return NotFound(new { Success = false, Error = "詞卡不存在" });
}

// 2. 更新欄位
flashcard.Word = request.Word;
flashcard.Translation = request.Translation;
// ... 更新其他欄位
flashcard.UpdatedAt = DateTime.UtcNow;

// 3. 保存變更
await _context.SaveChangesAsync();
```

**成功回應**:
```json
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    // ... 更新後的完整詞卡資料
    "updatedAt": "2025-09-24T10:35:00Z"
  },
  "message": "詞卡更新成功"
}
```

#### 🗑️ DELETE /api/flashcards/{id}
**功能**: 刪除詞卡 (軟刪除機制)

**路徑參數**:
- `id`: 詞卡唯一識別碼 (GUID)

**實際實現邏輯**:
```csharp
// 軟刪除：設定 IsArchived = true
var flashcard = await _context.Flashcards
    .FirstOrDefaultAsync(f => f.Id == id && f.UserId == userId && !f.IsArchived);

if (flashcard == null)
{
    return NotFound(new { Success = false, Error = "詞卡不存在" });
}

flashcard.IsArchived = true;
flashcard.UpdatedAt = DateTime.UtcNow;
await _context.SaveChangesAsync();
```

**成功回應**:
```json
{
  "success": true,
  "message": "詞卡已刪除"
}
```

#### ⭐ POST /api/flashcards/{id}/favorite
**功能**: 切換詞卡的收藏狀態

**路徑參數**:
- `id`: 詞卡唯一識別碼 (GUID)

**實際實現邏輯**:
```csharp
var flashcard = await _context.Flashcards
    .FirstOrDefaultAsync(f => f.Id == id && f.UserId == userId && !f.IsArchived);

if (flashcard == null)
{
    return NotFound(new { Success = false, Error = "詞卡不存在" });
}

// 切換收藏狀態
flashcard.IsFavorite = !flashcard.IsFavorite;
flashcard.UpdatedAt = DateTime.UtcNow;
await _context.SaveChangesAsync();
```

**成功回應**:
```json
{
  "success": true,
  "data": {
    "isFavorite": true
  },
  "message": "已加入收藏"
}
```

## 4. 前端整合規格

### 4.1 FlashcardsService 類別

#### TypeScript 服務實現
```typescript
class FlashcardsService {
  private readonly baseURL = `${process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5008'}/api`;

  // 統一請求處理
  private async makeRequest<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
    const response = await fetch(`${this.baseURL}${endpoint}`, {
      headers: {
        'Content-Type': 'application/json',
        ...options.headers,
      },
      ...options,
    });

    if (!response.ok) {
      const errorData = await response.json().catch(() => ({ error: 'Network error' }));
      throw new Error(errorData.error || `HTTP ${response.status}`);
    }

    return response.json();
  }

  // API 方法實現
  async getFlashcards(search?: string, favoritesOnly: boolean = false): Promise<ApiResponse<{flashcards: Flashcard[], count: number}>> {
    const params = new URLSearchParams();
    if (search) params.append('search', search);
    if (favoritesOnly) params.append('favoritesOnly', 'true');

    const queryString = params.toString();
    const endpoint = `/flashcards${queryString ? `?${queryString}` : ''}`;

    return await this.makeRequest<ApiResponse<{flashcards: Flashcard[], count: number}>>(endpoint);
  }

  async createFlashcard(data: CreateFlashcardRequest): Promise<ApiResponse<Flashcard>> {
    return await this.makeRequest<ApiResponse<Flashcard>>('/flashcards', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  }

  async updateFlashcard(id: string, data: CreateFlashcardRequest): Promise<ApiResponse<Flashcard>> {
    return await this.makeRequest<ApiResponse<Flashcard>>(`/flashcards/${id}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async deleteFlashcard(id: string): Promise<ApiResponse<void>> {
    return await this.makeRequest<ApiResponse<void>>(`/flashcards/${id}`, {
      method: 'DELETE',
    });
  }

  async toggleFavorite(id: string): Promise<ApiResponse<void>> {
    return await this.makeRequest<ApiResponse<void>>(`/flashcards/${id}/favorite`, {
      method: 'POST',
    });
  }
}

export const flashcardsService = new FlashcardsService();
```

### 4.2 前端使用範例

#### 詞卡列表載入
```typescript
const loadFlashcards = async () => {
  try {
    setLoading(true);
    const result = await flashcardsService.getFlashcards();
    if (result.success && result.data) {
      setFlashcards(result.data.flashcards);
    } else {
      setError(result.error || 'Failed to load flashcards');
    }
  } catch (err) {
    setError('Failed to load flashcards');
  } finally {
    setLoading(false);
  }
};
```

#### 詞卡保存 (含重複檢測)
```typescript
const handleSaveWord = async (word: string, analysis: any) => {
  try {
    const cardData = {
      word: word,
      translation: analysis.translation || '',
      definition: analysis.definition || '',
      pronunciation: analysis.pronunciation || `/${word}/`,
      partOfSpeech: analysis.partOfSpeech || 'unknown',
      example: `Example sentence with ${word}.`
    };

    const response = await flashcardsService.createFlashcard(cardData);

    if (response.success) {
      alert(`✅ 已成功將「${word}」保存到詞卡庫！`);
      return { success: true };
    } else if (response.error && response.error.includes('已存在')) {
      alert(`⚠️ 詞卡「${word}」已經存在於詞卡庫中`);
      return { success: false, error: 'duplicate' };
    } else {
      throw new Error(response.error || '保存失敗');
    }
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : '保存失敗';
    alert(`❌ 保存詞卡失敗: ${errorMessage}`);
    return { success: false, error: errorMessage };
  }
};
```

## 5. 搜尋與篩選功能

### 5.1 後端搜尋實現

#### 支援的搜尋欄位
```csharp
// 目前實現的搜尋範圍
query = query.Where(f =>
    f.Word.Contains(search) ||           // 詞彙本身
    f.Translation.Contains(search) ||    // 中文翻譯
    (f.Definition != null && f.Definition.Contains(search)) // 英文定義
);

// 未來可擴展的搜尋範圍
// f.Example.Contains(search) ||         // 例句內容
// f.ExampleTranslation.Contains(search) // 例句翻譯
```

#### 搜尋邏輯特性
- **大小寫敏感**: 目前使用 `Contains()` 進行大小寫敏感搜尋
- **部分匹配**: 支援關鍵字部分匹配
- **邏輯運算**: OR 邏輯 (任一欄位包含關鍵字即匹配)

### 5.2 前端搜尋與篩選

#### 即時搜尋實現
```typescript
// 前端即時篩選邏輯
const filteredCards = allCards.filter(card => {
  // 基本文字搜尋
  if (searchTerm) {
    const searchLower = searchTerm.toLowerCase();
    const matchesText =
      card.word?.toLowerCase().includes(searchLower) ||
      card.translation?.toLowerCase().includes(searchLower) ||
      card.definition?.toLowerCase().includes(searchLower);

    if (!matchesText) return false;
  }

  // CEFR 等級篩選
  if (searchFilters.cefrLevel && card.difficultyLevel !== searchFilters.cefrLevel) {
    return false;
  }

  // 詞性篩選
  if (searchFilters.partOfSpeech && card.partOfSpeech !== searchFilters.partOfSpeech) {
    return false;
  }

  // 掌握度篩選
  if (searchFilters.masteryLevel) {
    const mastery = card.masteryLevel || 0;
    if (searchFilters.masteryLevel === 'high' && mastery < 80) return false;
    if (searchFilters.masteryLevel === 'medium' && (mastery < 60 || mastery >= 80)) return false;
    if (searchFilters.masteryLevel === 'low' && mastery >= 60) return false;
  }

  // 收藏篩選
  if (searchFilters.onlyFavorites && !card.isFavorite) {
    return false;
  }

  return true;
});
```

#### 進階篩選選項
```typescript
interface SearchFilters {
  cefrLevel: string;        // A1, A2, B1, B2, C1, C2
  partOfSpeech: string;     // noun, verb, adjective, adverb, preposition, interjection
  masteryLevel: string;     // high (80%+), medium (60-79%), low (<60%)
  onlyFavorites: boolean;   // 僅收藏詞卡
}
```

## 6. 錯誤處理機制

### 6.1 後端錯誤處理

#### 統一錯誤處理模式
```csharp
try
{
    // API 邏輯
    return Ok(new { Success = true, Data = result });
}
catch (DbUpdateException ex)
{
    _logger.LogError(ex, "Database error during flashcard operation");
    return StatusCode(500, new { Success = false, Error = "資料庫操作失敗" });
}
catch (ArgumentException ex)
{
    _logger.LogWarning(ex, "Invalid argument for flashcard operation");
    return BadRequest(new { Success = false, Error = ex.Message });
}
catch (Exception ex)
{
    _logger.LogError(ex, "Unexpected error during flashcard operation");
    return StatusCode(500, new { Success = false, Error = "內部伺服器錯誤" });
}
```

#### 特殊情況處理
```csharp
// 重複詞卡檢測
if (existing != null)
{
    return Ok(new
    {
        Success = false,
        Error = "詞卡已存在",
        IsDuplicate = true,
        ExistingCard = new { /* 現有詞卡資料 */ }
    });
}

// 詞卡不存在
if (flashcard == null)
{
    return NotFound(new { Success = false, Error = "詞卡不存在" });
}
```

### 6.2 前端錯誤處理

#### API 服務層錯誤處理
```typescript
private async makeRequest<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
  try {
    const response = await fetch(`${this.baseURL}${endpoint}`, options);

    if (!response.ok) {
      const errorData = await response.json().catch(() => ({ error: 'Network error' }));
      throw new Error(errorData.error || errorData.details || `HTTP ${response.status}`);
    }

    return response.json();
  } catch (error) {
    console.error('API request failed:', error);
    throw error;
  }
}
```

#### 用戶反饋機制
```typescript
// 成功操作反饋
if (response.success) {
  alert(`✅ 已成功將「${word}」保存到詞卡庫！`);
  return { success: true };
}

// 重複詞卡反饋
else if (response.error && response.error.includes('已存在')) {
  alert(`⚠️ 詞卡「${word}」已經存在於詞卡庫中`);
  return { success: false, error: 'duplicate' };
}

// 一般錯誤反饋
else {
  alert(`❌ 保存詞卡失敗: ${response.error}`);
  return { success: false, error: response.error };
}
```

## 7. 認證與授權

### 7.1 開發階段認證

#### 目前實現 (測試模式)
```csharp
[AllowAnonymous] // 暫時移除認證要求
public class FlashcardsController : ControllerBase
{
    private Guid GetUserId()
    {
        // 使用固定測試用戶 ID
        return Guid.Parse("00000000-0000-0000-0000-000000000001");
    }
}
```

#### 自動測試用戶創建
```csharp
// 確保測試用戶存在
var testUser = await _context.Users.FirstOrDefaultAsync(u => u.Id == userId);
if (testUser == null)
{
    testUser = new User
    {
        Id = userId,
        Username = "testuser",
        Email = "test@example.com",
        DisplayName = "測試用戶",
        SubscriptionType = "free",
        EnglishLevel = "A2",
        CreatedAt = DateTime.UtcNow
    };
    _context.Users.Add(testUser);
    await _context.SaveChangesAsync();
}
```

### 7.2 生產環境認證 (未來啟用)

#### JWT Token 解析
```csharp
[Authorize] // 生產環境啟用
public class FlashcardsController : ControllerBase
{
    private Guid GetUserId()
    {
        var userIdString = User.FindFirst(ClaimTypes.NameIdentifier)?.Value ??
                          User.FindFirst("sub")?.Value;

        if (Guid.TryParse(userIdString, out var userId))
            return userId;

        throw new UnauthorizedAccessException("Invalid user ID in token");
    }
}
```

## 8. 效能優化

### 8.1 資料庫查詢優化

#### 索引建議
```sql
-- 用戶詞卡查詢索引
CREATE INDEX IX_Flashcards_UserId_IsArchived ON Flashcards(UserId, IsArchived);

-- 搜尋優化索引
CREATE INDEX IX_Flashcards_Word ON Flashcards(Word);
CREATE INDEX IX_Flashcards_Translation ON Flashcards(Translation);

-- 收藏篩選索引
CREATE INDEX IX_Flashcards_IsFavorite ON Flashcards(IsFavorite);

-- 複合查詢索引
CREATE INDEX IX_Flashcards_UserId_IsFavorite_IsArchived ON Flashcards(UserId, IsFavorite, IsArchived);
```

#### 查詢優化技巧
```csharp
// 使用 AsNoTracking 提升查詢效能 (只讀查詢)
var flashcards = await query
    .AsNoTracking()
    .OrderByDescending(f => f.CreatedAt)
    .ToListAsync();

// 選擇性載入欄位 (避免載入不必要的關聯資料)
.Select(f => new {
    f.Id, f.Word, f.Translation, f.Definition,
    // 僅選擇需要的欄位
})
```

### 8.2 快取策略 (未來實現)

#### 記憶體快取
```csharp
// 用戶詞卡列表快取 (30分鐘)
var cacheKey = $"flashcards:user:{userId}";
var cachedCards = await _cacheService.GetAsync<List<Flashcard>>(cacheKey);

if (cachedCards == null)
{
    cachedCards = await LoadFlashcardsFromDatabase(userId);
    await _cacheService.SetAsync(cacheKey, cachedCards, TimeSpan.FromMinutes(30));
}
```

#### 搜尋結果快取
```csharp
// 搜尋結果快取 (10分鐘)
var searchCacheKey = $"search:{userId}:{searchTerm}:{favoritesOnly}";
var cachedResults = await _cacheService.GetAsync<SearchResult>(searchCacheKey);
```

## 9. 測試規格

### 9.1 API 測試用例

#### 功能測試
```bash
# 測試詞卡創建
curl -X POST http://localhost:5008/api/flashcards \
  -H "Content-Type: application/json" \
  -d '{
    "word": "test",
    "translation": "測試",
    "definition": "A trial or examination",
    "pronunciation": "/test/",
    "partOfSpeech": "noun",
    "example": "This is a test sentence"
  }'

# 測試搜尋功能
curl "http://localhost:5008/api/flashcards?search=test"

# 測試收藏功能
curl -X POST http://localhost:5008/api/flashcards/{id}/favorite

# 測試詞卡更新
curl -X PUT http://localhost:5008/api/flashcards/{id} \
  -H "Content-Type: application/json" \
  -d '{ /* 更新的詞卡資料 */ }'

# 測試詞卡刪除
curl -X DELETE http://localhost:5008/api/flashcards/{id}
```

#### 邊界條件測試
```bash
# 測試重複詞卡創建
curl -X POST http://localhost:5008/api/flashcards \
  -d '{"word": "existing-word", ...}'
# 預期回應: success: false, isDuplicate: true

# 測試不存在的詞卡操作
curl http://localhost:5008/api/flashcards/non-existent-id
# 預期回應: 404 Not Found

# 測試空搜尋
curl "http://localhost:5008/api/flashcards?search="
# 預期回應: 返回所有詞卡
```

### 9.2 效能測試

#### 載入測試
```bash
# 測試大量詞卡載入 (1000+ 詞卡)
time curl "http://localhost:5008/api/flashcards"
# 預期: < 2秒

# 測試搜尋效能
time curl "http://localhost:5008/api/flashcards?search=sophisticated"
# 預期: < 300ms
```

## 10. 部署與監控

### 10.1 健康檢查

#### API 健康檢查端點
```csharp
// Program.cs 中配置
services.AddHealthChecks()
    .AddDbContextCheck<DramaLingDbContext>();

app.MapHealthChecks("/health");
```

**健康檢查請求**:
```bash
curl http://localhost:5008/health
```

### 10.2 日誌監控

#### 結構化日誌
```csharp
_logger.LogInformation("Creating flashcard for user {UserId}, word: {Word}",
    userId, request.Word);

_logger.LogError(ex, "Failed to create flashcard for user {UserId}", userId);

_logger.LogWarning("Duplicate flashcard creation attempt: {Word} for user {UserId}",
    request.Word, userId);
```

#### 關鍵指標監控
- **API 響應時間**: 平均 < 200ms
- **成功率**: > 99.5%
- **重複詞卡檢測**: 準確率 100%
- **資料庫連接**: 健康狀態監控

---

**文檔版本**: v1.0
**建立日期**: 2025-09-24
**基於**: FlashcardsController.cs v1.0
**維護負責**: API 開發團隊
**更新頻率**: 控制器變更時同步更新

> 📋 **相關參考文檔**
>
> **📋 需求與規格**
> - [詞卡管理功能需求規格](../../01_requirement/詞卡管理功能產品需求規格.md) - 查看完整功能需求和用戶故事
>
> **🏗️ 技術架構**
> - [後端架構詳細說明](../../04_technical/backend-architecture.md) - 了解後端技術實現細節
> - [前端架構詳細說明](../../04_technical/frontend-architecture.md) - 了解前端整合方式