openapi: 3.0.3
info:
  title: Youthes E-Commerce API
  version: 1.0.0
  description: |
    Portfolio-ready OpenAPI specification for the Youthes e-commerce backend.
    The API covers customer shopping flows and admin operations for catalog,
    orders, testimonials, and editable static content.
servers:
  - url: https://youthes-api.duckdns.org/api/v1
    description: Production
  - url: http://localhost:3000/api/v1
    description: Local development
tags:
  - name: Auth
  - name: Products
  - name: Categories
  - name: Cart
  - name: Orders
  - name: Users
  - name: Testimonials
  - name: Pages
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  schemas:
    MessageResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        message:
          type: string
          example: Operation completed successfully
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        message:
          type: string
          example: Invalid credentials
    PaginationMeta:
      type: object
      properties:
        page:
          type: integer
          example: 1
        limit:
          type: integer
          example: 10
        total:
          type: integer
          example: 42
        pages:
          type: integer
          example: 5
    User:
      type: object
      properties:
        _id:
          type: string
          example: 6804f6df8e2f1e4cbf30f001
        fullName:
          type: string
          example: Ahmed Mohamed
        email:
          type: string
          format: email
          example: ahmed@example.com
        phone:
          type: string
          example: "01012345678"
        gender:
          type: string
          enum: [male, female]
          example: male
        address:
          type: string
          example: Cairo, Egypt
        role:
          type: string
          enum: [user, admin]
          example: user
        isActive:
          type: boolean
          example: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    AuthResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        message:
          type: string
          example: Logged in successfully
        data:
          type: object
          properties:
            user:
              $ref: '#/components/schemas/User'
            token:
              type: string
              example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.example
    RegisterRequest:
      type: object
      required: [fullName, email, phone, password, gender]
      properties:
        fullName:
          type: string
          minLength: 2
          maxLength: 50
        email:
          type: string
          format: email
        phone:
          type: string
        password:
          type: string
          minLength: 8
        gender:
          type: string
          enum: [male, female]
        address:
          type: string
    LoginRequest:
      type: object
      required: [email, password]
      properties:
        email:
          type: string
          format: email
        password:
          type: string
    Category:
      type: object
      properties:
        _id:
          type: string
        name:
          type: string
        slug:
          type: string
        isActive:
          type: boolean
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    Subcategory:
      type: object
      properties:
        _id:
          type: string
        name:
          type: string
        slug:
          type: string
        category:
          type: string
        isActive:
          type: boolean
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    CategoryWithSubs:
      allOf:
        - $ref: '#/components/schemas/Category'
        - type: object
          properties:
            subcategories:
              type: array
              items:
                $ref: '#/components/schemas/Subcategory'
    Product:
      type: object
      properties:
        _id:
          type: string
        name:
          type: string
        slug:
          type: string
        description:
          type: string
        price:
          type: number
          example: 799
        image:
          type: string
          format: uri
        category:
          oneOf:
            - type: string
            - $ref: '#/components/schemas/Category'
        subcategory:
          nullable: true
          oneOf:
            - type: string
            - $ref: '#/components/schemas/Subcategory'
        stockCount:
          type: integer
          example: 15
        isDeleted:
          type: boolean
          example: false
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    ProductListResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        products:
          type: array
          items:
            $ref: '#/components/schemas/Product'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    ProductResponse:
      type: object
      properties:
        success:
          type: boolean
        message:
          type: string
        data:
          $ref: '#/components/schemas/Product'
    ProductCreateForm:
      type: object
      required: [name, description, price, stockCount, category, image]
      properties:
        name:
          type: string
        description:
          type: string
        price:
          type: number
        stockCount:
          type: integer
        category:
          type: string
        subcategory:
          type: string
        image:
          type: string
          format: binary
    ProductUpdateForm:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
        price:
          type: number
        stockCount:
          type: integer
        category:
          type: string
        subcategory:
          type: string
        image:
          type: string
          format: binary
    CartProduct:
      type: object
      properties:
        _id:
          type: string
        name:
          type: string
        image:
          type: string
          format: uri
        price:
          type: number
        stockCount:
          type: integer
    CartItem:
      type: object
      properties:
        product:
          $ref: '#/components/schemas/CartProduct'
        quantity:
          type: integer
          example: 2
        priceAtAdd:
          type: number
          example: 799
        priceChanged:
          type: boolean
          example: false
        currentPrice:
          type: number
          example: 799
        subtotal:
          type: number
          example: 1598
    CartSummary:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/CartItem'
        itemCount:
          type: integer
          example: 2
        subtotal:
          type: number
          example: 1598
        shippingFee:
          type: number
          example: 50
        total:
          type: number
          example: 1648
        hasPriceChanges:
          type: boolean
          example: false
    CartResponse:
      type: object
      properties:
        success:
          type: boolean
        message:
          type: string
        data:
          $ref: '#/components/schemas/CartSummary'
    CartItemRequest:
      type: object
      required: [productId, quantity]
      properties:
        productId:
          type: string
        quantity:
          type: integer
          minimum: 1
    CartQuantityRequest:
      type: object
      required: [quantity]
      properties:
        quantity:
          type: integer
          minimum: 1
    CartMergeRequest:
      type: object
      required: [items]
      properties:
        items:
          type: array
          items:
            type: object
            required: [productId, quantity]
            properties:
              productId:
                type: string
              quantity:
                type: integer
                minimum: 1
    OrderItem:
      type: object
      properties:
        productId:
          type: string
        productName:
          type: string
        productImage:
          type: string
          format: uri
        unitPrice:
          type: number
        quantity:
          type: integer
        subtotal:
          type: number
    Order:
      type: object
      properties:
        _id:
          type: string
        orderNumber:
          type: string
          example: YTH-20260420-0001
        user:
          oneOf:
            - type: string
            - $ref: '#/components/schemas/User'
        items:
          type: array
          items:
            $ref: '#/components/schemas/OrderItem'
        deliveryPhone:
          type: string
        deliveryAddress:
          type: string
        shippingFee:
          type: number
        totalAmount:
          type: number
        paymentMethod:
          type: string
          enum: [COD]
        status:
          type: string
          enum: [Pending, Prepared, Shipped, Delivered, CancelledByUser, CancelledByAdmin, Rejected]
        cancelledBy:
          type: string
          nullable: true
          enum: [user, admin]
        cancellationReason:
          type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    OrderResponse:
      type: object
      properties:
        success:
          type: boolean
        message:
          type: string
        data:
          $ref: '#/components/schemas/Order'
    OrderListResponse:
      type: object
      properties:
        success:
          type: boolean
        message:
          type: string
        data:
          type: array
          items:
            $ref: '#/components/schemas/Order'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    OrderCreateRequest:
      type: object
      required: [deliveryPhone, deliveryAddress]
      properties:
        deliveryPhone:
          type: string
        deliveryAddress:
          type: string
    OrderStatusUpdateRequest:
      type: object
      required: [status]
      properties:
        status:
          type: string
          enum: [Prepared, Shipped, Delivered, CancelledByAdmin, Rejected]
        note:
          type: string
    CancelOrderRequest:
      type: object
      properties:
        reason:
          type: string
    SalesReport:
      type: object
      properties:
        period:
          type: object
          properties:
            from:
              type: string
              format: date-time
            to:
              type: string
              format: date-time
        summary:
          type: object
          properties:
            totalRevenue:
              type: number
            totalOrders:
              type: integer
            averageOrderValue:
              type: number
        topProducts:
          type: array
          items:
            type: object
            properties:
              _id:
                type: string
              productName:
                type: string
              totalSold:
                type: integer
              totalRevenue:
                type: number
    Testimonial:
      type: object
      properties:
        _id:
          type: string
        user:
          oneOf:
            - type: string
            - $ref: '#/components/schemas/User'
        userName:
          type: string
        reviewText:
          type: string
        rating:
          type: integer
          minimum: 1
          maximum: 5
        status:
          type: string
          enum: [pending, approved, rejected, ignored]
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    TestimonialRequest:
      type: object
      required: [reviewText, rating]
      properties:
        reviewText:
          type: string
          minLength: 10
          maxLength: 500
        rating:
          type: integer
          minimum: 1
          maximum: 5
    TestimonialStatusRequest:
      type: object
      required: [status]
      properties:
        status:
          type: string
          enum: [pending, approved, rejected, ignored]
    TestimonialListResponse:
      type: object
      properties:
        success:
          type: boolean
        message:
          type: string
        data:
          type: array
          items:
            $ref: '#/components/schemas/Testimonial'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    AboutUsRequest:
      type: object
      required: [title, body]
      properties:
        title:
          type: string
        body:
          type: string
    FAQRequest:
      type: object
      required: [items]
      properties:
        items:
          type: array
          items:
            type: object
            properties:
              question:
                type: string
              answer:
                type: string
    ContactUsRequest:
      type: object
      properties:
        phone:
          type: string
        email:
          type: string
          format: email
        address:
          type: string
        workingHours:
          type: string
        socialLinks:
          type: array
          items:
            type: object
            properties:
              label:
                type: string
              url:
                type: string
                format: uri
    StaticPage:
      type: object
      properties:
        _id:
          type: string
        pageKey:
          type: string
          enum: [about_us, faq, contact_us]
        content:
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    StaticPageResponse:
      type: object
      properties:
        success:
          type: boolean
        message:
          type: string
        data:
          $ref: '#/components/schemas/StaticPage'
    UserListResponse:
      type: object
      properties:
        success:
          type: boolean
        message:
          type: string
        data:
          type: array
          items:
            $ref: '#/components/schemas/User'
        meta:
          allOf:
            - $ref: '#/components/schemas/PaginationMeta'
            - type: object
              properties:
                hasNextPage:
                  type: boolean
                hasPrevPage:
                  type: boolean
paths:
  /auth/register:
    post:
      tags: [Auth]
      summary: Register a new user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterRequest'
      responses:
        '201':
          description: Account created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
        '400':
          description: Validation or duplicate data error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /auth/login:
    post:
      tags: [Auth]
      summary: Login with email and password
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LoginRequest'
      responses:
        '200':
          description: Login successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
        '401':
          description: Invalid credentials
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /auth/logout:
    post:
      tags: [Auth]
      summary: Logout current user
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Logout acknowledged
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
  /products:
    get:
      tags: [Products]
      summary: List public products
      parameters:
        - in: query
          name: page
          schema:
            type: integer
            default: 1
        - in: query
          name: limit
          schema:
            type: integer
            default: 10
        - in: query
          name: category
          schema:
            type: string
        - in: query
          name: subcategory
          schema:
            type: string
        - in: query
          name: search
          schema:
            type: string
        - in: query
          name: sort
          schema:
            type: string
            enum: [newest, oldest, name_asc, name_desc, price_asc, price_desc]
      responses:
        '200':
          description: Product list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductListResponse'
    post:
      tags: [Products]
      summary: Create a product
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/ProductCreateForm'
      responses:
        '201':
          description: Product created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductResponse'
  /products/{slug}:
    get:
      tags: [Products]
      summary: Get product by slug
      parameters:
        - in: path
          name: slug
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Product details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductResponse'
        '404':
          description: Product not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /products/admin/all:
    get:
      tags: [Products]
      summary: List products for admin
      security:
        - bearerAuth: []
      parameters:
        - in: query
          name: page
          schema:
            type: integer
            default: 1
        - in: query
          name: limit
          schema:
            type: integer
            default: 10
        - in: query
          name: category
          schema:
            type: string
        - in: query
          name: search
          schema:
            type: string
      responses:
        '200':
          description: Admin product list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductListResponse'
  /products/{id}:
    put:
      tags: [Products]
      summary: Update a product
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/ProductUpdateForm'
      responses:
        '200':
          description: Product updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductResponse'
    delete:
      tags: [Products]
      summary: Soft delete a product
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Product deleted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
  /categories:
    get:
      tags: [Categories]
      summary: Get active categories and subcategories
      responses:
        '200':
          description: Categories fetched
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/CategoryWithSubs'
    post:
      tags: [Categories]
      summary: Create category
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name]
              properties:
                name:
                  type: string
                isActive:
                  type: boolean
      responses:
        '201':
          description: Category created
  /categories/admin:
    get:
      tags: [Categories]
      summary: Get all categories for admin
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Categories fetched
  /categories/{id}:
    put:
      tags: [Categories]
      summary: Update category
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
      responses:
        '200':
          description: Category updated
    delete:
      tags: [Categories]
      summary: Delete category if unused
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Category deleted
  /categories/{id}/subcategories:
    post:
      tags: [Categories]
      summary: Create subcategory
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name]
              properties:
                name:
                  type: string
                isActive:
                  type: boolean
      responses:
        '201':
          description: Subcategory created
  /categories/{id}/subcategories/{subId}:
    put:
      tags: [Categories]
      summary: Update subcategory
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
        - in: path
          name: subId
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
      responses:
        '200':
          description: Subcategory updated
    delete:
      tags: [Categories]
      summary: Delete subcategory if unused
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
        - in: path
          name: subId
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Subcategory deleted
  /cart:
    get:
      tags: [Cart]
      summary: Get current user's cart
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Cart fetched
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CartResponse'
    delete:
      tags: [Cart]
      summary: Clear current user's cart
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Cart cleared
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
  /cart/items:
    post:
      tags: [Cart]
      summary: Add item to cart
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CartItemRequest'
      responses:
        '201':
          description: Item added
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CartResponse'
  /cart/items/{productId}:
    put:
      tags: [Cart]
      summary: Update cart item quantity
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: productId
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CartQuantityRequest'
      responses:
        '200':
          description: Cart updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CartResponse'
    delete:
      tags: [Cart]
      summary: Remove item from cart
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: productId
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Item removed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CartResponse'
  /cart/merge:
    post:
      tags: [Cart]
      summary: Merge guest cart into current user's cart
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CartMergeRequest'
      responses:
        '200':
          description: Cart merged
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CartResponse'
  /cart/confirm-price/{productId}:
    patch:
      tags: [Cart]
      summary: Confirm updated pricing for one product or all items
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: productId
          required: true
          schema:
            type: string
          description: Product id or literal value `all`
      responses:
        '200':
          description: Price confirmed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CartResponse'
  /orders:
    post:
      tags: [Orders]
      summary: Create a new order from current cart
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OrderCreateRequest'
      responses:
        '201':
          description: Order placed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderResponse'
  /orders/my:
    get:
      tags: [Orders]
      summary: Get current user's orders
      security:
        - bearerAuth: []
      parameters:
        - in: query
          name: page
          schema:
            type: integer
            default: 1
        - in: query
          name: limit
          schema:
            type: integer
            default: 10
      responses:
        '200':
          description: Orders fetched
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderListResponse'
  /orders/my/{id}:
    get:
      tags: [Orders]
      summary: Get a single current-user order
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Order fetched
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderResponse'
  /orders/my/{id}/cancel:
    patch:
      tags: [Orders]
      summary: Cancel a pending order
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CancelOrderRequest'
      responses:
        '200':
          description: Order cancelled
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderResponse'
  /orders/admin:
    get:
      tags: [Orders]
      summary: Get all orders for admin
      security:
        - bearerAuth: []
      parameters:
        - in: query
          name: page
          schema:
            type: integer
        - in: query
          name: limit
          schema:
            type: integer
        - in: query
          name: status
          schema:
            type: string
        - in: query
          name: userId
          schema:
            type: string
        - in: query
          name: search
          schema:
            type: string
          description: Matches order number
        - in: query
          name: dateFrom
          schema:
            type: string
            format: date
        - in: query
          name: dateTo
          schema:
            type: string
            format: date
      responses:
        '200':
          description: Orders fetched
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderListResponse'
  /orders/admin/{id}:
    get:
      tags: [Orders]
      summary: Get a single order for admin
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Order fetched
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderResponse'
  /orders/admin/{id}/status:
    patch:
      tags: [Orders]
      summary: Update order status as admin
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OrderStatusUpdateRequest'
      responses:
        '200':
          description: Order status updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderResponse'
  /orders/admin/reports/sales:
    get:
      tags: [Orders]
      summary: Get delivered-order sales report
      security:
        - bearerAuth: []
      parameters:
        - in: query
          name: dateFrom
          schema:
            type: string
            format: date
        - in: query
          name: dateTo
          schema:
            type: string
            format: date
      responses:
        '200':
          description: Sales report generated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/SalesReport'
  /orders/admin/notifications:
    get:
      tags: [Orders]
      summary: Get admin notification counters
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Notification counts fetched
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      newOrders:
                        type: integer
                      outOfStock:
                        type: integer
  /users/me:
    get:
      tags: [Users]
      summary: Get current user profile
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Profile fetched
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/User'
    put:
      tags: [Users]
      summary: Update current user profile
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                fullName:
                  type: string
                email:
                  type: string
                  format: email
                phone:
                  type: string
                address:
                  type: string
      responses:
        '200':
          description: Profile updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/User'
  /users/me/change-password:
    post:
      tags: [Users]
      summary: Change current user password
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [currentPassword, newPassword]
              properties:
                currentPassword:
                  type: string
                newPassword:
                  type: string
                  minLength: 8
      responses:
        '200':
          description: Password changed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
  /users:
    get:
      tags: [Users]
      summary: List customer users as admin
      security:
        - bearerAuth: []
      parameters:
        - in: query
          name: page
          schema:
            type: integer
            default: 1
        - in: query
          name: limit
          schema:
            type: integer
            default: 20
        - in: query
          name: isActive
          schema:
            type: boolean
        - in: query
          name: search
          schema:
            type: string
      responses:
        '200':
          description: Users fetched
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserListResponse'
  /users/{id}/toggle:
    patch:
      tags: [Users]
      summary: Toggle customer active status
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        '200':
          description: User toggled
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/User'
  /testimonials/approved:
    get:
      tags: [Testimonials]
      summary: Get approved testimonials
      responses:
        '200':
          description: Testimonials fetched
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TestimonialListResponse'
  /testimonials:
    post:
      tags: [Testimonials]
      summary: Submit a testimonial
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TestimonialRequest'
      responses:
        '201':
          description: Testimonial submitted
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/Testimonial'
  /testimonials/admin:
    get:
      tags: [Testimonials]
      summary: Get testimonials for moderation
      security:
        - bearerAuth: []
      parameters:
        - in: query
          name: status
          schema:
            type: string
            enum: [pending, approved, rejected, ignored]
        - in: query
          name: page
          schema:
            type: integer
        - in: query
          name: limit
          schema:
            type: integer
      responses:
        '200':
          description: Testimonials fetched
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TestimonialListResponse'
  /testimonials/admin/{id}:
    patch:
      tags: [Testimonials]
      summary: Update testimonial status
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TestimonialStatusRequest'
      responses:
        '200':
          description: Testimonial status updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/Testimonial'
  /pages/{key}:
    get:
      tags: [Pages]
      summary: Get static page content
      parameters:
        - in: path
          name: key
          required: true
          schema:
            type: string
            enum: [about_us, faq, contact_us]
      responses:
        '200':
          description: Page content fetched
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StaticPageResponse'
  /pages/admin/about_us:
    put:
      tags: [Pages]
      summary: Update About Us page
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AboutUsRequest'
      responses:
        '200':
          description: About Us updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StaticPageResponse'
  /pages/admin/faq:
    put:
      tags: [Pages]
      summary: Update FAQ page
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FAQRequest'
      responses:
        '200':
          description: FAQ updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StaticPageResponse'
  /pages/admin/contact_us:
    put:
      tags: [Pages]
      summary: Update Contact Us page
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContactUsRequest'
      responses:
        '200':
          description: Contact Us updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StaticPageResponse'
