<?php

namespace App\Models;

use App\Entities\BaseEntity;

//계층형구조구현용 모델(게시판,카테고리 등등)
abstract class BaseHierarchyModel extends BaseModel
{
    protected function __construct(string $className)
    {
        parent::__construct($className);
        $this->allowedFields = [...$this->allowedFields, "grpno", "grporder", "grpdepth", "parent"];
        $this->validationRules = [...$this->validationRules,];
    }
    abstract public function getContentField();
    abstract public function reply($parent_entity, array $formDatas): BaseEntity;

    public function getEntitys(array $conditions = array(), array $orderBys = array()): array
    {
        $orderBys = ["grpno DESC", "grporder ASC", ...$orderBys];
        return parent::getEntitys($conditions, $orderBys);
    }
    public function getSiblingEntitys($entity)
    {
        return parent::getEntitys(['grpno' => $entity->getHierarchy_No()]);
    }
    public function getFieldRule(string $field, array $rules, string $action = ""): array
    {
        switch ($field) {
            case "grpno":
            case "grporder":
            case "grpdepth":
                $rules[$field] = "if_exist|numeric"; //반드시숫자여야함
                break;
            case "parent":
                $rules[$field] = "if_exist";
                break;
            default:
                $rules = parent::getFieldRule($field, $rules, $action);
                break;
        }
        return $rules;
    }

    private function getMax($field, $coditions = null)
    {
        //생성시는 해당Field의 max값을 구해서 넣는다.
        $query = is_null($coditions) ? $this->selectMax($field) : $this->selectMax($field)->where($coditions);
        $max = $query->get()->getResult()[0]->$field + 1;
        if (!$max) {
            throw new \Exception("{$field}는 {$max}의 값을 가질수 없습니다.");
        }
        return $max;
    }
    final protected function create_process($entity, array $formDatas)
    {
        //생성시는 grpno의 max값을 구해서 넣는다.
        $formDatas['grpno'] = $this->getMax('grpno');
        return parent::create_process($entity, $formDatas);
    }

    final protected function reply_process($parent_entity, $entity, array $formDatas)
    {
        //reply용 설정
        $entity->parent = $parent_entity->getPrimaryKey();
        $entity->grpno = $parent_entity->grpno;
        //Reply시는 grpno가 부모와 같고 grporder의 max값을 구해서 넣는다.
        $entity->grporder = $this->getMax('grporder', ['grpno' => $parent_entity->grpno]);
        $entity->grpdepth = $parent_entity->grpdepth + 1;
        return parent::create_process($entity, $formDatas);
    }
}
