<?php

declare(strict_types=1);
require DENTAL_ROOT . '/app/bootstrap.php';
require_login();
require DENTAL_ROOT . '/app/layout.php';

$pdo = db();
$user = current_user();
$userId = (int)($user['id'] ?? 0);
$error = '';
$structuredReady = schema_column_exists(table('users'), 'first_name') && schema_column_exists(table('users'), 'middle_name') && schema_column_exists(table('users'), 'last_name');
$contactReady = schema_column_exists(table('users'), 'contact_number');
$jobTitleReady = schema_column_exists(table('users'), 'job_title');
$addressReady = schema_column_exists(table('users'), 'address');
$emergencyReady = schema_column_exists(table('users'), 'emergency_contact_name') && schema_column_exists(table('users'), 'emergency_contact_phone');
$completionReady = schema_column_exists(table('users'), 'profile_completed_at');
$mfaReady = function_exists('dental_mfa_schema_ready') && dental_mfa_schema_ready();
$mfaPrerequisites = function_exists('dental_mfa_prerequisites_status')
    ? dental_mfa_prerequisites_status()
    : [
        'ready' => $mfaReady && extension_loaded('openssl'),
        'schema_ready' => $mfaReady,
        'openssl_ready' => extension_loaded('openssl'),
        'application_key_ready' => false,
        'reason' => $mfaReady ? 'application_key_unavailable' : 'schema_unavailable',
    ];
$mfaOperationalReady = !empty($mfaPrerequisites['ready']);

function my_profile_select_columns(): string
{
    $columns = 'u.id,u.branch_id,u.role_id,u.name,u.email,u.status,u.email_verified_at,u.last_login_at,u.must_change_password,r.code role_code,r.name role_name,b.name branch_name';
    $optional = [
        'first_name' => 'u.first_name',
        'middle_name' => 'u.middle_name',
        'last_name' => 'u.last_name',
        'contact_number' => 'u.contact_number',
        'job_title' => 'u.job_title',
        'address' => 'u.address',
        'emergency_contact_name' => 'u.emergency_contact_name',
        'emergency_contact_phone' => 'u.emergency_contact_phone',
        'profile_completed_at' => 'u.profile_completed_at',
        'employee_no' => 'u.employee_no',
    ];
    foreach ($optional as $alias => $expr) {
        $columns .= schema_column_exists(table('users'), $alias) ? ',' . $expr : ',NULL ' . $alias;
    }
    return $columns;
}

function my_profile_role_rows(PDO $pdo, int $userId, array $profile): array
{
    if ($userId <= 0) return [];
    if (user_role_assignments_schema_ready()) {
        $stmt = $pdo->prepare(
            'SELECT r.code,r.name,ura.assignment_type,ura.status FROM `' . table('user_role_assignments') . '` ura '
            . 'JOIN `' . table('roles') . '` r ON r.id=ura.role_id '
            . 'WHERE ura.user_id=? AND ura.status="active" ORDER BY FIELD(ura.assignment_type,"primary","secondary"), r.name'
        );
        $stmt->execute([$userId]);
        $rows = $stmt->fetchAll();
        if ($rows) return $rows;
    }
    return [[
        'code' => (string)($profile['role_code'] ?? actual_role()),
        'name' => (string)($profile['role_name'] ?? role_profile(actual_role())['name']),
        'assignment_type' => 'primary',
        'status' => 'active',
    ]];
}

function my_profile_is_complete(array $profile, bool $contactReady): bool
{
    $first = trim((string)($profile['first_name'] ?? ''));
    $last = trim((string)($profile['last_name'] ?? ''));
    $email = trim((string)($profile['email'] ?? ''));
    $contact = trim((string)($profile['contact_number'] ?? ''));
    return $first !== '' && $last !== '' && $email !== '' && (!$contactReady || $contact !== '');
}

$select = my_profile_select_columns();
$load = static function () use ($pdo, $userId, $select): array {
    $stmt = $pdo->prepare('SELECT ' . $select . ' FROM `' . table('users') . '` u JOIN `' . table('roles') . '` r ON r.id=u.role_id LEFT JOIN `' . table('branches') . '` b ON b.id=u.branch_id WHERE u.id=? LIMIT 1');
    $stmt->execute([$userId]);
    $row = $stmt->fetch();
    if (!$row) throw new RuntimeException('Your account profile could not be loaded. Sign out and sign in again.');
    return $row;
};
$profile = $load();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    try {
        verify_csrf();
        $action = (string)($_POST['action'] ?? 'update_profile');
        if (app_demo_read_only()) throw new RuntimeException('The demo clinic is read-only. Profile changes are disabled.');

        if ($action === 'update_profile') {
            if (!$structuredReady) throw new RuntimeException('The structured staff-profile update is pending. Ask the Superuser to open System Setup → Updates & Database.');
            $first = trim((string)($_POST['first_name'] ?? ''));
            $middle = trim((string)($_POST['middle_name'] ?? ''));
            $last = trim((string)($_POST['last_name'] ?? ''));
            $contact = trim((string)($_POST['contact_number'] ?? ''));
            $address = trim((string)($_POST['address'] ?? ''));
            $emergencyName = trim((string)($_POST['emergency_contact_name'] ?? ''));
            $emergencyPhone = trim((string)($_POST['emergency_contact_phone'] ?? ''));
            if ($first === '' || $last === '') throw new RuntimeException('First name and last name are required.');
            if ($contactReady && $contact === '') throw new RuntimeException('Contact number is required to complete your staff profile.');
            $name = person_name_from_parts($first, $middle, $last);
            $sets = ['name=?','first_name=?','middle_name=?','last_name=?'];
            $params = [$name,$first,$middle !== '' ? $middle : null,$last];
            if ($contactReady) { $sets[] = 'contact_number=?'; $params[] = $contact !== '' ? $contact : null; }
            if ($addressReady) { $sets[] = 'address=?'; $params[] = $address !== '' ? $address : null; }
            if ($emergencyReady) { $sets[] = 'emergency_contact_name=?'; $params[] = $emergencyName !== '' ? $emergencyName : null; $sets[] = 'emergency_contact_phone=?'; $params[] = $emergencyPhone !== '' ? $emergencyPhone : null; }
            if ($completionReady) { $sets[] = 'profile_completed_at=?'; $params[] = ($first !== '' && $last !== '' && (!$contactReady || $contact !== '')) ? date('Y-m-d H:i:s') : null; }
            $sets[] = 'updated_at=NOW()';
            $params[] = $userId;
            $pdo->beginTransaction();
            $pdo->prepare('UPDATE `' . table('users') . '` SET ' . implode(',', $sets) . ' WHERE id=?')->execute($params);
            if (has_role('dentist') && schema_table_exists(table('dentist_profiles'))) {
                $pdo->prepare('UPDATE `' . table('dentist_profiles') . '` SET display_name=?,updated_at=NOW() WHERE user_id=?')->execute([$name,$userId]);
            }
            $pdo->commit();
            $_SESSION['user']['name'] = $name;
            audit('my_profile_updated', 'user', $userId, ['profile_completed' => true]);
            flash('success', 'Your personal and contact details were updated. Work assignment, roles, and permissions were not changed.');
            header('Location: my_profile.php');
            exit;
        }

        if ($action === 'change_password') {
            $current = (string)($_POST['current_password'] ?? '');
            $new = (string)($_POST['new_password'] ?? '');
            $confirm = (string)($_POST['new_password_confirmation'] ?? '');
            if (strlen($new) < 10) throw new RuntimeException('Use a new password containing at least 10 characters.');
            if ($new !== $confirm) throw new RuntimeException('The new passwords do not match.');
            $stmt = $pdo->prepare('SELECT password_hash FROM `' . table('users') . '` WHERE id=? LIMIT 1');
            $stmt->execute([$userId]);
            $hash = (string)$stmt->fetchColumn();
            if ($hash === '' || !password_verify($current, $hash)) throw new RuntimeException('The current password is incorrect.');
            $pdo->prepare('UPDATE `' . table('users') . '` SET password_hash=?,must_change_password=0,updated_at=NOW() WHERE id=?')->execute([password_hash($new, PASSWORD_DEFAULT), $userId]);
            if (function_exists('dental_security_revoke_user_sessions')) dental_security_revoke_user_sessions($userId, 'password_changed', true);
            audit('my_profile_password_changed', 'user', $userId);
            flash('success', 'Your password was updated. Other signed-in devices were revoked.');
            header('Location: my_profile.php');
            exit;
        }

        if ($action === 'begin_mfa') {
            if (!$mfaOperationalReady) {
                $reason = (string)($mfaPrerequisites['reason'] ?? '');
                throw new RuntimeException(match ($reason) {
                    'schema_unavailable' => 'Apply or repair the v0.9.0.3 database update before setting up MFA.',
                    'openssl_unavailable' => 'Enable the PHP OpenSSL extension before setting up MFA.',
                    'application_key_unavailable' => 'Restore a valid application encryption key before setting up MFA.',
                    default => 'MFA setup is not operational on this installation.',
                });
            }
            if (dental_mfa_user_enabled($userId)) throw new RuntimeException('MFA is already enabled for this account.');
            $current = (string)($_POST['current_password'] ?? '');
            $stmt = $pdo->prepare('SELECT password_hash FROM `' . table('users') . '` WHERE id=? LIMIT 1');
            $stmt->execute([$userId]);
            $hash = (string)$stmt->fetchColumn();
            if ($hash === '' || !password_verify($current, $hash)) throw new RuntimeException('The current password is incorrect.');
            dental_mfa_begin_enrollment($userId, (string)$profile['email']);
            flash('success', 'Authenticator setup started. Enter the displayed secret in your authenticator app, then verify the current code.');
            header('Location: my_profile.php?security=1&enroll_mfa=1');
            exit;
        }

        if ($action === 'confirm_mfa') {
            $codes = dental_mfa_confirm_enrollment($userId, (string)($_POST['mfa_code'] ?? ''));
            $_SESSION['mfa_recovery_codes_once'] = $codes;
            if (function_exists('dental_security_revoke_user_sessions')) dental_security_revoke_user_sessions($userId, 'mfa_enabled', true);
            audit('my_profile_mfa_enabled', 'user', $userId);
            header('Location: my_profile.php?security=1&mfa_saved=1');
            exit;
        }

        if ($action === 'cancel_mfa_enrollment') {
            unset($_SESSION['mfa_enrollment']);
            $bootstrapAccess = function_exists('dental_mfa_bootstrap_access_allowed')
                && dental_mfa_bootstrap_access_allowed((array)current_user());
            if ($bootstrapAccess) {
                flash('warning', 'MFA enrollment was paused. Superuser recovery access remains available until the first working authenticator is enrolled.');
                header('Location: role_switch.php?return_primary=1');
            } else {
                flash('success', 'MFA enrollment was cancelled.');
                header('Location: my_profile.php?security=1');
            }
            exit;
        }

        if ($action === 'disable_mfa') {
            dental_mfa_disable($userId, (string)($_POST['current_password'] ?? ''), (string)($_POST['mfa_code'] ?? ''));
            if (function_exists('dental_security_revoke_user_sessions')) dental_security_revoke_user_sessions($userId, 'mfa_disabled', true);
            audit('my_profile_mfa_disabled', 'user', $userId);
            flash('success', 'Two-step verification was disabled for this account.');
            header('Location: my_profile.php?security=1');
            exit;
        }
        throw new RuntimeException('Unsupported profile action.');
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        $error = $e->getMessage();
        $profile = $load();
    }
}

$roleRows = my_profile_role_rows($pdo, $userId, $profile);
$complete = my_profile_is_complete($profile, $contactReady);
$isDentist = in_array('dentist', array_map(static fn(array $row): string => (string)$row['code'], $roleRows), true);
$mfaEnabled = $mfaReady && function_exists('dental_mfa_user_enabled') && dental_mfa_user_enabled($userId);
$mfaPending = $mfaReady && function_exists('dental_mfa_pending_enrollment') ? dental_mfa_pending_enrollment($userId) : null;
$mfaRecoveryRemaining = $mfaEnabled && function_exists('dental_mfa_recovery_codes_remaining') ? dental_mfa_recovery_codes_remaining($userId) : 0;
$mfaRecoveryCodes = isset($_SESSION['mfa_recovery_codes_once']) && is_array($_SESSION['mfa_recovery_codes_once']) ? $_SESSION['mfa_recovery_codes_once'] : [];
unset($_SESSION['mfa_recovery_codes_once']);
$mfaRequiredForRole = function_exists('dental_mfa_policy_required_for_user') && dental_mfa_policy_required_for_user((array)current_user());
$mfaBootstrapAccess = false;
$mfaDentistLimitedAccess = false;
$dentistProfessional = null;
if ($isDentist && schema_table_exists(table('dentist_profiles'))) {
    $specialtySelect = schema_table_exists(table('dentist_specialties')) ? ',ds.name specialty_name' : ',NULL specialty_name';
    $specialtyJoin = schema_table_exists(table('dentist_specialties')) ? ' LEFT JOIN `' . table('dentist_specialties') . '` ds ON ds.id=dp.specialty_id ' : ' ';
    $professionalStmt = $pdo->prepare(
        'SELECT dp.professional_title,dp.license_number,dp.license_expiry,dp.profile_status,dp.credential_status,dp.primary_branch_id' . $specialtySelect
        . ' FROM `' . table('dentist_profiles') . '` dp' . $specialtyJoin . 'WHERE dp.user_id=? LIMIT 1'
    );
    $professionalStmt->execute([$userId]);
    $dentistProfessional = $professionalStmt->fetch() ?: null;
}
render_header('Profile Center');
?>
<div class="management-workspace">
<?php if ($error): ?><div class="flash error" data-auto-dismiss="10000"><?=e($error)?></div><?php endif; ?>
<?php if (!$structuredReady || !$contactReady || !$completionReady): ?><div class="alert warning"><strong>Profile update pending.</strong> Ask the Superuser to apply Version 0.5.9.8.74 in System Setup so staff can complete all profile fields.</div><?php endif; ?>
<?php if (isset($_GET['complete']) && !$complete): ?><div class="alert warning"><strong>Complete your profile.</strong> Add your required name and contact details before continuing routine clinic work.</div><?php endif; ?>
<section class="card hero-card">
    <div><span class="eyebrow">One staff identity</span><h2><?=e(user_full_name($profile))?></h2><p><?=e((string)$profile['email'])?> · <?=e((string)($profile['branch_name'] ?: 'All branches'))?></p></div>
    <div class="role-welcome-tools"><span class="badge <?=$complete?'success':''?>"><?=$complete?'Profile complete':'Profile incomplete'?></span></div>
</section>
<section class="card">
    <div class="card-head"><div><h2>Work assignment</h2><p>Administrators manage employee number, position, branch, roles, and account status. These are shown here without creating another editable profile.</p></div><?php if ($isDentist): ?><a class="btn ghost" href="doctor_profile.php">Professional credentials &amp; clinical setup</a><?php endif; ?></div>
    <div class="management-summary">
        <div><span>Employee number</span><strong><?=e((string)($profile['employee_no'] ?: 'Not assigned'))?></strong></div>
        <div><span>Position</span><strong><?=e((string)($profile['job_title'] ?: $profile['role_name']))?></strong></div>
        <div><span>Branch</span><strong><?=e((string)($profile['branch_name'] ?: 'All branches'))?></strong></div>
        <div><span>Account</span><strong><?=e(ucfirst((string)$profile['status']))?></strong></div>
    </div>
    <div class="inline-actions">
        <?php foreach ($roleRows as $roleRow): ?><span class="badge"><?=e((string)$roleRow['name'])?> · <?=e(ucfirst((string)$roleRow['assignment_type']))?></span><?php endforeach; ?>
    </div>
</section>
<section class="card">
    <div class="card-head"><div><h2>Personal and contact details</h2><p>This is the only self-service identity record. Dentist credentials and administrator-controlled employment assignments are separate controls, not duplicate profiles.</p></div></div>
    <form method="post" class="form-grid">
        <input type="hidden" name="csrf" value="<?=e(csrf_token())?>">
        <input type="hidden" name="action" value="update_profile">
        <label>First name<input name="first_name" maxlength="80" value="<?=e((string)($profile['first_name'] ?? ''))?>" required></label>
        <label>Middle name<input name="middle_name" maxlength="80" value="<?=e((string)($profile['middle_name'] ?? ''))?>"></label>
        <label>Last name<input name="last_name" maxlength="80" value="<?=e((string)($profile['last_name'] ?? ''))?>" required></label>
        <label>Email<input value="<?=e((string)$profile['email'])?>" readonly><small>Email is an account identity. Ask an Administrator to correct invitation email before activation.</small></label>
        <label>Contact number<input name="contact_number" maxlength="50" value="<?=e((string)($profile['contact_number'] ?? ''))?>" <?=$contactReady?'required':'disabled'?>></label>
        <label class="wide">Address<textarea name="address" <?=$addressReady?'':'disabled'?>><?=e((string)($profile['address'] ?? ''))?></textarea></label>
        <label>Emergency contact name<input name="emergency_contact_name" maxlength="150" value="<?=e((string)($profile['emergency_contact_name'] ?? ''))?>" <?=$emergencyReady?'':'disabled'?>></label>
        <label>Emergency contact phone<input name="emergency_contact_phone" maxlength="50" value="<?=e((string)($profile['emergency_contact_phone'] ?? ''))?>" <?=$emergencyReady?'':'disabled'?>></label>
        <button class="btn primary" <?=app_demo_read_only()?'disabled':''?>>Save my profile</button>
    </form>
</section>
<?php if ($isDentist): ?>
<section class="card">
    <div class="card-head"><div><h2>Dentist professional record</h2><p>License, specialty, documents, clinical privileges, public biography, signatures, and treatment preferences belong to the professional record—not a second personal profile.</p></div><a class="btn primary" href="doctor_profile.php">Open professional setup</a></div>
    <?php if ($dentistProfessional): ?>
    <div class="management-summary">
        <div><span>Specialty</span><strong><?=e((string)($dentistProfessional['specialty_name'] ?: 'General / not specified'))?></strong></div>
        <div><span>License</span><strong><?=e((string)($dentistProfessional['license_number'] ?: 'Not entered'))?></strong></div>
        <div><span>Credential review</span><strong><?=e(ucfirst((string)($dentistProfessional['credential_status'] ?: 'pending')))?></strong></div>
        <div><span>Professional record</span><strong><?=e(ucfirst((string)($dentistProfessional['profile_status'] ?: 'draft')))?></strong></div>
    </div>
    <?php else: ?><div class="alert warning"><strong>Professional setup is incomplete.</strong> Open the professional setup page to add license and dental-practice information.</div><?php endif; ?>
</section>
<?php endif; ?>
<section class="card" id="account-security">
    <div class="card-head"><div><h2>Two-step verification</h2><p>Optional extra protection for this account. It does not change role permissions or block normal clinic work.</p></div><span class="badge <?=$mfaEnabled?'success':''?>"><?=$mfaEnabled?'Enabled':'Optional'?></span></div>
    <?php if(!$mfaOperationalReady):?>
        <?php $mfaReason=(string)($mfaPrerequisites['reason']??''); ?>
        <div class="alert warning"><strong>MFA setup is temporarily unavailable.</strong>
            <?php if($mfaReason==='schema_unavailable'):?>The v0.9.0.3 MFA tables are missing or incomplete. Open Updates &amp; Database and repair the release state.
            <?php elseif($mfaReason==='openssl_unavailable'):?>The PHP OpenSSL extension is disabled. Enable it before enrolling an authenticator.
            <?php elseif($mfaReason==='application_key_unavailable'):?>The application encryption key is missing or invalid. Restore a valid <code>app.key</code> before enrollment.
            <?php else:?>The installation cannot safely store and verify MFA secrets yet.<?php endif;?>
        </div>
        <?php if($mfaBootstrapAccess):?><p><a class="btn ghost" href="system_setup.php?tab=updates">Open Updates &amp; Database</a></p><?php endif;?>
    <?php elseif($mfaRecoveryCodes):?>
        <div class="alert warning"><strong>Save these recovery codes now.</strong> Each code works once. They will not be shown again.</div>
        <div class="management-compact-list"><?php foreach($mfaRecoveryCodes as $recoveryCode):?><code><?=e((string)$recoveryCode)?></code><?php endforeach;?></div>
        <p><small>Store the codes outside this server in a secure password manager or printed emergency record.</small></p>
    <?php elseif($mfaPending):?>
        <?php $pendingSecret=(string)($mfaPending['secret']??''); $issuer=preg_replace('/[^A-Za-z0-9 ._-]/','',(string)app_config('app.name','DentalCare'))?:'DentalCare'; $pendingUri='otpauth://totp/'.rawurlencode($issuer.':'.strtolower((string)$profile['email'])).'?secret='.rawurlencode($pendingSecret).'&issuer='.rawurlencode($issuer).'&algorithm=SHA1&digits=6&period=30'; ?>
        <div class="alert info"><strong>Step 1:</strong> Add an account in your authenticator app using the secret below. Keep this secret private.</div>
        <dl><dt>Account</dt><dd><?=e((string)$profile['email'])?></dd><dt>Secret key</dt><dd><code><?=e($pendingSecret)?></code></dd><dt>Setup URI</dt><dd><code class="wrap-code"><?=e($pendingUri)?></code></dd></dl>
        <form method="post" class="form-grid compact-form" autocomplete="off">
            <input type="hidden" name="csrf" value="<?=e(csrf_token())?>">
            <label>Current six-digit code<input name="mfa_code" inputmode="numeric" pattern="[0-9]{6}" maxlength="6" autocomplete="one-time-code" required autofocus></label>
            <button class="btn primary" name="action" value="confirm_mfa">Verify and enable MFA</button>
            <button class="btn ghost" name="action" value="cancel_mfa_enrollment" formnovalidate>Cancel setup</button>
        </form>
    <?php elseif($mfaEnabled):?>
        <div class="alert success"><strong>MFA is active.</strong> Your password must be followed by an authenticator or unused recovery code at sign-in.</div>
        <p><strong><?=$mfaRecoveryRemaining?></strong> unused recovery code<?=$mfaRecoveryRemaining===1?'':'s'?> remaining.</p>
        <details class="compact-details"><summary>Disable MFA</summary>
            <form method="post" class="form-grid compact-form" autocomplete="off">
                <input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="disable_mfa">
                <label>Current password<input type="password" name="current_password" autocomplete="current-password" required></label>
                <label>Authenticator or recovery code<input name="mfa_code" autocomplete="one-time-code" required maxlength="20"></label>
                <button class="btn ghost" data-confirm="Disable two-step verification for this account?">Disable two-step verification</button>
            </form>
        </details>
    <?php else:?>
        <form method="post" class="form-grid compact-form" autocomplete="off">
            <input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="begin_mfa">
            <label>Confirm current password<input type="password" name="current_password" autocomplete="current-password" required></label>
            <button class="btn primary">Add two-step verification</button>
        </form>
    <?php endif;?>
</section>
<section class="card">
    <div class="card-head"><div><h2>Password</h2><p>Change only your own password. Role, branch, and status remain protected staff-management controls.</p></div></div>
    <form method="post" class="form-grid compact-form">
        <input type="hidden" name="csrf" value="<?=e(csrf_token())?>">
        <input type="hidden" name="action" value="change_password">
        <label>Current password<input type="password" name="current_password" autocomplete="current-password" required></label>
        <label>New password<input type="password" name="new_password" minlength="10" autocomplete="new-password" required></label>
        <label>Confirm new password<input type="password" name="new_password_confirmation" minlength="10" autocomplete="new-password" required></label>
        <button class="btn ghost" <?=app_demo_read_only()?'disabled':''?>>Change password</button>
    </form>
</section>
</div>
<?php render_footer();
