<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Kalnoy\Nestedset\NodeTrait;

/**
 * @property int id
 * @property string|null productNo
 * @property string|null name
 * @property ProductTypeEnum|null type
 * @property DbStatusFieldEnum status
 * @property bool canSee
 * @property timestamp|null created_at
 * @property timestamp|null updated_at
 * @property timestamp|null deleted_at
 */
class ProductGroup extends Model
{
    use HasFactory,NodeTrait,SoftDeletes;

    protected $fillable = [
        'productNo',
        'name',
        'type',
        'status',
        'canSee',
    ];

    protected ?array $needsId = null;

    private function getNodeToArray($node, $needChild, $maxDepth = 999)
    {
        if ($this->needsId) {
            if (! in_array($node->id, $this->needsId)) {
                return false;
            }
        }
        $productGroupArray = $node->toArray();
        $productGroupArray['isLeaf'] = $node->isLeaf();
        if (! $productGroupArray['isLeaf'] && $node->depth < $maxDepth) {
            $productGroupArray['children'] = $this->getChildNodesArray($node, $maxDepth);
            if (count($productGroupArray['children']) < 1) {
                $productGroupArray['isLeaf'] = true;
            }
        }

        return $productGroupArray;
    }

    private function getChildNodesArray($node, $maxDepth = 999)
    {
        $childrenArray = [];
        $children = ProductGroup::find($node->id)->descendants()->withDepth()->having('depth', '=', $node->depth + 1)->get();
        foreach ($children as $child) {
            if ($node->depth <= $maxDepth) {
                if ($children = $this->getNodeToArray($child, true, $maxDepth)) {
                    $childrenArray[] = $children;
                }

            }
        }

        return $childrenArray;
    }

    public function allToTreeArray($NodeId = 1, $maxDepth = 999)
    {
        $productGroup = $this->withDepth()->where('id', $NodeId)->get()->first();

        return $this->getNodeToArray($productGroup, true, $maxDepth);
    }

    public function nodesWithParentToTree(array $nodesId)
    {
        $this->needsId = [];
        foreach ($nodesId as $nodeId) {
            $this->needsId = array_unique(array_merge($this->needsId, $this->ancestorsAndSelf($nodeId)->pluck('id')->toArray()));
        }

        return $this->allToTreeArray();
    }

    /**
     * add parents Array, parentsId Array, ParentsName Array, hasChild parameter
     */
    public function allWithParents($maxDepth = 999): array
    {
        // $productGroupArray=$this->with('ancestors')->get()->toArray();
        $productGroupArray = [];
        $productGroups = $this->withDepth()->get();
        foreach ($productGroups as $item) {
            if ($item->depth > $maxDepth) {
                continue;
            }
            $children = ProductGroup::descendantsOf($item);
            (count($children) > 0) ? $item->hasChild = true : $item->hasChild = false;
            $parents = ProductGroup::ancestorsOf($item);
            $item->parents = $parents->toArray();
            $item->parentsNames = ProductGroup::ancestorsOf($item)->pluck('name')->toArray();
            $item->parentsPath = implode('/', ProductGroup::ancestorsOf($item)->pluck('name')->toArray());
            $item->parentsIds = ProductGroup::ancestorsOf($item)->pluck('id')->toArray();
            $item->parentsIdPointer = implode('_', ProductGroup::ancestorsOf($item)->pluck('name')->toArray());
            $productGroupArray[] = $item->toArray();
        }

        return $productGroupArray;
    }

    /**
     * add parents Array, parentsId Array, ParentsName Array, hasChild parameter
     */
    public function allWithPath($maxDepth = 999): array
    {
        $pathSeparator = '/';
        $pointerSeparator = '_';

        $productGroupArray = [];
        $productGroups = $this->withDepth()->get();
        foreach ($productGroups as $item) {
            if ($item->depth > $maxDepth) {
                continue;
            }
            $children = ProductGroup::descendantsOf($item);
            (count($children) > 0) ? $item->hasChild = true : $item->hasChild = false;
            $parents = ProductGroup::ancestorsOf($item);
            $item->parentsNames = ProductGroup::ancestorsOf($item)->pluck('name')->toArray();
            $item->parentsIds = ProductGroup::ancestorsOf($item)->pluck('id')->toArray();
            $item->parentsPath = implode('/', ProductGroup::ancestorsOf($item)->pluck('name')->toArray());
            $item->parentsIdPointer = implode('_', ProductGroup::ancestorsOf($item)->pluck('name')->toArray());
            if (count($item->parentsIds) > 0) {
                $item->fullPath = $item->parentsPath.$pathSeparator.$item->name;
                $item->fullPointer = $item->parentsIdPointer.$pointerSeparator.$item->name;
            } else {
                $item->fullPath = $item->name;
                $item->fullPointer = $item->name;
            }
            $productGroupArray[] = $item->toArray();
        }

        return $productGroupArray;
    }
}
