<?php

namespace Eater\Glim\Service;

use Eater\Glim\Model\Base\UserQuery;
use Eater\Glim\Model\InviteQuery;
use Eater\Glim\Model\Invite;
use Eater\Glim\Model\User as UserModel;

class User extends  Main
{
    /**
     * @param string $invite
     * @param string $username
     * @param string $email
     * @param string $password
     * @return UserModel
     * @throws \Exception
     */
    public function register($invite, $username, $email, $password)
    {
        $invite = InviteQuery::create()->findOneByInvite($invite);

        if ($invite === null) {
            throw new \Exception("Invalid invite code");
        }

        $this->validateUserParams($username,  $email, $password);

        $inviteUser = $invite->getUser();

        $user = new UserModel();
        $user->setUsername($username);
        $user->setEmail($email);
        $user->setPassword(\password_hash($password, PASSWORD_DEFAULT));

        if ($inviteUser === null || $inviteUser->getMaxInvites() === -1) {
            $user->setMaxInvites(5);
        } elseif ($inviteUser->getMaxInvites() > 0) {
            $user->setMaxInvites($inviteUser->getMaxInvites() - 1);
        } else {
            $user->setMaxInvites(0);
        }

        $user->save();

        $invite->delete();

        return $user;
    }

    public function validateUserParams($username, $email, $password) {
        if ($username === "") {
            throw new \Exception("No username given");
        }

        if (!preg_match('~^[a-z0-9\-]+$~', $username)) {
            throw new \Exception("Username can only consist of a-z, 0-9 and -");
        }

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new \Exception("Email is invalid");
        }

        if ($password === "") {
            throw new \Exception("Password is nothing, though strong. we rather not have you use that");
        }

        if (strlen($password) < 9) {
            throw new \Exception("Please pick a password with more then 8 characters");
        }

        if ($this->exists($username)) {
            throw new \Exception("User already exists");
        }
    }

    public function createSuperuser($username, $email, $password) {

        $this->validateUserParams($username, $email, $password);

        $user = new UserModel();
        $user->setUsername($username);
        $user->setPassword(\password_hash($password, PASSWORD_DEFAULT));
        $user->setSuperuser(true);
        $user->setMaxInvites(-1);
        $user->save();

        return $user;
    }

    /**
     * @param string $username
     * @return bool
     */
    public function exists($username)
    {
        $amount = UserQuery::create()->findByUsername($username)->count();

        return $amount > 0;
    }

    public function login($username, $password)
    {
        $user = UserQuery::create()->findOneByUsername($username);

        if ($user === null || !password_verify($password, $user->getPassword())) {
            return null;
        }

        return $user;
    }

    /**
     * @param UserModel $user
     * @return string
     */
    public function createInvite(UserModel $user)
    {
        $invite = new Invite();
        $invite->setInvite(bin2hex(openssl_random_pseudo_bytes(20)));
        $invite->setUser($user);
        $invite->save();

        $user->setUsedInvites($user->getUsedInvites() + 1);
        $user->save();

        return $invite->getInvite();
    }
}
