<?php

declare(strict_types=1);

require DENTAL_ROOT . '/app/bootstrap.php';
require_documentation_schema();
require DENTAL_ROOT . '/app/layout.php';

$token=(string)($_GET['token']??$_POST['token']??'');
$hash=hash('sha256',$token);
$guardianSelect=schema_column_exists(table('patient_portal_invites'),'guardian_id')
    ? ',i.guardian_id,g.name guardian_name,g.email guardian_email,g.verification_status guardian_status,g.authorized_to_consent,g.authorized_to_receive_records'
    : ',NULL guardian_id,NULL guardian_name,NULL guardian_email,NULL guardian_status,0 authorized_to_consent,0 authorized_to_receive_records';
$guardianJoin=schema_column_exists(table('patient_portal_invites'),'guardian_id')
    ? ' LEFT JOIN `' . table('patient_guardians') . '` g ON g.id=i.guardian_id AND g.patient_id=i.patient_id'
    : '';
$stmt=db()->prepare('SELECT i.*,p.first_name,p.last_name,p.email patient_email'.$guardianSelect.' FROM `' . table('patient_portal_invites') . '` i JOIN `' . table('patients') . '` p ON p.id=i.patient_id'.$guardianJoin.' WHERE i.token_hash=? AND i.used_at IS NULL AND i.expires_at>NOW() ORDER BY i.id DESC LIMIT 1');
$stmt->execute([$hash]);
$invite=$stmt->fetch();
$error='';

if($_SERVER['REQUEST_METHOD']==='POST'&&$invite){
    verify_csrf();
    $password=(string)($_POST['password']??'');
    if(strlen($password)<10)$error='Use at least 10 characters.';
    elseif($password!==($_POST['password_confirmation']??''))$error='The passwords do not match.';
    else{
        $pdo=db();$pdo->beginTransaction();
        try{
            $guardianId=(int)($invite['guardian_id']??0);
            $isGuardian=$guardianId>0;
            if($isGuardian){
                if(!patient_portal_account_patient_schema_ready())throw new RuntimeException('The clinic must apply Version 0.5.9.8.4 before guardian access can be activated.');
                if((string)($invite['guardian_status']??'')!=='verified'||empty($invite['authorized_to_receive_records']))throw new RuntimeException('Guardian record access is not currently verified and authorized. Contact the clinic.');
                if(strtolower(trim((string)$invite['email']))!==strtolower(trim((string)($invite['guardian_email']??''))))throw new RuntimeException('The invitation no longer matches the verified guardian email. Contact the clinic.');
            }
            else {
                if (strtolower(trim((string)$invite['email'])) !== strtolower(trim((string)($invite['patient_email']??'')))) {
                    throw new RuntimeException('The invitation no longer matches the email saved in the patient record. Contact the clinic for a new invitation.');
                }
            }

            $accountStmt=$pdo->prepare('SELECT id,password_hash,status FROM `' . table('patient_portal_accounts') . '` WHERE LOWER(email)=LOWER(?) LIMIT 1 FOR UPDATE');
            $accountStmt->execute([(string)$invite['email']]);
            $existingAccount=$accountStmt->fetch()?:null;
            $accountId=(int)($existingAccount['id']??0);
            if($accountId>0 && (string)($existingAccount['status']??'')==='active' && !empty($existingAccount['password_hash'])){
                if(!password_verify($password,(string)$existingAccount['password_hash']))throw new RuntimeException('This email already has an active portal account. Enter its existing password to link this patient or dependent.');
                $pdo->prepare('UPDATE `' . table('patient_portal_accounts') . '` SET patient_id=COALESCE(patient_id,?),updated_at=NOW() WHERE id=?')->execute([(int)$invite['patient_id'],$accountId]);
            }elseif($accountId>0){
                $passwordHash=password_hash($password,PASSWORD_DEFAULT);
                $pdo->prepare('UPDATE `' . table('patient_portal_accounts') . '` SET password_hash=?,status="active",patient_id=COALESCE(patient_id,?),updated_at=NOW() WHERE id=?')->execute([$passwordHash,(int)$invite['patient_id'],$accountId]);
            }else{
                $passwordHash=password_hash($password,PASSWORD_DEFAULT);
                $pdo->prepare('INSERT INTO `' . table('patient_portal_accounts') . '` (patient_id,email,password_hash,status,created_at) VALUES (?,?,?,"active",NOW())')->execute([(int)$invite['patient_id'],strtolower(trim((string)$invite['email'])),$passwordHash]);
                $accountId=(int)$pdo->lastInsertId();
            }

            if(patient_portal_account_patient_schema_ready()){
                $isSelf=$isGuardian?0:1;
                $canManage=$isGuardian?(int)!empty($invite['authorized_to_consent']):1;
                $canHealth=$canManage;
                $pdo->prepare('INSERT INTO `' . table('patient_portal_account_patients') . '` (account_id,patient_id,guardian_id,is_self,can_view_records,can_manage_appointments,can_submit_health,status,authorized_at,authorized_by,created_at) VALUES (?,?,?,?,1,?,?,"active",NOW(),?,NOW()) ON DUPLICATE KEY UPDATE guardian_id=VALUES(guardian_id),is_self=VALUES(is_self),can_view_records=1,can_manage_appointments=VALUES(can_manage_appointments),can_submit_health=VALUES(can_submit_health),status="active",authorized_at=NOW(),authorized_by=VALUES(authorized_by),revoked_at=NULL,updated_at=NOW()')
                    ->execute([$accountId,(int)$invite['patient_id'],$guardianId?:null,$isSelf,$canManage,$canHealth,(int)($invite['created_by']??0)?:null]);
            }
            $pdo->prepare('UPDATE `' . table('patient_portal_invites') . '` SET used_at=NOW(),updated_at=NOW() WHERE id=? AND used_at IS NULL')->execute([(int)$invite['id']]);
            $pdo->commit();
            flash('success',$isGuardian?'Your guardian portal account is active and the authorized dependent has been linked.':'Your patient portal account is active.');
            header('Location: ' . dental_clean_url('patient-login.php?activated=1'), true, 303);exit;
        }catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();$error=$e->getMessage();}
    }
}

render_header('Activate Patient Portal',true);render_public_nav();
?>
<main class="portal-main"><section class="card portal-login-card"><?php if(!$invite):?><h1>Invitation unavailable</h1><p>This activation link is invalid, expired, or already used. Contact the clinic for a new invitation.</p><?php else:?><h1>Welcome, <?=e((string)($invite['guardian_name']?:$invite['first_name']))?></h1><p>Create a password for <?=e((string)$invite['email'])?><?php if(!empty($invite['guardian_id'])):?> to access the authorized record of <?=e(trim((string)$invite['first_name'].' '.(string)$invite['last_name']))?><?php endif;?>.</p><?php if($error):?><div class="alert error"><?=e($error)?></div><?php endif;?><form method="post" class="form-grid"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="token" value="<?=e($token)?>"><label class="wide">Password<input type="password" name="password" minlength="10" required></label><label class="wide">Confirm password<input type="password" name="password_confirmation" minlength="10" required></label><button class="btn primary">Activate portal</button></form><?php endif;?></section></main>
<?php render_public_footer();render_footer(true); ?>
