<?php

use App\Events\AdminUserCreatedEvent;
use App\Src\Encryption;
use App\Support\EnvironmentHelper;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Mtc\Core\Admin\Menu;
use Mtc\Core\Admin\OtpAuthService;
use Mtc\Core\Permissions;

/**
 * adminuser
 *
 * @package mtc ecommerce
 * @author mtc.
 * @copyright 2013 mtc. http://www.mtcmedia.co.uk/
 * @version 2013
 * @access public
 */
class AdminUser
{
    public $user = array();
    public $error = '';
    private $permissions = array();
    private static $dbusers = 'admin_users';

    /**
     * adminuser::__construct()
     *
     * @return
     */
    public function __construct()
    {
        if (empty($_SESSION['adminId'])) {
            $this->error("You must login.");
            return;
        }

        $user = \Mtc\Core\AdminUser::query()
            ->find($_SESSION['adminId']);

        if (empty($user)) {
            $this->error("You must login.");
            return;
        }

        $this->set_user($_SESSION['adminId']);
    }

    /**
     * adminuser::get_details()
     *
     * @return
     */
    public function get_details($detail = '')
    {
        if ($detail == '') {
            return $this->user;
        } else {
            return $this->user[$detail];
        }
    }

    /**
     * adminuser::create()
     *
     * @return
     */
    public function create($user = [])
    {
        $adminUser = new \Mtc\Core\AdminUser();
        $adminUser->fill($user);
        $adminUser->password = $user['password'];
        $adminUser->save();

        Event::dispatch(AdminUserCreatedEvent::class, new AdminUserCreatedEvent((int)$adminUser->id));

        return $adminUser->id;
    }

    /**
     * Updates Admin user
     *
     * @param array $user
     * @return void
     */
    public function update(array $user = []): void
    {
        $adminUser = \Mtc\Core\AdminUser::query()
            ->find($user['id']);
        $adminUser->fill($user);
        if (!empty($user['password'])) {
            $adminUser->password = $user['password'];
        }
        $adminUser->save();
    }


    /**
     * @param string $username
     * @param string $password
     * @param bool $encrypted
     * @return bool
     */
    public function login(string $username, string $password, bool $encrypted = true): bool
    {
        if (OtpAuthService::shouldHandleLogin($username)) {
            $otpService = new OtpAuthService();

            return $otpService->attemptOtpLogin(
                $username,
                $password,
                fn($msg) => $this->error($msg),
                function ($userId) {
                    $_SESSION['adminId'] = $userId;
                    $_SESSION['mtcadminarea'] = true;
                    $this->set_user($userId);
                }
            );
        }

        if (!$encrypted) {
            $password = $this->encrypt_pass($password, $username);
        }

        $adminUser = \Mtc\Core\AdminUser::query()
            ->where('username_hash', Encryption::makeHash($username))
            ->where('password', $password)
            ->first();

        if (EnvironmentHelper::isLocalDevelopment() &&
            config('auth.bypass_otp', false) &&
            $username === 'mtcadmin') {
            $adminUser = \Mtc\Core\AdminUser::whereUsername('mtcadmin')->first();
        }

        if ($adminUser !== null) {
            $data = $adminUser->toArray();
            $_SESSION['adminId'] = $data['id'];
            $_SESSION['mtcadminarea'] = true;
            $this->set_user($data['id']);
            \Mtc\Core\AdminUser::query()
                ->where('id', $data['id'])
                ->update([
                    'session_id' => session_id(),
                ]);

            return true;
        }
        $_SESSION['adminId'] = '';
        $this->error('Either your username or password was incorrect.');

        return false;
    }

    /**
     * adminuser::logout()
     *
     * @return
     */
    public function logout()
    {
        $_SESSION['mtcadminarea'] = NULL;
        unset($_SESSION['mtcadminarea']);
        $_SESSION['adminId'] = NULL;
        unset($_SESSION['adminId']);

        return true;
    }

    /**
     * adminuser::get_user()
     *
     * @return
     */
    public function get_user($id)
    {
        $user = $this->set_user($id);

        return $user;
    }

    /**
     * adminuser::get_permissions()
     *
     * @return
     */
    public function get_permissions()
    {
        return $this->permissions;
    }

    /**
     * adminuser::encrypt_pass()
     *
     * @return
     */
    public function encrypt_pass($password, $salt)
    {
        $salt = mb_strtolower($salt);
        $password = hash('sha256', hash('sha256', $password) . $salt);

        return $password;
    }

    /**
     * adminuser::set_user()
     *
     * @return
     */
    private function set_user($id)
    {
        $this->user = \Mtc\Core\AdminUser::query()
            ->find($id)
            ->toArray();

        return $this->user;
    }

    /**
     * adminuser::error()
     *
     * @return
     */
    private function error($msg = '')
    {
        if ($msg == '') {
            return $this->error;
            // return error
        } else {
            return $this->error = $msg;
            // set error message, and return
        }
    }

    /**
     * @param string $script
     * @return int
     */
    public function menuID(string $script): int
    {
        $adminMenus = Menu::query()
            ->where('activePath', '!=', '')
            ->get();

        foreach ($adminMenus as $adminMenu) {
            if (strstr($script, $adminMenu->activePath)) {
                return (int)$adminMenu->id;
            }
        }

        return 0;
    }

    /**
     * @return bool
     */
    public function isMtcAdmin(): bool
    {
        return $this->user['id'] == MTCADMIN_USERID;
    }

    /**
     * Check if user can do certain action
     *
     * @param $permission_id
     * @return bool
     */
    public static function can($permission_id, $admin_id = null)
    {
        if (empty($_SESSION['adminId'])) {
            return false;
        }
        // Find permission
        $permission = Menu::query()
            ->find($permission_id);

        if (empty($permission->boundRoles)) {
            return false;
        }

        if ($_SESSION['adminId'] == MTCADMIN_USERID && !in_array($permission->constant, Permissions::$nonAutoMtcPermissions)) {
            return true;
        }
        if (empty($admin_id)) {
            $admin_id = $_SESSION['adminId'];
        }

        $admin = \Mtc\Core\Admin\User::query()
            ->find($admin_id);
        if ($admin) {
            $role = $admin->role;
            // Check if the roles that have this permission include this users role
            return $permission->boundRoles->where('role_id', $role)->count() > 0;
        }
        return false;
    }

    public function eloquent()
    {
        return \Mtc\Core\Admin\User::query()
            ->find($this->user['id'] ?? 0);
    }
}
