<?php
/**
 * File RoleController.php
 *
 * @author Tuan Duong <bacduong@gmail.com>
 * @package Laravue
 * @version 1.0
 */

namespace App\Http\Controllers;

use App\Http\Resources\PermissionResource;
use App\Laravue\Models\Permission;
use App\RoleMeta;
use App\RuleCustom;
use Illuminate\Http\Request;
use App\Laravue\Models\Role;
use App\Http\Resources\RoleResource;
use Illuminate\Support\Arr;
use Validator;

/**
 * Class RoleController
 *
 * @package App\Http\Controllers
 */
class RoleController extends Controller
{
    const ITEM_PER_PAGE = 20;

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $params = $request->all();
        $list = Role::select('id', 'name');
        $limit = Arr::get($params, 'limit', static::ITEM_PER_PAGE);
        $keyword = Arr::get($params, 'keyword', '');

        if (!empty($keyword)) {
            $list->where('name', 'LIKE', '%' . $keyword . '%');
        }
        $list->orderBy('id');

        return RoleResource::collection($list->paginate($limit));
        //return RoleResource::collection(Role::all());
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), ['name' => ['required']]);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $params = $request->all();
        $roleName = trim($params['name']);
        $roleName = str_replace(" ", "", $roleName);
        $roleName = strtolower($roleName);

        $checkRole = Role::where('name', $roleName)->count();
        if ($checkRole > 0) return response()->json(['error' => 'Role is exist.'], 404);
        $role = Role::create(['name' => $roleName]);
        RoleMeta::create(['role_id' => $role->id, 'description' => $params['description']]);

        $customRules = [];
        $permissionIds = [];
        $permissionMenu = $params['permissionMenu'];
        foreach ($permissionMenu as $m) {
            if ($m['selected'] == 1 || $m['selected'] == true || $m['selected'] == 'true') $permissionIds[] = $m['id'];
        }
        $permissionOther = $params['permissionOther'];
        foreach ($permissionOther as $groups) {
            foreach ($groups as $item) {
                if ($item['selected'] == 1 || $item['selected'] == true || $item['selected'] == 'true') $permissionIds[] = $item['id'];
                if (isset($item['rules'])) {
                    foreach ($item['rules'] as $r) {
                        if ($r['condition_name'] == 'user_id' && (trim($r['condition_value']) != null || trim($r['condition_value']) != "")) {
                            $r['condition_value'] = "owner";
                        }
                        if (trim($r['condition_value']) != null && trim($r['condition_value']) != "") {
                            $customRules[] = [
                                'role_id'           => $role->id,
                                'permission_id'     => $item['id'],
                                'condition_compare' => $r['condition_compare'],
                                'condition_name'    => $r['condition_name'],
                                'condition_value'   => $r['condition_value'],
                                'created_at'        => date('Y-m-d H:i:s'),
                                'updated_at'        => date('Y-m-d H:i:s'),
                            ];
                        }
                    }
                }
            }
        }

        $permissions = Permission::allowed()->whereIn('id', $permissionIds)->get();
        $role->syncPermissions($permissions);
        $role->save();
        if (count($customRules) > 0) RuleCustom::insert($customRules);

        return new RoleResource($role);
    }

    /**
     * Display the specified resource.
     *
     * @param Role
     * @return \Illuminate\Http\Response
     */
    public function show($roleId = 0)
    {
        $role = Role::where('id', $roleId)->first();
        if (!isset($role) || $role->name == 'admin') return response()->json(['errors' => 'Role is invalid'], 403);

        $checked = [];
        foreach ($role->permissions as $item) {
            $checked[$item->id] = $item->id;
        }

        $customRules = RuleCustom::where('role_id', $role->id)->get();
        $listRule = [];
        foreach ($customRules as $item) {
            $listRule[$item->permission_id][] = [
                'id'                => $item->id,
                'condition_name'    => $item->condition_name,
                'condition_compare' => $item->condition_compare,
                'condition_value'   => $item->condition_value,
                'open'              => false,
            ];
        }

        $permissionsAll = Permission::select('*')->orderBy('name')->get();
        $list = $this->detectPermission($permissionsAll, $listRule, $checked);

        return response()->json(['data' => ['id' => $role->id, 'name' => $role->name, 'meta' => $role->meta, 'permissions' => $list]], 200);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param \Illuminate\Http\Request $request
     * @param Role $role
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id = 0)
    {
        $role = Role::where('id', $id)->first();
        if (!isset($role) || $role === null || $role->name == 'admin' || $role->isAdmin()) return response()->json(['errors' => 'Role is invalid'], 404);

        $params = $request->all();
        RoleMeta::where('role_id', $role->id)->update(['description' => $params['description']]);

        $customRules = [];
        $permissionIds = [];
        $permissionMenu = $params['permissionMenu'];
        foreach ($permissionMenu as $m) {
            if ($m['selected'] == 1 || $m['selected'] == true || $m['selected'] == 'true') $permissionIds[] = $m['id'];
        }
        $permissionOther = $params['permissionOther'];
        foreach ($permissionOther as $groups) {
            foreach ($groups as $item) {
                if ($item['selected'] == 1 || $item['selected'] == true || $item['selected'] == 'true') $permissionIds[] = $item['id'];
                if (isset($item['rules'])) {
                    foreach ($item['rules'] as $r) {
                        if (trim($r['condition_value']) != null && trim($r['condition_value']) != "") {
                            $customRules[] = [
                                'role_id'           => $role->id,
                                'permission_id'     => $item['id'],
                                'condition_compare' => $r['condition_compare'],
                                'condition_name'    => $r['condition_name'],
                                'condition_value'   => $r['condition_value'],
                                'created_at'        => date('Y-m-d H:i:s'),
                                'updated_at'        => date('Y-m-d H:i:s'),
                            ];
                        }
                    }
                }
            }
        }

        $permissions = Permission::allowed()->whereIn('id', $permissionIds)->get();
        $role->syncPermissions($permissions);
        $role->save();
        RuleCustom::where('role_id', $role->id)->delete();
        if (count($customRules) > 0) RuleCustom::insert($customRules);

        return response()->json(null, 204);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param int $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }

    /**
     * Get permissions from role
     *
     * @param Role $role
     * @return \Illuminate\Http\Response
     */
    public function permissions(Role $role)
    {
        return PermissionResource::collection($role->permissions);
    }

    public function roleList()
    {
        $list = Role::select('id', 'name')->get();
        return response()->json(['data' => $list], 200);
    }

    public function permissionsAll()
    {
        $allPermission = Permission::select('*')->orderBy('name')->get();
        $list = $this->detectPermission($allPermission);

        return response()->json($list, 200);
    }

    private function detectPermission($permissions = [], $rules = [], $checked = []) {
        $result = [];
        foreach ($permissions as $pIt) {
            if (strpos($pIt->name, "view-menu-") !== false) {
                $fullName = str_replace("view-menu-", "", $pIt->name);
                $fullName = str_replace("-", " ", $fullName);
                $fullName = str_replace("fortuneteller", "Fortune teller", $fullName);
                $fullName = str_replace("fortunemethod", "Method", $fullName);
                $fullName = ucfirst($fullName);

                $result['menus'][] = [
                    'id'        => $pIt->id,
                    'name'      => $pIt->name,
                    'full_name' => $fullName,
                    'selected'  => isset($checked[$pIt->id]),
                ];
            } else {
                $fullName = str_replace("manage-", "", $pIt->name);
                $pkey = $fullName;
                $actionKey = 'manage';
                if (strpos($fullName, "-") !== false) {
                    $pkeyArr = explode("-", $fullName);
                    $pkey = isset($pkeyArr[0]) ? $pkeyArr[0] : $pkey;
                    $actionKey = (isset($pkeyArr[1]) && $pkeyArr[1] != "") ? $pkeyArr[1] : $actionKey;
                }
                if ($pkey == "permission") continue;

                if (strpos($fullName, "-only") !== false) {
                    $fullName = "View " . $pkey . " items";
                } elseif (strpos($fullName, "-create") !== false) {
                    $fullName = "Create new " . $pkey;
                } elseif (strpos($fullName, "-edit") !== false) {
                    $fullName = "Edit " . $pkey;
                } elseif (strpos($fullName, "-delete") !== false) {
                    $fullName = "Delete " . $pkey;
                } elseif (strpos($fullName, "-custom") !== false) {
                    $fullName = "Custom view list " . $pkey;
                } elseif (strpos($fullName, "-import") !== false) {
                    $fullName = "Import " . $pkey . " data";
                } elseif (strpos($fullName, "-group") !== false) {
                    $fullName = "Show items of the store";
                } elseif (strpos($fullName, "-owner") !== false) {
                    $fullName = "Show own items";
                } elseif (strpos($fullName, "-store") !== false) {
                    $fullName = "Store Option";
                } elseif (strpos($fullName, "-teller") !== false) {
                    $fullName = "Fortune Teller Option";
                } elseif (strpos($fullName, "-assign") !== false) {
                    $fullName = "Show assigned items";
                } elseif (strpos($fullName, "-hidden") !== false) {
                    $fullName = "Hide unused items";
                } elseif (strpos($fullName, "dashboard-") !== false) {
                    $endName = str_replace("dashboard-", "", $fullName);
                    $fullName = ucfirst($endName);
                } else {
                    $fullName = "Manage " . $pkey;
                }

                $fullName = str_replace("fortuneteller", "fortune teller", $fullName);
                $fullName = str_replace("fortunemethod", "method", $fullName);

                $result['others'][$pkey][$actionKey] = [
                    'id'        => $pIt->id,
                    'name'      => $pIt->name,
                    'full_name' => $fullName,
                    'selected'  => isset($checked[$pIt->id]),
                    'rules'     => isset($rules[$pIt->id]) ? $rules[$pIt->id] : []
                ];
            }
        }

        return $result;
    }
}
