<?php

namespace addons\webman\traits;

use addons\webman\Admin;
use support\Db;

/**
 * @method $this offDataAuth() 关闭数据权限
 */
trait DataPermissions
{
    //全部数据权限
    private $FULL_DATA_RIGHTS = 0;
    //自定义数据权限
    private $CUSTOM_DATA_PERMISSIONS = 1;
    //本部门及以下数据权限
    private $THIS_DEPARTMENT_AND_THE_FOLLOWING_DATA_PERMISSIONS = 2;
    //本部门数据权限
    private $DATA_PERMISSIONS_FOR_THIS_DEPARTMENT = 3;
    //本人数据权限
    private $PERSONAL_DATA_RIGHTS = 4;

    /**
     * 关闭数据权限
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeOffDataAuth($query)
    {
        return $query->withoutGlobalScope('dataAuth');
    }

    /**
     * 数据权限字段
     * @var array
     */
    public function initializeDataPermissions()
    {
        $adminId = Admin::id();
        if ($adminId && plugin()->webman->config('admin_auth_id') != $adminId) {

            static::addGlobalScope('dataAuth', function ($builder) {
                $adminId = Admin::id();
                if (request()->app != 'api' && $adminId && plugin()->webman->config('admin_auth_id') != $adminId) {
                    $role_user_table = plugin()->webman->config('database.role_user_table');
                    $role_table = plugin()->webman->config('database.role_table');
                    $role = DB::connection($this->getConnectionName())->table($role_table)
                        ->selectRaw($role_table . '.id,data_type')
                        ->where($role_user_table . '.user_id', $adminId)
                        ->join($role_user_table, $role_user_table . '.role_id', '=', $role_table . '.id')
                        ->orderBy('data_type')
                        ->first();
                    $builder->where(function ($query) use ($role, $adminId) {
                        $table = $this->getTable();
                        $user_table = plugin()->webman->config('database.user_table');
                        switch ($role->data_type) {
                            case $this->CUSTOM_DATA_PERMISSIONS:
                                $role_department_table = plugin()->webman->config('database.role_department_table');
                                $query->where(function ($q) use ($table, $query, $user_table, $role_department_table, $role) {
                                    $this->eachDataAuth(function ($field, $adminField) use ($table, $q, $user_table, $role_department_table, $role) {
                                        $db = DB::connection($this->getConnectionName())->table($user_table)
                                            ->selectRaw($user_table . '.' . $adminField)
                                            ->whereNull($user_table . '.deleted_at')
                                            ->join($role_department_table, $role_department_table . '.department_id', '=', $user_table . '.department_id')
                                            ->where($role_department_table . '.role_id', $role->id);
                                        $q->whereRaw($table . '.' . $field . ' IN (' . $db->toSql() . ')', $db->getBindings());
                                    });
                                })->orWhere(function ($q) use ($table) {
                                    $this->eachDataAuth(function ($field, $adminField) use ($table, $q) {
                                        $q->where($table . '.' . $field, Admin::user()->$adminField);
                                    });
                                });
                                break;
                            case $this->THIS_DEPARTMENT_AND_THE_FOLLOWING_DATA_PERMISSIONS:
                                $department_id = Admin::user()->department_id;
                                $department_table = plugin()->webman->config('database.department_table');
                                $this->eachDataAuth(function ($field, $adminField) use ($table, $query, $department_id, $user_table, $department_table) {
                                    $db = DB::connection($this->getConnectionName())->table($user_table)
                                        ->selectRaw($user_table . '.' . $adminField)
                                        ->whereNull($user_table . '.deleted_at')
                                        ->join($department_table, $department_table . '.id', '=', $user_table . '.department_id')
                                        ->whereRaw("FIND_IN_SET({$department_id},{$department_table}.path)");
                                    $query->whereRaw($table . '.' . $field . ' IN (' . $db->toSql() . ')', $db->getBindings());
                                });
                                break;
                            case $this->DATA_PERMISSIONS_FOR_THIS_DEPARTMENT:
                                $department_id = Admin::user()->department_id;
                                $this->eachDataAuth(function ($field, $adminField) use ($table, $query, $department_id, $user_table) {
                                    $db = DB::connection($this->getConnectionName())->table($user_table)
                                        ->selectRaw($user_table . '.' . $adminField)
                                        ->whereNull($user_table . '.deleted_at')
                                        ->where('department_id', $department_id);
                                    $query->whereRaw($table . '.' . $field . ' IN (' . $db->toSql() . ')', $db->getBindings());
                                });
                                break;
                            case $this->PERSONAL_DATA_RIGHTS:
                                $this->eachDataAuth(function ($field, $adminField) use ($table, $query) {
                                    $query->where($table . '.' . $field, Admin::user()->$adminField);
                                });
                                break;
                        }
                    });
                }
            });
        }
    }

    private function eachDataAuth(\Closure $closure)
    {
        foreach ($this->dataAuth as $key => $field) {
            if (is_numeric($key)) {
                $adminField = 'id';
            } else {
                $adminField = $key;
            }
            call_user_func_array($closure, [$field, $adminField]);
        }
    }
}
