# API Usage Examples - Lesson Attachments

## 📎 Lesson Attachments Endpoints

---

## 1. Upload Attachment (Instructor)

### POST `/instructor/courses/:courseId/lessons/:lessonId/attachments`

#### Request:
```http
POST /api/instructor/courses/1/lessons/5/attachments
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: multipart/form-data

file: <slides.pdf>
description_th: "สไลด์ประกอบการสอน"
description_en: "Lecture slides"
sort_order: 1
```

#### Response 201:
```json
{
  "id": 10,
  "lesson_id": 5,
  "file_name": "slides.pdf",
  "file_path": "lessons/5/slides.pdf",
  "file_size": 2048576,
  "mime_type": "application/pdf",
  "description": {
    "th": "สไลด์ประกอบการสอน",
    "en": "Lecture slides"
  },
  "sort_order": 1,
  "download_url": "/api/lessons/5/attachments/10/download",
  "created_at": "2024-12-23T15:00:00Z"
}
```

#### Response 422 (File Too Large):
```json
{
  "error": {
    "code": "FILE_TOO_LARGE",
    "message": "File size exceeds maximum limit of 100 MB",
    "file_size": 104857600,
    "max_size": 104857600
  }
}
```

#### Response 422 (Too Many Attachments):
```json
{
  "error": {
    "code": "MAX_ATTACHMENTS_EXCEEDED",
    "message": "Maximum 10 attachments per lesson",
    "current_count": 10,
    "max_count": 10
  }
}
```

#### Response 422 (Invalid File Type):
```json
{
  "error": {
    "code": "INVALID_FILE_TYPE",
    "message": "File type not allowed",
    "mime_type": "application/x-executable",
    "allowed_types": ["application/pdf", "application/zip", "image/jpeg", "..."]
  }
}
```

---

## 2. List Attachments (Instructor)

### GET `/instructor/courses/:courseId/lessons/:lessonId/attachments`

#### Request:
```http
GET /api/instructor/courses/1/lessons/5/attachments
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

#### Response 200:
```json
{
  "lesson_id": 5,
  "attachments": [
    {
      "id": 10,
      "file_name": "slides.pdf",
      "file_size": 2048576,
      "mime_type": "application/pdf",
      "description": {
        "th": "สไลด์ประกอบการสอน",
        "en": "Lecture slides"
      },
      "sort_order": 1,
      "download_url": "/api/lessons/5/attachments/10/download",
      "created_at": "2024-12-23T15:00:00Z"
    },
    {
      "id": 11,
      "file_name": "code.zip",
      "file_size": 512000,
      "mime_type": "application/zip",
      "description": {
        "th": "โค้ดตัวอย่าง",
        "en": "Sample code"
      },
      "sort_order": 2,
      "download_url": "/api/lessons/5/attachments/11/download",
      "created_at": "2024-12-23T15:05:00Z"
    },
    {
      "id": 12,
      "file_name": "exercises.docx",
      "file_size": 256000,
      "mime_type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
      "description": {
        "th": "แบบฝึกหัด",
        "en": "Exercises"
      },
      "sort_order": 3,
      "download_url": "/api/lessons/5/attachments/12/download",
      "created_at": "2024-12-23T15:10:00Z"
    }
  ],
  "total": 3
}
```

---

## 3. Update Attachment Info (Instructor)

### PUT `/instructor/courses/:courseId/lessons/:lessonId/attachments/:attachmentId`

#### Request:
```http
PUT /api/instructor/courses/1/lessons/5/attachments/10
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

{
  "description": {
    "th": "สไลด์ประกอบการสอน (ฉบับแก้ไข)",
    "en": "Lecture slides (revised)"
  },
  "sort_order": 2
}
```

#### Response 200:
```json
{
  "id": 10,
  "lesson_id": 5,
  "file_name": "slides.pdf",
  "file_size": 2048576,
  "mime_type": "application/pdf",
  "description": {
    "th": "สไลด์ประกอบการสอน (ฉบับแก้ไข)",
    "en": "Lecture slides (revised)"
  },
  "sort_order": 2,
  "updated_at": "2024-12-23T15:20:00Z"
}
```

---

## 4. Delete Attachment (Instructor)

### DELETE `/instructor/courses/:courseId/lessons/:lessonId/attachments/:attachmentId`

#### Request:
```http
DELETE /api/instructor/courses/1/lessons/5/attachments/10
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

#### Response 204:
```
No Content
```

---

## 5. Reorder Attachments (Instructor)

### PUT `/instructor/courses/:courseId/lessons/:lessonId/attachments/reorder`

#### Request:
```http
PUT /api/instructor/courses/1/lessons/5/attachments/reorder
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

{
  "attachments": [
    { "id": 11, "sort_order": 1 },
    { "id": 12, "sort_order": 2 },
    { "id": 10, "sort_order": 3 }
  ]
}
```

#### Response 200:
```json
{
  "message": "Attachments reordered successfully",
  "attachments": [
    {
      "id": 11,
      "file_name": "code.zip",
      "sort_order": 1
    },
    {
      "id": 12,
      "file_name": "exercises.docx",
      "sort_order": 2
    },
    {
      "id": 10,
      "file_name": "slides.pdf",
      "sort_order": 3
    }
  ]
}
```

---

## 6. Get Lesson with Attachments (Student)

### GET `/students/courses/:courseId/lessons/:lessonId`

**Changes**: เพิ่ม `attachments` array

#### Request:
```http
GET /api/students/courses/1/lessons/5
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

#### Response 200:
```json
{
  "id": 5,
  "title": "บทที่ 3: ทฤษฎี",
  "content": "<p>เนื้อหาบทเรียน...</p>",
  "type": "video",
  "video_url": "https://cdn.example.com/videos/lesson-5.m3u8",
  "duration": "00:25:00",
  "is_completed": false,
  "can_access": true,
  
  "attachments": [
    {
      "id": 11,
      "file_name": "code.zip",
      "file_size": 512000,
      "mime_type": "application/zip",
      "description": "โค้ดตัวอย่าง",
      "download_url": "/api/lessons/5/attachments/11/download"
    },
    {
      "id": 12,
      "file_name": "exercises.docx",
      "file_size": 256000,
      "mime_type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
      "description": "แบบฝึกหัด",
      "download_url": "/api/lessons/5/attachments/12/download"
    },
    {
      "id": 10,
      "file_name": "slides.pdf",
      "file_size": 2048576,
      "mime_type": "application/pdf",
      "description": "สไลด์ประกอบการสอน",
      "download_url": "/api/lessons/5/attachments/10/download"
    }
  ]
}
```

---

## 7. Download Attachment

### GET `/lessons/:lessonId/attachments/:attachmentId/download`

#### Request:
```http
GET /api/lessons/5/attachments/10/download
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

#### Response 200:
```http
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="slides.pdf"
Content-Length: 2048576

<binary file data>
```

#### Response 403 (Not Enrolled):
```json
{
  "error": {
    "code": "NOT_ENROLLED",
    "message": "You must enroll in this course to download attachments",
    "course_id": 1
  }
}
```

---

## Frontend Integration Examples

### 1. Upload Attachment Component

```javascript
async function uploadAttachment(courseId, lessonId, file, description) {
  const formData = new FormData();
  formData.append('file', file);
  formData.append('description_th', description.th);
  formData.append('description_en', description.en);
  formData.append('sort_order', 1);
  
  try {
    const response = await fetch(
      `/api/instructor/courses/${courseId}/lessons/${lessonId}/attachments`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${token}`
        },
        body: formData
      }
    );
    
    if (!response.ok) {
      const error = await response.json();
      
      if (error.error.code === 'FILE_TOO_LARGE') {
        showAlert('ไฟล์ใหญ่เกินไป (สูงสุด 100 MB)');
      } else if (error.error.code === 'MAX_ATTACHMENTS_EXCEEDED') {
        showAlert('แนบไฟล์ได้สูงสุด 10 ไฟล์');
      } else if (error.error.code === 'INVALID_FILE_TYPE') {
        showAlert('ประเภทไฟล์ไม่รองรับ');
      }
      return;
    }
    
    const data = await response.json();
    showSuccess('อัปโหลดไฟล์สำเร็จ');
    return data;
  } catch (error) {
    console.error('Upload error:', error);
    showAlert('เกิดข้อผิดพลาดในการอัปโหลด');
  }
}
```

### 2. Display Attachments List

```javascript
function AttachmentsList({ attachments }) {
  return (
    <div className="attachments-list">
      <h3>📎 ไฟล์แนบ ({attachments.length})</h3>
      
      {attachments.map(attachment => (
        <div key={attachment.id} className="attachment-item">
          <div className="file-icon">
            {getFileIcon(attachment.mime_type)}
          </div>
          
          <div className="file-info">
            <div className="file-name">{attachment.file_name}</div>
            <div className="file-description">{attachment.description}</div>
            <div className="file-size">{formatFileSize(attachment.file_size)}</div>
          </div>
          
          <a 
            href={attachment.download_url}
            download
            className="download-button"
          >
            ⬇ ดาวน์โหลด
          </a>
        </div>
      ))}
    </div>
  );
}

function getFileIcon(mimeType) {
  if (mimeType.includes('pdf')) return '📄';
  if (mimeType.includes('zip')) return '📦';
  if (mimeType.includes('word')) return '📝';
  if (mimeType.includes('excel')) return '📊';
  if (mimeType.includes('powerpoint')) return '📊';
  if (mimeType.includes('image')) return '🖼️';
  return '📎';
}

function formatFileSize(bytes) {
  if (bytes < 1024) return bytes + ' B';
  if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
  return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
}
```

### 3. Drag & Drop Reorder

```javascript
function ReorderAttachments({ attachments, onReorder }) {
  const [items, setItems] = useState(attachments);
  
  const handleDragEnd = (result) => {
    if (!result.destination) return;
    
    const reordered = Array.from(items);
    const [removed] = reordered.splice(result.source.index, 1);
    reordered.splice(result.destination.index, 0, removed);
    
    // Update sort_order
    const updated = reordered.map((item, index) => ({
      id: item.id,
      sort_order: index + 1
    }));
    
    setItems(reordered);
    onReorder(updated);
  };
  
  return (
    <DragDropContext onDragEnd={handleDragEnd}>
      <Droppable droppableId="attachments">
        {(provided) => (
          <div {...provided.droppableProps} ref={provided.innerRef}>
            {items.map((item, index) => (
              <Draggable key={item.id} draggableId={String(item.id)} index={index}>
                {(provided) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                  >
                    {item.file_name}
                  </div>
                )}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  );
}
```

---

## Allowed File Types

| Category | MIME Type | Extension |
|----------|-----------|-----------|
| **Documents** | `application/pdf` | .pdf |
| | `application/msword` | .doc |
| | `application/vnd.openxmlformats-officedocument.wordprocessingml.document` | .docx |
| | `application/vnd.ms-excel` | .xls |
| | `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` | .xlsx |
| | `application/vnd.ms-powerpoint` | .ppt |
| | `application/vnd.openxmlformats-officedocument.presentationml.presentation` | .pptx |
| **Archives** | `application/zip` | .zip |
| | `application/x-rar-compressed` | .rar |
| | `application/x-7z-compressed` | .7z |
| **Images** | `image/jpeg` | .jpg |
| | `image/png` | .png |
| | `image/gif` | .gif |
| **Text** | `text/plain` | .txt |
| | `text/csv` | .csv |

---

## File Limits

- **Max file size**: 100 MB per file
- **Max attachments**: 10 files per lesson
- **Total size**: 500 MB per lesson

---

## Summary

**New Endpoints**: 6
- `POST /instructor/courses/:courseId/lessons/:lessonId/attachments`
- `GET /instructor/courses/:courseId/lessons/:lessonId/attachments`
- `PUT /instructor/courses/:courseId/lessons/:lessonId/attachments/:attachmentId`
- `DELETE /instructor/courses/:courseId/lessons/:lessonId/attachments/:attachmentId`
- `PUT /instructor/courses/:courseId/lessons/:lessonId/attachments/reorder`
- `GET /lessons/:lessonId/attachments/:attachmentId/download`

**Modified Endpoints**: 2
- `GET /students/courses/:courseId/lessons/:lessonId` - เพิ่ม attachments array
- `GET /students/courses/:courseId/learn` - เพิ่ม attachments_count
