<?php
declare (strict_types = 1);

namespace app\admin\validate\v1;

use app\admin\model\v1\SysNavigationItemModel;
use think\facade\Db;
use think\Validate;

class NavigationItemValidate extends Validate
{
    /**
     * 定义验证规则
     * 格式：'字段名' =>  ['规则1','规则2'...]
     *
     * @var array
     */
    protected $rule = [
        'id'        => 'require|integer',
        'nav_id'    => 'require|integer',
        'pid'       => 'integer|different:id|checkPidNotBeChildren',
        'name'      => 'require|max:64',
        'desc'      => 'max:255',
        'icon'      => 'max:64',
        'image'     => 'max:255',
        'link_to'   => 'require|max:64|in:article,article_category,product,product_category,system_page,custom',
        'link'      => 'max:255',
        'sort'      => 'integer',
        'blank'     => 'in:0,1',
        'status'    => 'require|in:1,-1',
    ];

    /**
     * 定义错误信息
     * 格式：'字段名.规则名' =>  '错误信息'
     *
     * @var array
     */
    protected $message = [
        'id.require'                => 'ID不能为空',
        'id.integer'                => 'ID必须为整数',
        'nav_id.require'            => '导航ID不能为空',
        'nav_id.integer'            => '导航ID必须为整数',
        'pid.integer'               => '父级ID必须为整数',
        'pid.different'             => '父级ID不能为自身',
        'pid.checkPidNotBeChildren' => '父级ID不能为自身的子导航',
        'name.require'              => '导航名称不能为空',
        'name.max'                  => '导航名称最多不能超过64个字符',
        'desc.max'                  => '导航名称最多不能超过:rule个字符',
        'icon.max'                  => '图标最多不能超过64个字符',
        'image.max'                 => '图标最多不能超过:rule个字符',
        'link_to.require'           => '链接类型不能为空',
        'link_to.max'               => '链接类型最多不能超过64个字符',
        'link_to.in'                => '链接类型必须是article,article_category,product_category,product,system_page,custom中之一',
        'link.max'                  => '链接最多不能超过255个字符',
        'sort.integer'              => '排序必须为整数',
        'blank.in'                  => '是否新窗口打开只能是0或1',
        'status.require'            => '状态不能为空',
        'status.in'                 => '状态只能是1或-1',
    ];

    // 验证pid
    protected function checkPidNotBeChildren($value, $rule, $data = [])
    {
        if ($value == 0) {
            return true;
        }

        $children   = [];
        $table_name = (new SysNavigationItemModel)->getTable();
        if (env('DB_VERSION', '5') == '8') {
            $children = Db::query(
                preg_replace(
                    '/\s+/u',
                    ' ',
                    "WITH RECURSIVE tree_by AS (
                        SELECT a.id, a.pid FROM $table_name a WHERE a.id = {$data['id']}
                        UNION ALL
                        SELECT k.id, k.pid FROM $table_name k INNER JOIN tree_by t ON t.id = k.pid
                    )
                    SELECT id FROM tree_by WHERE id <> {$data['id']};"
                )
            );
        } else {
            $children = \think\facade\Db::query("
                SELECT t2.id
                    FROM (
                        SELECT
                            @r AS _id, (SELECT @r := GROUP_CONCAT(id) FROM $table_name WHERE FIND_IN_SET(pid, _id)) AS parent_id
                        FROM
                            (SELECT @r := {$data['id']}) vars, $table_name h
                        WHERE @r <> 0) t1
                    JOIN $table_name t2
                    ON FIND_IN_SET(t2.pid, t1._id)
                ORDER BY t2.id;
            ");
        }
        if (!empty($children) && in_array($data['pid'], array_column($children, 'id'))) {
            return false;
        }

        return true;
    }

    // 新增场景
    public function sceneAdd()
    {
        return $this->only(['nav_id', 'pid', 'name', 'icon', 'link_to', 'link', 'sort', 'blank', 'status'])->remove('pid', 'different|checkPidNotBeChildren');
    }

    // 更新场景
    public function sceneEdit()
    {
        return $this->only(['id', 'nav_id', 'pid', 'name', 'icon', 'link_to', 'link', 'sort', 'blank', 'status']);
    }
}
