# 人物資料修正機制指南

> **版本**: 1.0 | **適用**: 前端開發團隊  
> **目的**: 當發現 Person 綁定資料錯誤時，如何修正

---

## 修正場景總覽

| 錯誤類型 | 修正 API | 可否復原 |
|---------|:---:|:---:|
| 錯誤綁定 Speaker | `POST /person/:id/unbind-speaker` | ✅ 可重新綁定 |
| 綁錯 Speaker | `POST /person/:id/reassign-speaker` | ✅ 可再次修改 |
| 錯誤 Appearance | `POST /person/:id/remove-appearance` | ⚠️ 需手動重建 |
| Appearance 分錯人 | `POST /person/:id/reassign-appearance` | ✅ 可再轉移 |
| 兩人被合併為一人 | `POST /person/:id/split` | ⚠️ 需手動重建原資料 |
| 錯誤合併 | `POST /person/merge/undo` | ✅ 可撤銷（需 merge_id） |
| 錯誤命名 | `PATCH /person/:id` | ✅ 可隨時修改 |

---

## 1. Speaker 綁定修正

### 1.1 解除 Speaker 綁定

當發現某人物不應該綁定到某個 Speaker 時：

```bash
curl -X POST "$BASE/api/v1/person/Person_0/unbind-speaker" \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason": "ASRX 識別錯誤，此人物不是 SPEAKER_0"}'
```

```json
{
  "success": true,
  "message": "Speaker unbound from person 'Person_0'",
  "person_id": "Person_0",
  "reason": "ASRX 識別錯誤，此人物不是 SPEAKER_0"
}
```

**效果**:
- `speaker_id` 設為 `NULL`
- `metadata.speaker_unbound` 設為 `true`
- 不影響 `appearance_count` 和 `person_appearances`

### 1.2 重新綁定 Speaker

當發現人物應該綁定到不同的 Speaker 時：

```bash
curl -X POST "$BASE/api/v1/person/Person_0/reassign-speaker" \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"speaker_id": "SPEAKER_1", "reason": "修正：此人物實際上是 SPEAKER_1"}'
```

```json
{
  "success": true,
  "message": "Speaker 'SPEAKER_1' assigned to person 'Person_0'",
  "person_id": "Person_0",
  "new_speaker_id": "SPEAKER_1",
  "reason": "修正：此人物實際上是 SPEAKER_1"
}
```

---

## 2. Appearance（出場紀錄）修正

### 2.1 刪除錯誤的 Appearance

當發現某筆出場紀錄不應該屬於該人物：

```bash
curl -X POST "$BASE/api/v1/person/Person_0/remove-appearance" \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"appearance_id": 12345, "reason": "此時間段實際上是空鏡頭"}'
```

```json
{
  "success": true,
  "message": "Appearance 12345 removed from person 'Person_0'",
  "appearance_id": 12345,
  "person_id": "Person_0",
  "removed_duration": 3.5,
  "reason": "此時間段實際上是空鏡頭"
}
```

**效果**:
- 刪除指定的 `person_appearances` 紀錄
- 自動更新 `appearance_count` 和 `total_appearance_duration`
- 不刪除人物本身

### 2.2 轉移 Appearance 到另一人物

當發現某筆出場紀錄應該屬於另一個人物：

```bash
curl -X POST "$BASE/api/v1/person/Person_0/reassign-appearance" \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "appearance_id": 12345,
    "target_person_id": "Person_17",
    "reason": "此時間段臉孔比對顯示是 Person_17"
  }'
```

```json
{
  "success": true,
  "message": "Appearance 12345 reassigned from 'Person_0' to 'Person_17'",
  "appearance_id": 12345,
  "from_person_id": "Person_0",
  "to_person_id": "Person_17",
  "reason": "此時間段臉孔比對顯示是 Person_17"
}
```

**效果**:
- 更新 `person_appearances.person_id`
- 自動調整兩個人物的 `appearance_count` 和 `total_appearance_duration`

---

## 3. 人物分割（Split）

當發現兩個人物被錯誤地識別為同一人時：

```bash
curl -X POST "$BASE/api/v1/person/Person_0/split" \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "new_person_id": "Person_0_split",
    "appearance_ids_to_move": [12345, 12346, 12347],
    "new_person_name": "Unknown Person",
    "reason": "Person_0 實際上是兩個不同的人"
  }'
```

```json
{
  "success": true,
  "message": "Person 'Person_0' split into 'Person_0_split' with 3 appearances moved",
  "original_person_id": "Person_0",
  "new_person_id": "Person_0_split",
  "appearances_moved": 3,
  "new_person_duration": 12.5,
  "new_person_first": 5730.0,
  "new_person_last": 5745.0,
  "reason": "Person_0 實際上是兩個不同的人"
}
```

**效果**:
- 建立新人物 `Person_0_split`
- 將指定的 `person_appearances` 移至新人物
- 自動更新兩個人物的統計數據
- 新人物的 `metadata.split_from` 記錄原始人物 ID

---

## 4. 合併撤銷

當發現合併錯誤時：

```bash
# 查看合併歷史
curl "$BASE/api/v1/person/merge/history" -H "X-API-Key: $KEY"

# 撤銷合併
curl -X POST "$BASE/api/v1/person/merge/undo" \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"merge_id": "5b12e3ac-12fa-45c0-88e1-5cff67604a7d"}'
```

**⚠️ 限制**: 只有透過 API 執行的合併才有歷史記錄，可撤銷。

---

## 5. 名稱修正

最簡單的修正，隨時可改：

```bash
curl -X PATCH "$BASE/api/v1/person/Person_0" \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Cary Grant",
    "is_confirmed": true,
    "metadata": {
      "corrected_by": "user123",
      "correction_date": "2026-04-14"
    }
  }'
```

---

## 完整修正流程範例

### 情境：Person_0 被錯誤識別

```
1. 發現問題：Person_0 綁定到 SPEAKER_0，但實際上 30% 的出場是另一人

2. 解除錯誤綁定（可選）
   POST /api/v1/person/Person_0/unbind-speaker
   → speaker_id = NULL

3. 找出錯誤的 appearances
   GET /api/v1/person/Person_0/appearances
   → 檢視每筆出場紀錄的時間戳

4. 將錯誤 appearances 轉移到新人物
   # 建立新人物（由 split API 自動建立）
   POST /api/v1/person/Person_0/split
   {
     "new_person_id": "Person_100",
     "appearance_ids_to_move": [12340, 12341, ...],
     "new_person_name": "Unknown Actor"
   }

5. 重新綁定正確的 speaker
   POST /api/v1/person/Person_0/reassign-speaker
   {"speaker_id": "SPEAKER_0"}

6. 為新人物命名
   PATCH /api/v1/person/Person_100
   {"name": "Supporting Actor"}
```

---

## API 速查表

| 修正類型 | 方法 | 端點 |
|---------|:---:|------|
| 解除 Speaker | POST | `/api/v1/person/:id/unbind-speaker` |
| 重新綁定 Speaker | POST | `/api/v1/person/:id/reassign-speaker` |
| 刪除 Appearance | POST | `/api/v1/person/:id/remove-appearance` |
| 轉移 Appearance | POST | `/api/v1/person/:id/reassign-appearance` |
| 分割人物 | POST | `/api/v1/person/:id/split` |
| 撤銷合併 | POST | `/api/v1/person/merge/undo` |
| 查看合併歷史 | GET | `/api/v1/person/merge/history` |
| 修改名稱 | PATCH | `/api/v1/person/:id` |

---

## 注意事項

### 哪些修正可以完全復原？

| 修正類型 | 復原方式 |
|---------|---------|
| 解除 Speaker | 使用 `reassign-speaker` 重新綁定 |
| 重新綁定 Speaker | 再次使用 `reassign-speaker` |
| 刪除 Appearance | ⚠️ 無法自動復原，需手動重建 |
| 轉移 Appearance | 使用 `reassign-appearance` 轉移回去 |
| 分割人物 | ⚠️ 無法自動復原，需使用合併 API |
| 撤銷合併 | 無法再次撤銷（已撤銷過） |
| 修改名稱 | 再次使用 `PATCH` |

### 建議操作順序

1. **先檢視**: 使用 `GET /person/:id/appearances` 確認哪些資料錯誤
2. **小幅度修正**: 先嘗試 `unbind-speaker` 或 `reassign-appearance`
3. **大幅度修正**: 如需要分割人物，使用 `split`
4. **記錄原因**: 每個修正 API 都支援 `reason` 欄位，建議填寫

### 資料完整性

所有修正操作都會：
- 自動更新 `appearance_count` 和 `total_appearance_duration`
- 在 `metadata` 中記錄修正痕跡
- 使用資料庫交易確保一致性
