<?php

defined('ABSPATH') or die();

function drk_enable_otp()
{
    $user = wp_get_current_user();

    if (!$user) {
        return new WP_Error('invalid_otp', 'Not authorized', array('status' => 401));
    }

    update_user_meta($user->ID, 'drk_otp_is_active', "true");
    update_user_meta($user->ID, 'user_otp_secret', drk_generate_otp_code());
    delete_user_meta($user->ID, 'user_otp_mail_code', '');

    return get_user_meta($user->ID, 'user_otp_secret', true);
}

function drk_disable_otp()
{
    $user = wp_get_current_user();

    if (!$user) {
        return new WP_Error('invalid_otp', 'Not authorized', array('status' => 401));
    }

    delete_user_meta($user->ID, 'user_otp_secret', '');
    delete_user_meta($user->ID, 'drk_otp_is_active', '');

    return 'ok';
}

function drk_get_otp_qrcode_rest()
{
    $user = wp_get_current_user();

    if (!$user) {
        return new WP_Error('invalid_otp', 'Not authorized', array('status' => 401));
    }
    $otpSecret = get_user_meta($user->ID, "user_otp_secret", true);
    $is_otp_active = get_the_author_meta('drk_otp_is_active', $user->ID);
    if ($is_otp_active != true)
        $otpSecret = drk_generate_otp_code();

    if (!$otpSecret) {
        return new WP_Error('invalid_otp', 'Invalid otp code', array('status' => 400));
    }
    update_user_meta($user->ID, 'user_otp_secret', $otpSecret);

    $url = Sonata\GoogleAuthenticator\GoogleQrUrl::generate('Darkey (' . $user->data->user_login . ')', $otpSecret);

    echo '<img src="' . $url . '" />';
}

function drk_get_otp_qrcode_admin(WP_User $user)
{
    $otpSecret = get_user_meta($user->ID, "user_otp_secret", true);
    $is_otp_active = get_user_meta('drk_otp_is_active', $user->ID, true);
    if (strlen($otpSecret) == 0 || !$is_otp_active)
        $otpSecret = drk_generate_otp_code();

    if (!$otpSecret) {
        return new WP_Error('invalid_otp', 'Invalid otp code', array('status' => 400));
    }

    $url = Sonata\GoogleAuthenticator\GoogleQrUrl::generate('Darkey (' . $user->data->user_login . ')', $otpSecret);
    update_user_meta($user->ID, 'user_otp_secret', $otpSecret);
    echo '<img src="' . $url . '" />';
}

function drk_otp_verify(WP_REST_Request $request)
{
    $secret_key = defined('JWT_AUTH_SECRET_KEY') ? JWT_AUTH_SECRET_KEY : false;

    $token = $request->get_param('token');

    try {
        $data = Firebase\JWT\JWT::decode($token, $secret_key, ['HS256']);
    } catch (Exception $e) {
        return new WP_Error('invalid_token', $e->getMessage(), array('status' => 401));
    }

    $user = get_user_by('ID', $data->data->user->id);

    if (!$user) {
        return new WP_Error('invalid_otp', 'Not authorized', array('status' => 401));
    }

    $otpSecret = get_user_meta($user->ID, 'user_otp_secret', true);

    if (!$otpSecret) {
        return new WP_Error('invalid_otp', 'User doesn\'t have otp secret key', array('status' => 500, "user" => $user));
    }

    $g = new Sonata\GoogleAuthenticator\GoogleAuthenticator();

    if (!$g->checkCode($otpSecret, $request->get_param('code'))) {
        return new WP_Error('invalid_otp', 'Invalid otp code', array('status' => 400, 'otpSecret' => $otpSecret,'otp_code'=>$request->get_param('code'),'user'=>$user));
    }


    $issuedAt = time();
    $notBefore = $issuedAt;
    $expire = $issuedAt + (DAY_IN_SECONDS * 7);

    $token = [
        'iss' => get_bloginfo('url'),
        'iat' => $issuedAt,
        'nbf' => $notBefore,
        'exp' => $expire,
        'data' => [
            'user' => [
                'id' => $user->ID,
            ],
        ],
    ];
    $otp_is_active = get_the_author_meta('drk_otp_is_active', $user->data->ID);
    if ($otp_is_active != true) {
        update_user_meta($user->ID, 'drk_otp_is_active', "true");
        delete_user_meta($user->ID, 'user_otp_mail_code', "");
    }
    $twoFa = false;
    $twoFaAuth = get_the_author_meta('drk_otp_is_active', $user->data->ID);
    $twoFaEmail = get_the_author_meta('user_otp_mail_code', $user->data->ID);
    $twoFaPGP = get_the_author_meta('drk_pgp_is_enabled', $user->data->ID);

    if($twoFaAuth == "true"){
        $twoFa = 'Auth';
    }elseif($twoFaEmail != ""){
        $twoFa = 'Email';
    }elseif ($twoFaPGP == 'true'){
        $twoFa = 'PGP';
    }


    $email_is_confirmed = get_the_author_meta('drk_email_is_confirmed', $user->data->ID);
    $profile = drk_get_user_profile((array)$user->data);
    $roles = $user->get_role_caps();

    return [
        'token' => Firebase\JWT\JWT::encode($token, $secret_key),
        'user_email' => $user->data->user_email,
        'user_nicename' => $user->data->user_nicename,
        'user_display_name' => $user->data->display_name,
        "user_id" => $user->data->ID,
        "user_role" => get_userdata($user->data->ID)->roles,
        "user_caps" => $roles,
        "user_registered" => $user->data->user_registered,
        "2fa" => $twoFa,
        "is_email_confirmed" => $email_is_confirmed,
        "profile" => $profile
    ];
}

add_action('rest_api_init', 'get_2fa_qrcode_rest');
function get_2fa_qrcode_rest()
{

    register_rest_route('2fa/v1', '/enable', [
        'methods' => 'POST',
        'callback' => 'drk_enable_otp',
        'permission_callback' => '__return_true'
    ]);

    register_rest_route('2fa/v1', '/disable', [
        'methods' => 'POST',
        'callback' => 'drk_disable_otp',
        'permission_callback' => '__return_true'
    ]);

    register_rest_route('2fa/v1', '/qrcode', [
        'methods' => 'GET',
        'callback' => 'drk_get_otp_qrcode_rest',
        'permission_callback' => '__return_true'
    ]);

    register_rest_route('2fa/v1', '/verify', [
        'methods' => 'POST',
        'callback' => 'drk_otp_verify',
        'permission_callback' => '__return_true'
    ]);

}

add_filter('jwt_auth_token_before_dispatch', 'check_otp_is_enable', 10, 2);
function check_otp_is_enable($data, $user)
{
    $otpSecret = get_user_meta($user->ID, 'drk_otp_is_active', true);

    if (!$otpSecret) {
        return $data;
    }

    $secret_key = defined('JWT_AUTH_SECRET_KEY') ? JWT_AUTH_SECRET_KEY : false;
    $issuedAt = time();
    $notBefore = $issuedAt;
    $expire = $issuedAt + 3600;

    $token = [
        'iss' => get_bloginfo('url'),
        'iat' => $issuedAt,
        'nbf' => $notBefore,
        'exp' => $expire,
        'data' => [
            'user' => [
                'id' => $user->ID,
            ],
        ],
    ];

    $jwt = Firebase\JWT\JWT::encode($token, $secret_key ,'HS256');

    return new WP_Error('invalid_otp', 'OTP Auth is enabled', ['checker' => 'totp', 'token' => $jwt, 'status' => 403]);
}