<?php

defined('ABSPATH') or die();
putenv("GNUPGHOME=/var/www/admin.darkey.host");
function drk_add_pgp_key(WP_REST_Request $request)
{
    $user = wp_get_current_user();
    if (!$user) {
        return new WP_Error('invalid_pgp', 'Not authorized', array('status' => 401));
    }
    $public_key = $request->get_body();

    $filename = getenv('GNUPGHOME')."/.gpg/".$user->ID.".pgp";
    if(file($filename)){
        return new WP_Error('pgp_file_exist', 'PGP file is exist', array('status' => 405));
    }
    file_put_contents($filename, $public_key);
    $publicKey = file_get_contents($filename);

    $gpg= new gnupg();
    $gpg->seterrormode(gnupg::ERROR_EXCEPTION);
    $info = $gpg->import($publicKey);
    $gpg->addencryptkey($info['fingerprint']);

    $confirmation_code = drk_generate_otp_code();
    update_user_meta($user->ID,'drk_pgp_confirmation_code',$confirmation_code);

    $enc = $gpg->encrypt($confirmation_code);
    unlink($filename);

    update_user_meta($user->ID, 'drk_pgp_public_key', $public_key);

    echo $enc;
}

function drk_verify_pgp_key(WP_REST_Request $request)
{
    $user = wp_get_current_user();
    if (!$user) {
        return new WP_Error('invalid_pgp', 'Not authorized', array('status' => 401));
    }
    $public_key = get_the_author_meta('drk_pgp_public_key', $user->ID);
    $confirmation_code = get_the_author_meta('drk_pgp_confirmation_code',$user->ID);
    $decripted_code = $request->get_param('decripted_code');

    if($confirmation_code == "" || $public_key == ""){
        return new WP_Error('invalid_pgp_confirmation_code', 'Not set pgp key', array('status' => 401));
    }

    if(trim($decripted_code)!= trim($confirmation_code)){
        return new WP_Error('invalid_pgp_confirmation_code', 'Invalid confirmation code', array('status' => 401));
    }
    update_user_meta($user->ID, 'drk_pgp_is_enabled', "true");
    delete_user_meta($user->ID, 'user_otp_mail_code', '');
    delete_user_meta($user->ID, 'user_otp_secret', '');
    update_user_meta($user->ID, 'drk_otp_is_active', "false");
    delete_user_meta($user->ID,'drk_pgp_confirmation_code','');
    return true;
}

function drk_disable_pgp()
{
    $user = wp_get_current_user();
    $filename = getenv('GNUPGHOME')."/.gpg/".$user->ID.".pgp";
    if (!$user) {
        return new WP_Error('invalid_pgp', 'Not authorized', array('status' => 401));
    }
    update_user_meta($user->ID, 'drk_pgp_is_enabled', "false");
    delete_user_meta($user->ID,'drk_pgp_confirmation_code','');
    delete_user_meta($user->ID,'drk_pgp_public_key','');
    return unlink($filename);
}

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

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

    try {
        $key = new Firebase\JWT\Key($secret_key,'HS256');
        $data = Firebase\JWT\JWT::decode($token,$key);
    } 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_pgp', 'Not authorized', array('status' => 401));
    }
    $filename = getenv('GNUPGHOME')."/.gpg/".$user->ID.".pgp";
    $public_key = get_the_author_meta('drk_pgp_public_key', $user->ID);
    $confirmation_code = drk_generate_otp_code();
    update_user_meta($user->ID,'drk_pgp_confirmation_code',$confirmation_code);

    file_put_contents($filename, $public_key);
    $publicKey = file_get_contents($filename);
    $gpg= new gnupg();
    $gpg->seterrormode(gnupg::ERROR_EXCEPTION);
    $info = $gpg->import($publicKey);
    $gpg->addencryptkey($info['fingerprint']);

    echo $gpg->encrypt($confirmation_code);
}

function drk_pgp_verify(WP_REST_Request $request)
{
    $secret_key = defined('JWT_AUTH_SECRET_KEY') ? JWT_AUTH_SECRET_KEY : false;
    $token = $request->get_param('token');
    try {
        $key = new Firebase\JWT\Key($secret_key,'HS256');
        $data = Firebase\JWT\JWT::decode($token, $key);
    } 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_pgp', 'Invalid PGP', array('status' => 401));
    }
    $confirmation_code = get_the_author_meta('drk_pgp_confirmation_code',$user->ID);
    $decripted_code = $request->get_param('decripted_code');
    if(trim($decripted_code)!= trim($confirmation_code)){
        return new WP_Error('invalid_pgp_confirmation_code', 'Invalid confirmation code', array('status' => 401));
    }
    $pgp_is_active = get_the_author_meta('drk_pgp_is_enabled', $user->data->ID);
    if ($pgp_is_active != "true") {
        update_user_meta($user->ID, 'drk_pgp_is_enabled', "true");
        delete_user_meta($user->ID, 'user_otp_mail_code', "");
        delete_user_meta($user->ID, 'user_otp_secret', "");
    }

    $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();
    $issuedAt = time();
    $notBefore = $issuedAt;
    $expire = $issuedAt + 3600;

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

    return [
        'token' => Firebase\JWT\JWT::encode($payload, $secret_key,'HS256'),
        '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_pgp_auth_rest');
function get_pgp_auth_rest()
{

    register_rest_route('2fa/v1', '/add_pgp_key_activation', [
        'methods' => 'POST',
        'callback' => 'drk_add_pgp_key',
        'permission_callback' => '__return_true'
    ]);
    register_rest_route('2fa/v1', '/verify_pgp_key_activation', [
        'methods' => 'POST',
        'callback' => 'drk_verify_pgp_key',
        'permission_callback' => '__return_true',
        'args' => [
            'decripted_code' => [
                'required' => true,
                'type' => 'string',
            ],
        ]
    ]);
    register_rest_route('2fa/v1', '/pgp_disable', [
        'methods' => 'POST',
        'callback' => 'drk_disable_pgp',
        'permission_callback' => '__return_true'
    ]);
    register_rest_route('2fa/v1', '/pgp_verify', [
        'methods' => 'GET',
        'callback' => 'drk_get_pgp_verify',
        'permission_callback' => '__return_true',
        'args' => [
            'token' => [
                'required' => true,
                'type' => 'string',
            ],
        ]
    ]);
    register_rest_route('2fa/v1', '/pgp_verify', [
        'methods' => 'POST',
        'callback' => 'drk_pgp_verify',
        'permission_callback' => '__return_true',
        'args' => [
            'token' => [
                'required' => true,
                'type' => 'string',
            ],
            'decripted_code' => [
                'required' => true,
                'type' => 'string'
            ]
        ]
    ]);
}
add_filter('jwt_auth_token_before_dispatch', 'check_pgp_is_enable', 10, 2);
function check_pgp_is_enable($data, $user)
{
    $otpSecret = get_user_meta($user->ID, 'drk_pgp_is_enabled', true);

    if ($otpSecret == "false" || !$otpSecret) {
        return $data;
    }

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

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

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

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