<?php

/**
 * Authentication and account functions.  Connects to a Portal instance.
 */

/**
 * Check the login server API for sanity
 * @return boolean true if OK, else false
 */
function checkLoginServer() {
    try {
        $client = new GuzzleHttp\Client();

        $response = $client
                ->request('POST', PORTAL_API, [
            'form_params' => [
                'key' => PORTAL_KEY,
                'action' => "ping"
            ]
        ]);

        if ($response->getStatusCode() != 200) {
            return false;
        }

        $resp = json_decode($response->getBody(), TRUE);
        if ($resp['status'] == "OK") {
            return true;
        } else {
            return false;
        }
    } catch (Exception $e) {
        return false;
    }
}

////////////////////////////////////////////////////////////////////////////////
//                           Account handling                                 //
////////////////////////////////////////////////////////////////////////////////

/**
 * Checks the given credentials against the API.
 * @param string $username
 * @param string $password
 * @return boolean True if OK, else false
 */
function authenticate_user($username, $password) {
    $client = new GuzzleHttp\Client();

    $response = $client
            ->request('POST', PORTAL_API, [
        'form_params' => [
            'key' => PORTAL_KEY,
            'action' => "auth",
            'username' => $username,
            'password' => $password
        ]
    ]);

    if ($response->getStatusCode() > 299) {
        sendError("Login server error: " . $response->getBody());
    }

    $resp = json_decode($response->getBody(), TRUE);
    if ($resp['status'] == "OK") {
        return true;
    } else {
        return false;
    }
}

/**
 * Check if a username exists.
 * @param String $username
 */
function user_exists($username) {
    $client = new GuzzleHttp\Client();

    $response = $client
            ->request('POST', PORTAL_API, [
        'form_params' => [
            'key' => PORTAL_KEY,
            'action' => "userexists",
            'username' => $username
        ]
    ]);

    if ($response->getStatusCode() > 299) {
        sendError("Login server error: " . $response->getBody());
    }

    $resp = json_decode($response->getBody(), TRUE);
    if ($resp['status'] == "OK" && $resp['exists'] === true) {
        return true;
    } else {
        return false;
    }
}

/**
 * Check if a UID exists.
 * @param String $uid
 */
function uid_exists($uid) {
    $client = new GuzzleHttp\Client();

    $response = $client
            ->request('POST', PORTAL_API, [
        'form_params' => [
            'key' => PORTAL_KEY,
            'action' => "userexists",
            'uid' => $uid
        ]
    ]);

    if ($response->getStatusCode() > 299) {
        sendError("Login server error: " . $response->getBody());
    }

    $resp = json_decode($response->getBody(), TRUE);
    if ($resp['status'] == "OK" && $resp['exists'] === true) {
        return true;
    } else {
        return false;
    }
}

/**
 * Get the account status: NORMAL, TERMINATED, LOCKED_OR_DISABLED,
 * CHANGE_PASSWORD, or ALERT_ON_ACCESS
 * @param string $username
 * @return string
 */
function get_account_status($username) {
    $client = new GuzzleHttp\Client();

    $response = $client
            ->request('POST', PORTAL_API, [
        'form_params' => [
            'key' => PORTAL_KEY,
            'action' => "acctstatus",
            'username' => $username
        ]
    ]);

    if ($response->getStatusCode() > 299) {
        sendError("Login server error: " . $response->getBody());
    }

    $resp = json_decode($response->getBody(), TRUE);
    if ($resp['status'] == "OK") {
        return $resp['account'];
    } else {
        return false;
    }
}

////////////////////////////////////////////////////////////////////////////////
//                              Login handling                                //
////////////////////////////////////////////////////////////////////////////////

/**
 * Setup $_SESSION values with user data and set loggedin flag to true
 * @param string $username
 */
function doLoginUser($username) {
    $client = new GuzzleHttp\Client();

    $response = $client
            ->request('POST', PORTAL_API, [
        'form_params' => [
            'key' => PORTAL_KEY,
            'action' => "userinfo",
            'username' => $username
        ]
    ]);

    if ($response->getStatusCode() > 299) {
        sendError("Login server error: " . $response->getBody());
    }

    $resp = json_decode($response->getBody(), TRUE);
    var_dump($resp);
    if ($resp['status'] == "OK") {
        $userinfo = $resp['data'];
        $_SESSION['username'] = $username;
        $_SESSION['uid'] = $userinfo['uid'];
        $_SESSION['email'] = $userinfo['email'];
        $_SESSION['realname'] = $userinfo['name'];
        $_SESSION['password'] = $password;
        $_SESSION['loggedin'] = true;
        return true;
    } else {
        return false;
    }
}

function simLogin($username, $password) {
    $client = new GuzzleHttp\Client();

    $response = $client
            ->request('POST', PORTAL_API, [
        'form_params' => [
            'key' => PORTAL_KEY,
            'action' => "login",
            'username' => $username,
            'password' => $password
        ]
    ]);

    if ($response->getStatusCode() > 299) {
        sendError("Login server error: " . $response->getBody());
    }

    $resp = json_decode($response->getBody(), TRUE);
    if ($resp['status'] == "OK") {
        return true;
    } else {
        return $resp['msg'];
    }
}

function verifyReCaptcha($code) {
    try {
        $client = new GuzzleHttp\Client();

        $response = $client
                ->request('POST', "https://www.google.com/recaptcha/api/siteverify", [
            'form_params' => [
                'secret' => RECAPTCHA_SECRET_KEY,
                'response' => $code
            ]
        ]);

        if ($response->getStatusCode() != 200) {
            return false;
        }

        $resp = json_decode($response->getBody(), TRUE);
        if ($resp['success'] === true) {
            return true;
        }
        return false;
    } catch (Exception $e) {
        return false;
    }
}

////////////////////////////////////////////////////////////////////////////////
//                          2-factor authentication                           //
////////////////////////////////////////////////////////////////////////////////

/**
 * Check if a user has TOTP setup
 * @param string $username
 * @return boolean true if TOTP secret exists, else false
 */
function userHasTOTP($username) {
    $client = new GuzzleHttp\Client();

    $response = $client
            ->request('POST', PORTAL_API, [
        'form_params' => [
            'key' => PORTAL_KEY,
            'action' => "hastotp",
            'username' => $username
        ]
    ]);

    if ($response->getStatusCode() > 299) {
        sendError("Login server error: " . $response->getBody());
    }

    $resp = json_decode($response->getBody(), TRUE);
    if ($resp['status'] == "OK") {
        return $resp['otp'];
    } else {
        return false;
    }
}

/**
 * Verify a TOTP multiauth code
 * @global $database
 * @param string $username
 * @param int $code
 * @return boolean true if it's legit, else false
 */
function verifyTOTP($username, $code) {
    $client = new GuzzleHttp\Client();

    $response = $client
            ->request('POST', PORTAL_API, [
        'form_params' => [
            'key' => PORTAL_KEY,
            'action' => "verifytotp",
            'username' => $username,
            'code' => $code
        ]
    ]);

    if ($response->getStatusCode() > 299) {
        sendError("Login server error: " . $response->getBody());
    }

    $resp = json_decode($response->getBody(), TRUE);
    if ($resp['status'] == "OK") {
        return $resp['valid'];
    } else {
        return false;
    }
}
