paths:

  # ─────────────────────────────────────────────────────────────────────────────
  # ADMIN — LOGIN & 2FA FLOW
  # ─────────────────────────────────────────────────────────────────────────────

  /admin/login:
    post:
      summary: Admin login
      description: |
        Authenticate an Admin user with email and password.

        **2FA Flow:**
        - If 2FA is **disabled** → Returns a full `token` immediately.
        - If 2FA is **enabled** → Returns `requiresOtp: true` and an `otpId`. 
          A 6-digit code is sent to the Admin's registered email. 
          The client must then call `POST /admin/verify-otp` with the `otpId` and code to receive the JWT.
      tags: [Security — Admin]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email, password]
              properties:
                email:
                  type: string
                  format: email
                  example: "superadmin@airpero.com"
                password:
                  type: string
                  example: "SuperAdmin@123"
      responses:
        '200':
          description: Login successful (2FA not required)
          content:
            application/json:
              examples:
                without_2fa:
                  summary: 2FA disabled — full token returned
                  value:
                    success: true
                    message: "Login successful"
                    token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                    admin:
                      id: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                      fullName: "System Admin"
                      email: "superadmin@airpero.com"
                      role: "superadmin"
                      twoFaEnabled: false
                with_2fa:
                  summary: 2FA enabled — OTP required
                  value:
                    success: true
                    requiresOtp: true
                    otpId: "b5c6d7e8-f9a0-1b2c-3d4e-5f6a7b8c9d0e"
                    message: "OTP sent to your registered email address. Please verify to complete login."
        '401':
          description: Invalid credentials or inactive account
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  message:
                    type: string
                    example: "Invalid credentials"
        '403':
          description: Account suspended
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  message:
                    type: string
                    example: "Account blocked: Please reach out to support"

  /admin/verify-otp:
    post:
      summary: Complete Admin login with OTP (2FA Step 2)
      description: |
        Submit the 6-digit OTP received by email to complete a 2FA login.
        
        **OTP Rules:**
        - Expires after the configured `OTP_EXPIRES_MINUTES` (default: 10 minutes).
        - Single-use only — cannot be reused after successful verification.
        - Locked after **5 failed attempts** — must request a new OTP.
        - Rate-limited to **3 requests per minute** per IP.
      tags: [Security — Admin]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [otpId, code]
              properties:
                otpId:
                  type: string
                  format: uuid
                  description: The `otpId` returned by the login endpoint when 2FA is required.
                  example: "b5c6d7e8-f9a0-1b2c-3d4e-5f6a7b8c9d0e"
                code:
                  type: string
                  description: The 6-digit OTP code sent to the admin's email.
                  example: "483920"
      responses:
        '200':
          description: OTP verified — full JWT token returned
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Login successful"
                  token:
                    type: string
                    example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                  admin:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      fullName:
                        type: string
                        example: "System Admin"
                      email:
                        type: string
                        example: "superadmin@airpero.com"
                      role:
                        type: string
                        example: "superadmin"
                      twoFaEnabled:
                        type: boolean
                        example: true
        '400':
          description: Invalid OTP, expired OTP, or max attempts exceeded
          content:
            application/json:
              examples:
                invalid_code:
                  summary: Wrong code entered
                  value:
                    success: false
                    message: "Invalid OTP. 4 attempts remaining."
                expired:
                  summary: OTP has expired
                  value:
                    success: false
                    message: "OTP has expired. Please request a new one."
                max_attempts:
                  summary: Too many failed attempts
                  value:
                    success: false
                    message: "Too many failed attempts. Please request a new OTP."

  /admin/2fa/toggle:
    post:
      summary: Enable or disable 2FA for Admin
      description: |
        Toggles 2FA on or off for the currently authenticated Admin.
        - If 2FA is currently **OFF** → it will be turned **ON**. Future logins will require an email OTP.
        - If 2FA is currently **ON** → it will be turned **OFF**. Future logins will return a token immediately.
        
        Requires a valid Bearer token.
      tags: [Security — Admin]
      security:
        - bearerAuth: []
      responses:
        '200':
          description: 2FA status toggled successfully
          content:
            application/json:
              examples:
                enabled:
                  summary: 2FA turned ON
                  value:
                    success: true
                    message: "Two-factor authentication has been enabled."
                    twoFaEnabled: true
                disabled:
                  summary: 2FA turned OFF
                  value:
                    success: true
                    message: "Two-factor authentication has been disabled."
                    twoFaEnabled: false
        '401':
          description: Unauthorized — missing or invalid token

  /admin/forgot-password:
    post:
      summary: Request Admin password reset
      description: |
        Triggers a password reset email to the admin's registered address.
        The email contains a secure link that expires in **30 minutes**.

        **Security:** This endpoint always returns `200 OK` regardless of whether the email exists, 
        to prevent email enumeration attacks.

        Rate-limited to **3 requests per minute** per IP.
      tags: [Security — Admin]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email]
              properties:
                email:
                  type: string
                  format: email
                  example: "superadmin@airpero.com"
      responses:
        '200':
          description: Reset link sent (if email is registered)
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "If your email is registered, you will receive a password reset link shortly."

  /admin/reset-password:
    post:
      summary: Complete Admin password reset
      description: |
        Submits the reset token (from the email link) along with a new password.
        The token is valid for **30 minutes** from when it was issued.
        After use, the token is invalidated and cannot be reused.
      tags: [Security — Admin]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [token, newPassword]
              properties:
                token:
                  type: string
                  description: The plain-text reset token extracted from the reset URL query parameter.
                  example: "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
                newPassword:
                  type: string
                  description: New password (min 8 characters recommended).
                  example: "NewStrongPassword@2026"
      responses:
        '200':
          description: Password has been reset successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Password has been reset successfully."
        '400':
          description: Token is invalid, already used, or has expired
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  message:
                    type: string
                    example: "Password reset token is invalid or has expired"

  # ─────────────────────────────────────────────────────────────────────────────
  # MERCHANT — LOGIN & 2FA FLOW
  # ─────────────────────────────────────────────────────────────────────────────

  /merchants/login:
    post:
      summary: Merchant login (Dashboard)
      description: |
        Authenticate a Merchant user with email and password to receive a dashboard JWT token.

        **2FA Flow:**
        - If 2FA is **disabled** → Returns a full `token` immediately.
        - If 2FA is **enabled** → Returns `requiresOtp: true` and an `otpId`.
          A 6-digit code is emailed to the merchant. Call `POST /merchants/verify-otp` next.

        Rate-limited to **5 attempts per minute** per IP.
      tags: [Security — Merchant]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email, password]
              properties:
                email:
                  type: string
                  format: email
                  example: "merchant@business.com"
                password:
                  type: string
                  example: "MerchantPassword@2026"
      responses:
        '200':
          description: Login successful or OTP required
          content:
            application/json:
              examples:
                without_2fa:
                  summary: 2FA disabled — token returned
                  value:
                    success: true
                    message: "Login successful"
                    token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                    merchant:
                      id: "m1a2b3c4-d5e6-f7a8-b9c0-d1e2f3a4b5c6"
                      businessName: "Tech Innovators Ltd"
                      preview: "Tech Innovators"
                      email: "merchant@business.com"
                      twoFaEnabled: false
                with_2fa:
                  summary: 2FA enabled — OTP required
                  value:
                    success: true
                    requiresOtp: true
                    otpId: "c5d6e7f8-a9b0-c1d2-e3f4-a5b6c7d8e9f0"
                    message: "OTP sent to your registered email address. Please verify to complete login."
        '401':
          description: Invalid credentials or inactive account
        '403':
          description: Account suspended

  /merchants/verify-otp:
    post:
      summary: Complete Merchant login with OTP (2FA Step 2)
      description: |
        Submit the 6-digit OTP received by email after a 2FA login challenge.

        **OTP Rules:**
        - Expires in `OTP_EXPIRES_MINUTES` (default: 10 minutes).
        - Single-use — invalidated immediately after successful verification.
        - Locked after **5 failed attempts**.
        - Rate-limited to **3 requests per minute** per IP.
      tags: [Security — Merchant]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [otpId, code]
              properties:
                otpId:
                  type: string
                  format: uuid
                  description: The `otpId` returned by the merchant login endpoint.
                  example: "c5d6e7f8-a9b0-c1d2-e3f4-a5b6c7d8e9f0"
                code:
                  type: string
                  description: The 6-digit code from the email.
                  example: "748231"
      responses:
        '200':
          description: OTP verified — full JWT token returned
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Login successful"
                  token:
                    type: string
                    example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                  merchant:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      businessName:
                        type: string
                        example: "Tech Innovators Ltd"
                      email:
                        type: string
                        example: "merchant@business.com"
                      twoFaEnabled:
                        type: boolean
                        example: true
        '400':
          description: Invalid, expired, or locked-out OTP
          content:
            application/json:
              examples:
                invalid_code:
                  summary: Wrong code
                  value:
                    success: false
                    message: "Invalid OTP. 3 attempts remaining."
                expired:
                  summary: Code has expired
                  value:
                    success: false
                    message: "OTP has expired. Please request a new one."

  /merchants/2fa/toggle:
    post:
      summary: Enable or disable 2FA for Merchant
      description: |
        Toggles 2FA on or off for the currently authenticated merchant account.
        - **ON** → Future logins require an email OTP before a token is issued.
        - **OFF** → Future logins return the token immediately after password check.

        Requires a valid Dashboard Bearer token (JWT).
      tags: [Security — Merchant]
      security:
        - bearerAuth: []
      responses:
        '200':
          description: 2FA status toggled
          content:
            application/json:
              examples:
                enabled:
                  summary: 2FA turned ON
                  value:
                    success: true
                    message: "Two-factor authentication has been enabled."
                    twoFaEnabled: true
                disabled:
                  summary: 2FA turned OFF
                  value:
                    success: true
                    message: "Two-factor authentication has been disabled."
                    twoFaEnabled: false
        '401':
          description: Unauthorized

  /merchants/forgot-password:
    post:
      summary: Request Merchant password reset
      description: |
        Sends a secure password reset link to the merchant's registered email address.
        The link expires after **30 minutes**.

        Always returns `200` — does NOT confirm whether the email exists (anti-enumeration).
      tags: [Security — Merchant]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email]
              properties:
                email:
                  type: string
                  format: email
                  example: "merchant@business.com"
      responses:
        '200':
          description: Reset email sent (if email is registered)
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "If your email is registered, you will receive a password reset link shortly."

  /merchants/reset-password:
    post:
      summary: Complete Merchant password reset
      description: |
        Accepts the reset token (from the link in the email) and the new password.
        The token is single-use and expires after **30 minutes**.
      tags: [Security — Merchant]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [token, newPassword]
              properties:
                token:
                  type: string
                  description: The raw token extracted from the password reset URL query parameter.
                  example: "d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2"
                newPassword:
                  type: string
                  example: "NewSecurePassword@2026"
      responses:
        '200':
          description: Password reset successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Password has been reset successfully. You can now log in with your new password."
        '400':
          description: Token is invalid, already used, or has expired
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  message:
                    type: string
                    example: "Password reset token is invalid or has expired"

  # ─────────────────────────────────────────────────────────────────────────────
  # MERCHANT — PAYOUT OTP (TRANSACTION AUTHORIZATION)
  # ─────────────────────────────────────────────────────────────────────────────

  /merchants/payout/request-otp:
    post:
      summary: Request a payout authorization OTP
      description: |
        **Step 1 of a protected payout.** Generates and emails a 6-digit OTP to the merchant's registered email address.

        The returned `otpId` must be submitted alongside your payout request payload so the system can verify 
        the transaction was explicitly authorized by the merchant.

        **Workflow:**
        1. Call `POST /merchants/payout/request-otp` → Receive `otpId` + email with 6-digit code.
        2. Call `POST /merchants/payout` with `{ otpId, otpCode, ...payoutFields }`.
        3. The payout is executed only if the OTP is valid and unexpired.

        **OTP Rules:**
        - Expires in `OTP_EXPIRES_MINUTES` (default: 10 minutes).
        - Single-use — cannot be reused.
        - Locked after **5 failed verification attempts**.
      tags: [Security — Merchant]
      security:
        - bearerAuth: []
      responses:
        '200':
          description: OTP emailed to the merchant's registered address
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  otpId:
                    type: string
                    format: uuid
                    description: Use this ID when submitting your payout request.
                    example: "e1f2a3b4-c5d6-e7f8-a9b0-c1d2e3f4a5b6"
                  message:
                    type: string
                    example: "OTP sent to your registered email. Submit the OTP along with payout details to proceed."
        '401':
          description: Unauthorized — missing or invalid token
        '500':
          description: Internal server error while issuing OTP
