# شكل استجابات API الموحّد

هذا الملف يوثّق الظرف (envelope) الموحّد لكل استجابات `api/v1/*`، وهو مبني على
[`App\Traits\ApiResponseTrait`](../../app/Traits/ApiResponseTrait.php) و
[`App\Traits\ApiCode`](../../app/Traits/ApiCode.php).

## الظرف الأساسي

كل استجابة — نجاح أو فشل — بترجع بنفس الشكل:

```json
{
  "success": true,
  "code": "OK",
  "message": "تمت العملية بنجاح",
  "data": {},
  "meta": {},
  "errors": null
}
```

| المفتاح | النوع | الوصف |
|---|---|---|
| `success` | boolean | `true` للنجاح، `false` للفشل |
| `code` | string | كود ثابت لا يتغيّر مع اللغة — الموبايل يتفرّع عليه (انظر الجدول تحت) |
| `message` | string | رسالة قابلة للعرض، بلغة الطلب (`Accept-Language`) |
| `data` | object\|array\|null | بيانات النجاح. `{}` لو مفيش بيانات، `null` في الأخطاء |
| `meta` | object | بيانات إضافية — `pagination` للقوائم المرقّمة، `retry_after` لـ 429 |
| `errors` | object\|null | أخطاء التحقق (لكل حقل مصفوفة رسائل) — غير ذلك `null` |

## الهيدرز المطلوبة

| Header | إجباري؟ | الوصف |
|---|---|---|
| `Accept: application/json` | **نعم** | بدونه، أي طلب لمسار محمي هيرجع HTML redirect بدل JSON |
| `Authorization: Bearer {token}` | للمسارات المحمية | توكن Sanctum |
| `Accept-Language: ar\|en` | لا (افتراضي `ar`) | يحدد لغة `message` وأي نص مترجم في `data` |

## جدول الأكواد

| `code` | HTTP | يحصل امتى | رد فعل الموبايل المتوقع |
|---|---|---|---|
| `OK` | 200 | نجاح عملية قراءة/تحديث | عرض البيانات |
| `CREATED` | 201 | نجاح إنشاء مورد جديد | عرض البيانات / الانتقال للشاشة التالية |
| `NO_CONTENT` | 204 | نجاح بدون بيانات رجوع (مثل حذف) | إغلاق الشاشة / تحديث القائمة |
| `VALIDATION_ERROR` | 422 | فشل التحقق من صحة المدخلات | عرض رسائل الأخطاء تحت كل حقل من `errors` |
| `UNAUTHENTICATED` | 401 | التوكن غايب أو منتهي أو غير صالح | تسجيل خروج محلي + الرجوع لشاشة الدخول |
| `INVALID_CREDENTIALS` | 401 | بيانات دخول (هاتف/إيميل + كلمة مرور) غلط | عرض رسالة الخطأ تحت نموذج الدخول |
| `FORBIDDEN` | 403 | المستخدم مسجّل دخول لكن مالوش صلاحية | عرض رسالة "غير مصرح" |
| `NOT_FOUND` | 404 | المورد المطلوب مش موجود | عرض شاشة "غير موجود" / الرجوع للخلف |
| `CONFLICT` | 409 | تعارض مع الحالة الحالية للبيانات | عرض رسالة الخطأ كـ toast/dialog |
| `MEDICAL_PROFILE_REQUIRED` | 428 | العملية محتاجة ملف طبي مكتمل أولاً | فتح مودال "أكمل ملفك الصحي" |
| `FORCE_UPDATE_REQUIRED` | 426 | إصدار التطبيق أقل من الحد الأدنى المطلوب | فتح شاشة التحديث الإجباري (بلا إمكانية تخطي) |
| `TOO_MANY_REQUESTS` | 429 | تجاوز حد المحاولات المسموح (throttle) | تعطيل الزر + عرض `meta.retry_after` بالثواني |
| `SERVER_ERROR` | 500 | خطأ غير متوقع في السيرفر | عرض رسالة عامة + زر إعادة محاولة |
| `MAINTENANCE` | 503 | الخدمة تحت الصيانة | عرض شاشة صيانة |

## أمثلة

### نجاح — عنصر مفرد

```json
{
  "success": true,
  "code": "OK",
  "message": "تمت العملية بنجاح",
  "data": {
    "id": 12,
    "name": "أحمد محمد"
  },
  "meta": {},
  "errors": null
}
```

### نجاح — قائمة مرقّمة (pagination)

```json
{
  "success": true,
  "code": "OK",
  "message": "تمت العملية بنجاح",
  "data": [
    { "id": 1, "name": "..." },
    { "id": 2, "name": "..." }
  ],
  "meta": {
    "pagination": {
      "current_page": 1,
      "per_page": 15,
      "total": 42,
      "last_page": 3
    }
  },
  "errors": null
}
```

### إنشاء (201)

```json
{
  "success": true,
  "code": "CREATED",
  "message": "تم الإنشاء بنجاح",
  "data": { "id": 55 },
  "meta": {},
  "errors": null
}
```

### 422 — أخطاء تحقق

```json
{
  "success": false,
  "code": "VALIDATION_ERROR",
  "message": "البيانات المدخلة غير صحيحة",
  "data": null,
  "meta": {},
  "errors": {
    "phone": ["رقم الهاتف مستخدم من قبل"],
    "password": ["كلمة المرور يجب ألا تقل عن 8 أحرف"]
  }
}
```

### 401 — غير مسجّل دخول

```json
{
  "success": false,
  "code": "UNAUTHENTICATED",
  "message": "يجب تسجيل الدخول أولاً",
  "data": null,
  "meta": {},
  "errors": null
}
```

### 401 — بيانات دخول خاطئة

```json
{
  "success": false,
  "code": "INVALID_CREDENTIALS",
  "message": "بيانات الدخول غير صحيحة",
  "data": null,
  "meta": {},
  "errors": null
}
```

### 403 — ممنوع

```json
{
  "success": false,
  "code": "FORBIDDEN",
  "message": "غير مصرح لك بتنفيذ هذا الإجراء",
  "data": null,
  "meta": {},
  "errors": null
}
```

### 404 — غير موجود

```json
{
  "success": false,
  "code": "NOT_FOUND",
  "message": "العنصر المطلوب غير موجود",
  "data": null,
  "meta": {},
  "errors": null
}
```

### 409 — تعارض

```json
{
  "success": false,
  "code": "CONFLICT",
  "message": "هذا الطلب يتعارض مع الحالة الحالية",
  "data": null,
  "meta": {},
  "errors": null
}
```

### 428 — الملف الطبي مطلوب

```json
{
  "success": false,
  "code": "MEDICAL_PROFILE_REQUIRED",
  "message": "يرجى إكمال ملفك الطبي أولاً",
  "data": null,
  "meta": {},
  "errors": null
}
```

### 426 — تحديث إجباري

```json
{
  "success": false,
  "code": "FORCE_UPDATE_REQUIRED",
  "message": "يرجى تحديث التطبيق للمتابعة",
  "data": null,
  "meta": {},
  "errors": null
}
```

### 429 — محاولات كتيرة

```json
{
  "success": false,
  "code": "TOO_MANY_REQUESTS",
  "message": "عدد كبير من المحاولات، يرجى المحاولة لاحقاً",
  "data": null,
  "meta": {
    "retry_after": 45
  },
  "errors": null
}
```

### 500 — خطأ سيرفر

```json
{
  "success": false,
  "code": "SERVER_ERROR",
  "message": "حدث خطأ ما، يرجى المحاولة مرة أخرى",
  "data": null,
  "meta": {},
  "errors": null
}
```

## ملاحظات التنفيذ

- كل الاستجابات بتتولّد من `App\Traits\ApiResponseTrait` — الاستخدام يكون عبر controller
  يورّث `App\Http\Controllers\Api\V1\BaseApiController` (اللي بيستخدم التريت).
- أخطاء الاستثناءات (exceptions) غير المعالجة يدويًا بتتحول تلقائيًا لنفس الظرف عبر
  `withExceptions()` في [`bootstrap/app.php`](../../bootstrap/app.php) — مفيش أي مسار في
  `api/*` بيرجّع HTML أو نص خام.
- رسالة `SERVER_ERROR` ثابتة دايمًا ولا تحتوي على تفاصيل الاستثناء الحقيقي، منعًا لتسريب
  معلومات داخلية (نفس القاعدة اللي لازم تتطبّق على أي كود جديد في الـ API).
