<?php

include('../functions.php');
include('../helpers/passkeys.php');

sendy_passkeys_ensure_table();

$action = isset($_GET['action']) ? $_GET['action'] : '';
$post = sendy_passkeys_read_json();
$redirect_to = isset($post['redirect']) ? sendy_passkeys_json_safe_redirect($post['redirect']) : '';

try
{
if($action=='exists')
{
	$email = isset($post['email']) ? mysqli_real_escape_string($mysqli, trim($post['email'])) : '';
	if($email=='') sendy_passkeys_json(array('success'=>true, 'has_passkey'=>false));

	$app_id_line = null;
	if(CURRENT_DOMAIN!=APP_PATH_DOMAIN)
	{
		$q = 'SELECT id FROM apps WHERE custom_domain = "'.mysqli_real_escape_string($mysqli, CURRENT_DOMAIN).'" LIMIT 1';
		$r = mysqli_query($mysqli, $q);
		if($r && mysqli_num_rows($r) > 0)
		{
			$row = mysqli_fetch_array($r);
			$app_id_line = 'AND login.app = '.(int)$row['id'];
		}
	}

	$q = 'SELECT passkeys.id
		  FROM passkeys, login
		  WHERE passkeys.userID = login.id AND login.username = "'.$email.'" '.$app_id_line.'
		  LIMIT 1';
	$r = mysqli_query($mysqli, $q);
	sendy_passkeys_json(array('success'=>true, 'has_passkey'=>$r && mysqli_num_rows($r)>0));
}
else if($action=='start')
{
	$email = isset($post['email']) ? mysqli_real_escape_string($mysqli, trim($post['email'])) : '';
	if($email=='') sendy_passkeys_error('Please enter your email address.');

	$app_id_line = null;
	if(CURRENT_DOMAIN!=APP_PATH_DOMAIN)
	{
		$q = 'SELECT id FROM apps WHERE custom_domain = "'.mysqli_real_escape_string($mysqli, CURRENT_DOMAIN).'" LIMIT 1';
		$r = mysqli_query($mysqli, $q);
		if($r && mysqli_num_rows($r) > 0)
		{
			$row = mysqli_fetch_array($r);
			$app_id_line = 'AND app = '.(int)$row['id'];
		}
	}

	$q = 'SELECT id FROM login WHERE username = "'.$email.'" '.$app_id_line.' ORDER BY id ASC LIMIT 1';
	$r = mysqli_query($mysqli, $q);
	if(!$r || mysqli_num_rows($r)==0) sendy_passkeys_error('No passkey is registered for this email address.');
	$row = mysqli_fetch_array($r);
	$userID = (int)$row['id'];

	$credential_ids = array();
	$q = 'SELECT credential_id FROM passkeys WHERE userID = '.$userID;
	$r = mysqli_query($mysqli, $q);
	if($r)
	{
		while($row = mysqli_fetch_array($r))
			$credential_ids[] = base64_decode($row['credential_id']);
	}
	if(count($credential_ids)==0) sendy_passkeys_error('No passkey is registered for this email address.');

	$WebAuthn = sendy_passkeys_webauthn();
	$args = $WebAuthn->getGetArgs($credential_ids, 60, true, true, true, true, true, true);

	$_SESSION['passkey_login_challenge'] = $WebAuthn->getChallenge()->getBinaryString();
	$_SESSION['passkey_login_userID'] = $userID;
	$_SESSION['passkey_login_redirect'] = $redirect_to;

	sendy_passkeys_json($args);
}
else if($action=='finish')
{
	$challenge = sendy_passkeys_session_challenge('passkey_login_challenge');
	if($challenge===null || !isset($_SESSION['passkey_login_userID']))
		sendy_passkeys_error('Passkey login expired. Please try again.');

	$userID = (int)$_SESSION['passkey_login_userID'];
	$id_binary = sendy_passkeys_b64decode(isset($post['id']) ? $post['id'] : '');
	$credential_id_hash = mysqli_real_escape_string($mysqli, hash('sha256', $id_binary));

	$q = 'SELECT passkeys.id, passkeys.credential_public_key, passkeys.signature_counter, login.username, login.password, login.tied_to, login.app, login.auth_enabled, login.auth_key
		  FROM passkeys, login
		  WHERE passkeys.userID = login.id AND passkeys.userID = '.$userID.' AND passkeys.credential_id_hash = "'.$credential_id_hash.'"
		  LIMIT 1';
	$r = mysqli_query($mysqli, $q);
	if(!$r || mysqli_num_rows($r)==0) sendy_passkeys_error('Passkey not found.');
	$row = mysqli_fetch_array($r);

	$WebAuthn = sendy_passkeys_webauthn();
	$WebAuthn->processGet(
		sendy_passkeys_b64decode(isset($post['clientDataJSON']) ? $post['clientDataJSON'] : ''),
		sendy_passkeys_b64decode(isset($post['authenticatorData']) ? $post['authenticatorData'] : ''),
		sendy_passkeys_b64decode(isset($post['signature']) ? $post['signature'] : ''),
		$row['credential_public_key'],
		$challenge,
		$row['signature_counter']===null ? null : (int)$row['signature_counter'],
		true
	);

	$new_counter = $WebAuthn->getSignatureCounter();
	$counter_sql = $new_counter===null ? 'signature_counter = NULL' : 'signature_counter = '.(int)$new_counter;
	mysqli_query($mysqli, 'UPDATE passkeys SET '.$counter_sql.', last_used = '.time().' WHERE id = '.(int)$row['id']);

	$q = 'SELECT auth_salt FROM login WHERE id = 1 LIMIT 1';
	$r = mysqli_query($mysqli, $q);
	$auth_salt = '';
	if($r && mysqli_num_rows($r)>0)
	{
		$salt_row = mysqli_fetch_array($r);
		$auth_salt = $salt_row['auth_salt'];
	}

	$_SESSION['auth_key'] = $row['auth_key'];
	$_SESSION['restricted_to_app'] = $row['app'];
	$_SESSION['userID'] = $userID;

	$redirect_to = isset($_SESSION['passkey_login_redirect']) ? $_SESSION['passkey_login_redirect'] : '';
	unset($_SESSION['passkey_login_challenge'], $_SESSION['passkey_login_userID'], $_SESSION['passkey_login_redirect']);

	remember_login_email($row['username']);
	sendy_passkeys_set_login_cookie($userID, $row['username'], $row['password'], $auth_salt);
	sendy_passkeys_json(array('success'=>true, 'redirect'=>sendy_passkeys_redirect($redirect_to, $row['tied_to'], $_SESSION['restricted_to_app'])));
}

sendy_passkeys_error('Invalid passkey action.');
}
catch(Exception $e)
{
	sendy_passkeys_error($e->getMessage());
}
