<?php

namespace Wave\Http\Controllers\CMS;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\UserAccessLog;
use App\Models\Role;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Wave\Notifications\VerifyEmail;
use Yajra\DataTables\Facades\DataTables;

class UserController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function index()
    {
        $roles = Role::whereIn('id', [
            Role::IT_PERSONNEL_ROLE,
            Role::NUMSTATION_MANAGER_ROLE,
            Role::NUMSTATION_STAFF_ROLE,
        ])->get();
        return view('theme::cms.users.index')->with([
            'roles' => $roles,
        ]);
    }

    public function table()
    {
        $users = User::query()
            ->select(
                'users.id',
                'users.first_name',
                'users.last_name',
                'users.phone',
                'users.email',
                'roles.display_name',
                'users.status',
            )
            ->leftJoin('roles', 'users.role_id', '=', 'roles.id')
            ->whereIn('users.role_id', [
                Role::IT_PERSONNEL_ROLE,
                Role::NUMSTATION_MANAGER_ROLE,
                Role::NUMSTATION_STAFF_ROLE,
            ]);
            // ->whereNot('users.id', auth()->user()->id);

        return Datatables::of($users)
            ->escapeColumns(['id'])
            ->addColumn('status', function ($user) {
                $status = $user->status;
                if ($status == 'active') {
                    $status = '<span class="success item-list-note">' . ucwords($status) . '</span>';
                }
                else if ($status == 'inactive') {
                    $status = '<span class="failed item-list-note">' . ucwords($status) . '</span>';
                }

                return $status;
            })
            ->addColumn('actions', function ($user) {
                $suspendAction = '';
                $activateAction = '';
                $removeAction = '';
                $editUserAction = '';

                if (auth()->user()->userRole->hasAccess('manage-user-list-and-access-log')) {
                    $suspendAction = '<a class="dropdown-item suspend-user" href="#" data-action="' . route('cms.users.suspend', $user->id) . '">' . __("Suspend user") . '</a>';
                    $activateAction = '<a class="dropdown-item activate-user" href="#" data-action="' . route('cms.users.activate', $user->id) . '">' . __("Activate user") . '</a>';
                    $removeAction = '<a class="dropdown-item remove-user" href="#" data-action="' . route('cms.users.destroy', $user->id) . '">' . __("Remove user") . '</a>';
                    $editUserAction = '<a class="dropdown-item edit-user" href="#" data-action-show="' . route('cms.users.show', $user->id) . '" data-action-update="' . route('cms.users.update', $user->id) . '">' . __("Edit user") . '</a>';
                }

                $viewUserLogAction = '<a class="dropdown-item view-user-log" data-action="' . route("cms.users.accessLogsTable", $user->id) . '" href="#">' . __("View user log") . '</a>';
                $actions = '
                    <div class="dropdown non-custom">
                        <button type="button" data-bs-toggle="dropdown" aria-expanded="false"><img class="max-25" src="' . asset('themes/tailwind/images/more.svg') . '"></button>
                        <div class="dropdown-menu">
                            ' . ($user->status == 'active' ? $suspendAction : $activateAction) . '
                            ' . $removeAction . '
                            ' . $viewUserLogAction . '
                            ' . $editUserAction . '
                        </div>
                    </div>
                ';
                return $actions;
            })
            ->make(true);
    }

    public function accessLogsTable($userId = null)
    {
        $logs = UserAccessLog::query()
            ->select(
                'users.email',
                'user_access_logs.created_at',
                'user_access_logs.event',
                'user_access_logs.description',
                'user_access_logs.status',
            )
            ->leftJoin('users', 'user_access_logs.user_id', '=', 'users.id')
            ->when($userId, function ($query) use ($userId) {
                $query->where('users.id', $userId);
            })
            ->when(! $userId, function ($query) use ($userId) {
                $query->whereIn('users.role_id', [
                    Role::IT_PERSONNEL_ROLE,
                    Role::NUMSTATION_MANAGER_ROLE,
                    Role::NUMSTATION_STAFF_ROLE,
                ]);
            });

        return Datatables::of($logs)
            ->escapeColumns(['id'])
            ->addColumn('date', function ($log) {
                return date('Ymd', strtotime($log->created_at));
            })
            ->addColumn('time', function ($log) {
                return date('H:i', strtotime($log->created_at));
            })
            ->addColumn('status', function ($log) {
                return '<span class="' . $log->status . ' item-list-note">' . ucwords($log->status) . '</span>';
            })
            ->make(true);
    }

    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'first_name' => 'required|string|max:255',
            'last_name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'phone' => 'required|string',
            'password' => 'required|string|min:6|confirmed',
            'role_id' => 'required|int',
            'status' => 'required|string',
        ]);
        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors()
            ], 422);
        }
        else {
            event(new Registered($user = $this->create($request->all())));
    
            return response()->json([
                'success' => true,
                'message' => __("All changes have been saved!"),
            ]);
        }
    }

    public function suspend(User $user)
    {
        $user->status = 'inactive';
        $user->save();

        return response()->json([
            'success' => true,
            'message' => __("User has successfully suspended!"),
        ]);
    }

    public function activate(User $user)
    {
        $user->status = 'active';
        $user->save();

        return response()->json([
            'success' => true,
            'message' => __("User has successfully activated!"),
        ]);
    }

    public function destroy(User $user)
    {
        $user->delete();

        return response()->json([
            'success' => true,
            'message' => __("User has successfully removed!"),
        ]);
    }

    public function show(User $user)
    {
        return response()->json([
            'success' => true,
            'message' => __("User details has successfully retrieved!"),
            'user' => $user,
        ]);
    }

    public function update(User $user, Request $request)
    {
        $validator = Validator::make($request->all(), [
            'first_name' => 'required|string|max:255',
            'last_name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users,email,' . $user->id,
            'phone' => 'required|string',
            'current_password' => 'nullable|string|min:6',
            'password' => 'nullable|string|min:6|confirmed',
            'role_id' => 'required|int',
            'status' => 'required|string',
        ]);
        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors()
            ], 422);
        }
        else {
            if ($request->current_password && !\Hash::check($request->current_password, $user->password)) {
                return response()->json([
                    'success' => false,
                    'message' => __('The current password is incorrect.'),
                ]);
            }

            $userData = $request->all();
            if ($userData['password']) {
                $userData['password'] = bcrypt($userData['password']);
            }
            else {
                unset($userData['password']);
            }

            unset($userData['current_password']);
            unset($userData['password_confirmation']);
            
            $user->update($userData);
    
            return response()->json([
                'success' => true,
                'message' => __("All changes have been saved!"),
            ]);
        }
    }

    private function create(array $data)
    {
        $verification_code = Str::random(30);
        $verified = 0;

        $username = $this->getUniqueUsernameFromEmail($data['email']);
        $username_original = $username;
        $counter = 1;

        while(User::where('username', '=', $username)->first()){
            $username = $username_original . (string)$counter;
            $counter += 1;
        }

        $user = User::create([
            'first_name' => $data['first_name'],
            'last_name' => $data['last_name'],
            'name' => $data['first_name'] . ' ' . $data['last_name'],
            'email' => $data['email'],
            'username' => $username,
            'password' => bcrypt($data['password']),
            'role_id' => $data['role_id'],
            'verification_code' => $verification_code,
            'verified' => $verified,
            'trial_ends_at' => null,
            'phone' => $data['phone'],
            'company_id' => (isset($data['company_id']) ? $data['company_id'] : null)
        ]);

        $this->sendVerificationEmail($user);

        return $user;
    }

    private function getUniqueUsernameFromEmail($email)
    {
        $username = strtolower(trim(Str::slug(explode('@', $email)[0])));

        $new_username = $username;

        $user_exists = \Wave\User::where('username', '=', $username)->first();
        $counter = 1;
        while (isset($user_exists->id) ) {
            $new_username = $username . $counter;
            $counter += 1;
            $user_exists = \Wave\User::where('username', '=', $new_username)->first();
        }

        $username = $new_username;

        if(strlen($username) < 4){
            $username = $username . uniqid();
        }

        return strtolower($username);
    }

    private function sendVerificationEmail($user){
        Notification::route('mail', $user->email)->notify(new VerifyEmail($user));
    }
}
