<?php

namespace App\Http\Controllers\Admin;

use App\Exports\UsersExport;
use App\Http\Controllers\Controller;
use App\Libs\Facades\Localization;
use App\Libs\Facades\RequestContext;
use App\Libs\Transformers\BackendAuth\BackendUserTransformer;
use App\Models\BackendRole;
use App\Models\BackendUser;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Maatwebsite\Excel\Facades\Excel;
use Spatie\Fractal\Facades\Fractal;
use App\Models\Website;

class UserController extends Controller {

    public function getIndex()
    {
        return view('admin/pages/backend_users/admin_users');
    }

    public function postList(){
        $page = request()->input("current");
        $sort = request()->input("sort");
        $search = request()->input("searchPhrase");

        if (!empty($page)) {
            Paginator::currentPageResolver(function () use ($page) {
                return $page;
            });
            if (!empty($search)) {
                $query = BackendUser::where(function ($query) use ($search) {
                    $query->orWhere('name', 'like', "%{$search}%")
                    ->orWhere('username', 'like', "%{$search}%");
                });
            } else {
                $query = BackendUser::query();
            }
            $query->with('backendRole');
            if (empty($sort)) {
                $rows = $query->paginate(request()->input("rowCount"));
            } else {
                foreach ($sort as $field => $direction) {
                    if(empty($direction) || !Str::is(strtolower($direction),"desc")){
                        $order_direction = "asc";
                    }
                    $rows = $query->orderBy($field, strtolower($direction))->paginate(request()->input("rowCount"));
                    break;
                }
            }

            $result = array(
                "total"             => $rows->total(),
                "current"           => $rows->currentPage(),
                "rowCount"          => request()->input("rowCount"),
                "rows"              => $rows->getCollection()
            );

            $result["rows"] = Fractal::collection(
                $result["rows"],
                new BackendUserTransformer)->toArray();

            return response()->json($result);
        } else {
            $users = BackendUser::all();
            return response()->json(Fractal::collection(
                $users,
                new BackendUserTransformer(['backendRole']))->toArray());
        }
    }

    public function postInsert()
    {
        $data = array(
            'name' => strip_tags(request()->input('name', '')),
            'username' => request()->input('username'),
            'email' => request()->input('email'),
            'backend_role_id' => request()->input('backend_role_id'),
            'password' => request()->input('password'),
            'password_confirmation' => request()->input("password_confirmation")
        );

        $validator = Validator::make(
            $data,
            array(
                'name' => 'required|max:100',
                'email' => 'required|max:100|email|unique:backend_users,email',
                'username' => 'required|alpha_num|max:20|unique:backend_users',
                'backend_role_id' => 'required|integer|exists:backend_roles,id',
                'password' => "required|min:8|max:20|regex:/^.*(?=.{4,})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[\"\'!@#$%^&*()_+\-=\[\]{};':,.<>\/?]).*$/|confirmed"
            )
        );

        if ($validator->fails()) {
            request()->flash();
            return redirect()->to('/admin/admin-users/edit')->withErrors($validator);
        }
        unset($data["password_confirmation"]);

        $logged_user = Auth::guard('admin')->user();
        $websites = Website::all();

        $websiteAccess = request()->input('website_access');
        $websiteDefault = request()->input('website_default');

        $websitesAccess = array();
        foreach ($websites as $website) {
            if ($logged_user->hasPermission("backend.user.create")) {
                //If user has create / edit permissions, the websites array is given by the form
                if (!empty($websiteAccess) && array_key_exists($website->id, $websiteAccess)) {
                    $websitesAccess[$website->id] = array (
                        'is_default' => false
                    );
                }
            } else {
                //If the user does not have create / edit permissions, the websites array is the DB
                foreach ($logged_user->websites as $userWebsite) {
                    $websitesAccess[$userWebsite->id] = array (
                        'is_default' => false
                    );
                }
            }
        }

        if ($logged_user->hasPermission("backend.user.create")) {
            if ($websiteDefault && array_key_exists($websiteDefault, $websitesAccess)) {
                $websitesAccess[$websiteDefault]['is_default'] = true;
            } else {
                if (!empty($websitesAccess)) {
                    $websitesAccess[array_keys($websitesAccess)[0]]['is_default'] = true;
                }
            }
        }

        DB::transaction(function () use ($data, $websitesAccess) {
            $user = BackendUser::create($data);
            $user->websites()->sync($websitesAccess);
        });

        return redirect()->to('/admin/admin-users/')->with("message", "User Created.");
    }

    public function postEdit($user_id)
    {
        if (!is_numeric($user_id)) {
            abort(404);
        }

        $logged_user = Auth::guard('admin')->user();

        if ($logged_user->id != $user_id && !$logged_user->hasRole(array("Administrator"))) {
            abort(403);
        }

        $data = array(
            'name' => strip_tags(request()->input('name', '')),
            'username' => request()->input('username'),
            'backend_role_id' => request()->input('backend_role_id'),
            'email' => request()->input('email')
        );

        $rules = array(
            'name' => 'required|max:100',
            'username' => 'required|alpha_num|max:20|unique:backend_users,username,' . $user_id,
            'email' => 'required|max:100|email|unique:backend_users,email,' . $user_id,
        );

        if ($logged_user->hasRole(array("Administrator"))) {
            $rules['backend_role_id'] = 'required|integer|exists:backend_roles,id';
        }

        if(request()->filled("password")){
            $data['password'] = request()->input('password');
            $data['password_confirmation'] = request()->input('password_confirmation', "");
            $rules['password'] = "required|min:8|max:20|regex:/^.*(?=.{4,})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[\"\'!@#$%^&*()_+\-=\[\]{};':,.<>\/?]).*$/|confirmed";
        }

        $validator = Validator::make(
            $data,
            $rules
        );

        if($validator->fails()){
            request()->flash();
            return redirect()->to('/admin/admin-users/edit/' . $user_id)->withErrors($validator);
        }

        $user = BackendUser::find($user_id);

        if(empty($user)){
            abort(404);
        }

        $user->username = $data["username"];
        $user->name = $data["name"];
        $user->email = $data["email"];

        if($logged_user->hasPermission("backend.user.create")){
            $user->backend_role_id = $data['backend_role_id'];
        }

        if(isset($data["password"])){
            $user->password = $data["password"];
        }


        $websites = Website::all();
        $currentWebsites = $user->websites();
        $websiteAccess = request()->input('website_access');
        $websiteDefault = request()->input('website_default');

        $websitesAccess = array();
        foreach ($websites as $website) {
            if ($logged_user->hasPermission("backend.user.create")) {
                //If user has create / edit permissions, the websites array is given by the form
                if (!empty($websiteAccess) && array_key_exists($website->id, $websiteAccess)) {
                    $websitesAccess[$website->id] = array (
                        'is_default' => false
                    );
                }
            } else {
                //If the user does not have create / edit permissions, the websites array is the DB
                foreach ($user->websites as $userWebsite) {
                    $websitesAccess[$userWebsite->id] = array (
                        'is_default' => false
                    );
                }
            }
        }

        if ($logged_user->hasPermission("backend.user.create")
            || $logged_user->id == $user->id) {
            if ($websiteDefault && array_key_exists($websiteDefault, $websitesAccess)) {
                $websitesAccess[$websiteDefault]['is_default'] = true;
            } else {
                if (!empty($websitesAccess)) {
                    $websitesAccess[array_keys($websitesAccess)[0]]['is_default'] = true;
                }
            }
        }

        DB::transaction(function () use ($user, $websitesAccess) {
            $user->websites()->sync($websitesAccess);
            $user->save();
        });

        session()->flash('message', trans('backend.updated_successfully', array('entity' => trans('backend.user'))));
        if ($logged_user->hasPermission("backend.user.create")) {
            return redirect()->to('/admin/admin-users/')->with("message", "User Updated.");
        } else {
            return redirect()->to('/admin/admin.users/edit/' . $user_id);
        }
    }

    public function getEdit($user_id = null)
    {
        if ($user_id !== null && !is_numeric($user_id)) {
            abort(404);
        }

        $logged_user = Auth::guard('admin')->user();

        if(!empty($user_id) && $logged_user->id != $user_id && !$logged_user->hasRole(array("Administrator"))){
            abort(403);
        }

        RequestContext::set('selected_menu', 'admin');
        RequestContext::set('selected_menu_option', 'list_users');

        if (!empty($user_id)) {
            $user = BackendUser::find($user_id);
        } else {
            $user = new BackendUser();
        }

        $roles = BackendRole::pluck('name', 'id');
        $websites = Website::all();
        $websitesAccess = array();
        $currentWebsite = Localization::getWebsite();

        if($user->exists){
            foreach ($websites as $website) {
                $websiteAccess = $user->websites->find($website->id);
                if ($logged_user->hasPermission("backend.user.create") || !empty($websiteAccess)) {
                    $websitesAccess[] = array(
                        'id'         => $website->id,
                        'name'       => $website->name,
                        'has_access' => !empty($websiteAccess),
                        'is_default' => !empty($websiteAccess) && $websiteAccess->pivot->is_default,
                        'access_edit'=> $logged_user->hasPermission("backend.user.create")
                    );
                }
            }

            return view('admin/pages/backend_users/edit_user')
                ->with(array(
                    'user' => $user,
                    'roles' => $roles,
                    'websites' => $websitesAccess
                ));
        }else{
            foreach ($websites as $website) {
                $websitesAccess[] = array(
                    'id'         => $website->id,
                    'name'       => $website->name,
                    'has_access' => $currentWebsite->id == $website->id,
                    'is_default' => $currentWebsite->id == $website->id,
                    'access_edit'=> true
                );
            }

            return view('admin/pages/backend_users/insert_user')
                ->with(array(
                    'user' => $user,
                    'roles' => $roles,
                    'websites' => $websitesAccess
                ));
        }
    }

    public function postDelete()
    {
        $userId = request()->input('id');
        if (!is_numeric($userId)) {
            return response()->json(false);
        }

        $logged_user = Auth::guard('admin')->user();

        if($logged_user->id == $userId || !$logged_user->hasRole(array("Administrator"))){
            return response()->json(false);
        }

        BackendUser::destroy($userId);
        return response()->json(true);
    }

    public function getExportUsers()
    {
        return Excel::download(new UsersExport, 'users.xlsx');
    }
}
