# Subscription API

مدیریت پنل‌های اشتراکی (Free / Basic / Professional).

---

## GET /api/v1/subscription/plans

لیست پنل‌ها با دوره‌های فعال (عمومی — بدون auth).

> پلن `free`: همه امکانات (`patient_records`, `services`, `sms_panel`, `insurance`) فعال‌اند؛ تنها محدودیت آن تعداد منشی (`max_secretaries`) است.

**Response 200:**
```json
{
  "success": true,
  "data": [
    {
      "uuid": "...",
      "name": "free",
      "level": 0,
      "max_secretaries": 1,
      "features": { "patient_records": true, "services": true, "sms_panel": true, "insurance": true },
      "active": true,
      "periods": []
    },
    {
      "uuid": "...",
      "name": "basic",
      "level": 1,
      "max_secretaries": 3,
      "features": { "patient_records": true, "services": true, "sms_panel": false },
      "active": true,
      "periods": [
        {
          "uuid": "...",
          "plan_uuid": "...",
          "label": "یک ماهه",
          "duration_months": 1,
          "price_rials": 290000,
          "is_trial": false,
          "active": true,
          "sort_order": 1
        }
      ]
    }
  ]
}
```

---

## GET /api/v1/subscription/my

اشتراک فعال کاربر جاری.

**Permission:** `IS_AUTHENTICATED_FULLY`

**نکته:** از نسخه فعلی، این endpoint برای `ROLE_SECRETARY` نیز کار می‌کند. منشی از طریق `UserActiveContextRepository` به `db_uuid` entity مربوطه (doctor یا clinic) دسترسی پیدا می‌کند و اشتراک همان entity برگردانده می‌شود.

**Response 200:**
```json
{
  "success": true,
  "data": {
    "subscription": {
      "uuid": "...",
      "plan": { "name": "basic", "level": 1, "max_secretaries": 3, "features": {...} },
      "period": { "label": "یک ماهه", "duration_months": 1, "price_rials": 290000 },
      "is_trial": false,
      "starts_at": 1718000000,
      "expires_at": 1720678400,
      "days_remaining": 30,
      "is_active": true
    },
    "used_trial": false,
    "effective_plan": { "name": "basic", "level": 1, "max_secretaries": 3, "features": {...} }
  }
}
```

اگر اشتراک فعالی نداشت `subscription` برابر `null` است، اما `effective_plan` همیشه مقدار دارد: پلن اشتراک فعال، یا در نبود اشتراک، **پلن پیش‌فرض `free`**. فرانت‌اند برای تعیین دسترسی به امکانات (`hasFeature`) باید از `effective_plan` استفاده کند (نه `subscription`) تا کاربرانِ بدون اشتراک هم امکانات پلن free را داشته باشند. `subscription`/`hasPlan` صرفاً برای نمایش وضعیت اشتراک پولی است.

---

## POST /api/v1/subscription/trial

فعال‌سازی تریال رایگان (یکبار برای هر entity).

**Permission:** `IS_AUTHENTICATED_FULLY`

**Response 201:** همان ساختار ClinicSubscription

**Errors:**
| Code | HTTP | توضیح |
|------|------|-------|
| ERR_TRIAL_ALREADY_USED | 422 | قبلاً از تریال استفاده شده |
| ERR_TRIAL_DISABLED | 422 | تریال غیرفعال است (SiteConfig: trial_enabled=0) |
| ERR_FORBIDDEN_001 | 403 | پروفایل doctor/clinic یافت نشد |

---

## POST /api/v1/subscription-payment

شروع پرداخت اشتراک.

**Permission:** `IS_AUTHENTICATED_FULLY`

**Request Body:**
```json
{
  "gateway": "mellat",
  "amount_rials": 290000,
  "period_uuid": "uuid-of-subscription-period",
  "frontend_address": "https://example.com/payment-result"
}
```

| فیلد | نوع | الزامی |
|------|-----|--------|
| gateway | string (mellat\|sep) | ✅ |
| amount_rials | integer | ✅ |
| period_uuid | string (UUID) | ✅ |
| frontend_address | string (URL) | ❌ |

**Response 200:**
```json
{
  "success": true,
  "data": {
    "payment_uuid": "...",
    "redirect_url": "https://gateway.shaparak.ir/...",
    "order_id": "ORD-XXXXXXXXXXXXXXXX"
  }
}
```

---

## GET /api/v1/subscription-payment/callback/{gateway}

callback درگاه پرداخت — پس از پرداخت موفق، `ClinicSubscription` به صورت خودکار ایجاد می‌شود (بر اساس `period_uuid` ذخیره‌شده در metadata پرداخت).

---

## Admin Endpoints

### GET /api/v1/admin/subscription/plans
**Permission:** `ROLE_ADMIN` — لیست **همه** پلن‌ها شامل غیرفعال‌ها (بر خلاف endpoint عمومی که فقط فعال‌ها را برمی‌گرداند). هر پلن فیلد `active` دارد و `periods` همیشه یک آرایه است (فقط دوره‌های فعال).

### POST /api/v1/admin/subscription/plan
**Permission:** `ROLE_ADMIN`

```json
{
  "name": "enterprise",
  "level": 3,
  "max_secretaries": 20,
  "features": { "patient_records": true, "services": true, "sms_panel": true }
}
```

**خطاها:**

| کد | HTTP | شرح |
|----|------|-----|
| ERR_VALIDATION_001 | 422 | `name` یا `level` ارسال نشده |
| ERR_VALIDATION_001 | 422 | پلنی با این نام از قبل وجود دارد (نام یکتاست) |

### PATCH /api/v1/admin/subscription/plan/{uuid}
**Permission:** `ROLE_ADMIN` — ویرایش پنل (همه فیلدها اختیاری)

**خطاها:**

| کد | HTTP | شرح |
|----|------|-----|
| ERR_SUBSCRIPTION_NOT_FOUND | 404 | پلن یافت نشد |
| ERR_VALIDATION_001 | 422 | نام جدید متعلق به پلن دیگری است |

### POST /api/v1/admin/subscription/period
**Permission:** `ROLE_ADMIN`

```json
{
  "plan_uuid": "...",
  "label": "شش ماهه",
  "duration_months": 6,
  "price_rials": 1500000,
  "is_trial": false,
  "sort_order": 2
}
```

### PATCH /api/v1/admin/subscription/period/{uuid}
**Permission:** `ROLE_ADMIN` — ویرایش دوره

### DELETE /api/v1/admin/subscription/period/{uuid}
**Permission:** `ROLE_ADMIN` — غیرفعال کردن دوره (soft delete: `active=false`)

### GET /api/v1/admin/subscription/report
**Permission:** `ROLE_ADMIN`

Query params: `page`, `limit`

```json
{
  "success": true,
  "data": [
    {
      "uuid": "...",
      "entity_type": "clinic",
      "entity_id": 5,
      "is_trial": false,
      "starts_at": 1718000000,
      "expires_at": 1720678400,
      "plan_name": "basic",
      "plan_level": 1
    }
  ],
  "meta": { "totalRecords": 50, "totalPages": 3, "currentPage": 1 }
}
```

---

## Error Codes

| Code | HTTP | توضیح |
|------|------|-------|
| ERR_SUBSCRIPTION_REQUIRED | 403 | قابلیت نیاز به پنل Basic+ دارد |
| ERR_TRIAL_ALREADY_USED | 422 | تریال قبلاً استفاده شده |
| ERR_TRIAL_DISABLED | 422 | تریال غیرفعال است |
| ERR_SUBSCRIPTION_NOT_FOUND | 404 | پنل یافت نشد |
