# MoveProductCategory

## Permission Scope

productCatalog

## Overview

moveProductCategory reparents a category node within the hierarchical tree. The category and all its descendants move to the new location. Moving to null parent promotes the category to a root node. Circular references are prevented — a category cannot be moved under one of its own descendants.

## Business Rules

- Target category must exist
- If new parent ID is provided, the new parent must exist
- A category cannot be moved under itself or any of its descendants (circular reference prevention)
- Moving must not cause any descendant to exceed the configurable maximum tree depth
- Moving a category preserves all product assignments and child categories
- Moving a category updates the paths of all descendant categories to reflect the new hierarchy
- Moving to null parent makes the category a root node

## Process Flow

```mermaid
flowchart TD
    A[Receive move request] --> B{Category exists?}
    B -->|No| C[Return error: CATEGORY_NOT_FOUND]
    B -->|Yes| D{New parent provided?}
    D -->|Yes| E{New parent exists?}
    E -->|No| F[Return error: PARENT_NOT_FOUND]
    E -->|Yes| G{Circular reference?}
    G -->|Yes| H[Return error: CIRCULAR_REFERENCE]
    G -->|No| I{Depth within limit?}
    I -->|No| J[Return error: MAX_DEPTH_EXCEEDED]
    I -->|Yes| K[Update parent reference]
    D -->|No| K
    K --> K2[Update descendant paths]
    K2 --> L[Return moved category]
```

## External Dependencies

- None

## Error Scenarios

- **CATEGORY_NOT_FOUND**: Specified category ID does not exist
- **PARENT_NOT_FOUND**: Specified parent category ID does not exist
- **CIRCULAR_REFERENCE**: Moving the category would create a circular reference (new parent is a descendant)
- **MAX_DEPTH_EXCEEDED**: Operation would cause the category subtree to exceed the maximum depth limit

## Test Cases

- should return CategoryNotFoundError when category does not exist
- should return ParentNotFoundError when new parent does not exist
- should return CircularReferenceError when move would create a cycle
- should return MaxDepthExceededError when move would exceed max depth
- should move category to new parent successfully
- should promote category to root when newParentId is null
