<%- include('top') %>

<script type="text/javascript">
	app.auth.forceLogin();
	var currentUser;
	var isOwnProfile = !location.pathname.includes('/users/');

	function renderProfile(user){
		user.createTimestamp = moment(user.createTimestamp, "YYYYMMDDHHmmssZ").fromNow();
		user.modifyTimestamp = moment(user.modifyTimestamp, "YYYYMMDDHHmmssZ").fromNow();
		user.managerUids = (user.manager || []).map(app.user.dnToUid);
		$('#profile-uid-header').text(user.uid);
		$.scope.user.update(user);
	};

	async function renderUserGroups(user){
		try{
			let res = await app.api.get('group/?detail=true&member='+user.uid);
			$.scope.mygroups.empty();
			$.scope.mygroups.push(...res.results);
		}catch(error){
			console.error('renderUserGroups error:', error)
		}
	}

	async function removeFromGroup(cn, btn){
		const $row = $(btn).closest('tr');
		const confirmed = await app.messages.confirm(`Remove ${currentUser.uid} from "${cn}"?`, $row, 'warning');
		if (!confirmed) return;
		app.api.delete('group/' + encodeURIComponent(cn) + '/' + encodeURIComponent(currentUser.uid), function(error, data){
			if(error){ app.messages.action((data && data.message) || 'Failed to remove from group', $row, 'danger'); return; }
			$.scope.mygroups.remove('cn', cn);
		});
	}

	var addGroupSelect;
	async function addToGroups(btn){
		const cns = addGroupSelect.get();
		if(!cns.length) return;
		const $card = $(btn).closest('.card-body');
		for(const cn of cns){
			await new Promise(function(resolve){
				app.api.put('group/' + encodeURIComponent(cn) + '/' + encodeURIComponent(currentUser.uid), {}, function(error, data){
					if(error) app.messages.action((data && data.message) || `Failed to add to "${cn}"`, $card, 'danger');
					resolve();
				});
			});
		}
		addGroupSelect.clear();
		renderUserGroups(currentUser);
	}

	async function renderPersonalGroupMembers(user){
		try{
			let res = await app.api.get('user/' + user.uid + '/group-members');
			$.scope.personalGroupMembers.empty();
			$.scope.personalGroupMembers.push(...(res.results || []).map(uid => ({uid})));
		}catch(error){
			console.error('renderPersonalGroupMembers error:', error)
		}
	}

	async function removePersonalGroupMember(memberUid, btn){
		const $row = $(btn).closest('tr');
		const confirmed = await app.messages.confirm(`Remove ${memberUid} from ${currentUser.uid}'s group?`, $row, 'warning');
		if (!confirmed) return;
		app.api.delete('user/' + encodeURIComponent(currentUser.uid) + '/group-member/' + encodeURIComponent(memberUid), function(error, data){
			if(error){ app.messages.action((data && data.message) || 'Failed to remove from group', $row, 'danger'); return; }
			$.scope.personalGroupMembers.remove('uid', memberUid);
		});
	}

	var addPersonalGroupMemberSelect;
	async function addPersonalGroupMembers(btn){
		const uids = addPersonalGroupMemberSelect.get();
		if(!uids.length) return;
		const $card = $(btn).closest('.card-body');
		for(const uid of uids){
			await new Promise(function(resolve){
				app.api.put('user/' + encodeURIComponent(currentUser.uid) + '/group-member/' + encodeURIComponent(uid), {}, function(error, data){
					if(error) app.messages.action((data && data.message) || `Failed to add "${uid}"`, $card, 'danger');
					resolve();
				});
			});
		}
		addPersonalGroupMemberSelect.clear();
		renderPersonalGroupMembers(currentUser);
	}

	async function renderMyServices(){
		try{
			let res = await app.api.get('discovery/me');
			res.results.forEach(r => {
				r.resolvedAddress = r.resolvedAddress
					|| (r.metadata && r.metadata.address)
					|| (r.metadata && r.metadata.ip)
					|| 'N/A';
			});
			$.scope.myservices.empty();
			$.scope.myservices.push(...res.results);
		}catch(error){
			console.error('renderMyServices error:', error)
		}
	}

	async function renderMyMetrics(){
		try{
			let uid = currentUser.uid;
			let res = await app.api.get(`metrics/user/${uid}`);
			if (res && res.results && res.results.services) {
				const el = document.getElementById('metrics-user-services');
				if(!el) return;
				el.innerHTML = '';
				const items = res.results.services;
				if (!items || items.length === 0) {
					el.innerHTML = '<li class="list-group-item text-muted">No data available</li>';
					return;
				}
				items.forEach(item => {
					el.innerHTML += `<li class="list-group-item d-flex justify-content-between align-items-center">
						${item.value}
						<span class="badge bg-primary rounded-pill">${item.score}</span>
					</li>`;
				});
			}
		}catch(error){
			console.error('renderMyMetrics error:', error);
			const el = document.getElementById('metrics-user-services');
			if(el) el.innerHTML = '<li class="list-group-item text-danger">Failed to load metrics</li>';
		}
	}

	async function determinUser(){
		if(location.pathname.includes('/users/')){
			let uid = location.pathname.replace('/users/', '');
			return (await app.api.get('user/'+uid)).results;
		}else{
			return await app.auth.asyncUser;
		}
	}

	function editUser(user){
		user = user || currentUser;
		var $profileCard = $('#userProfile');
		var $editCard = $('#editProfile');
		$.scope.editProfile.update(user);
		setTimeout(function(){
			app.ui.userSelect('#edit-manager', {
				name: 'manager',
				values: user.managerUids || [],
				placeholder: 'Type a username…',
			});
			$profileCard.slideUp();
			$editCard.slideDown();
		}, 60);
	}

	function editUserSeccess(data){
		currentUser = data.results;
		renderProfile(currentUser);
		setTimeout(function(){
			$('#editProfile').slideUp();
			$('#userProfile').slideDown()
		}, 60);
	}

	async function toggleActive(uid, active){
		app.user.setActive(uid, active, async function(error, data){
			if(error) return app.messages.toast('Failed to update user status', 'danger');
			currentUser = await determinUser();
			renderProfile(currentUser);
		});
	}

	async function deleteUser(uid, btn){
		const $card = $(btn).closest('.card');
		const confirmed = await app.messages.confirm(`Delete user "${uid}"?`, $card, 'warning');
		if (!confirmed) return;
		app.api.delete('user/' + uid, function(error, data){
			if (error) {
				app.messages.action(data.message || 'Failed to delete user', $card, 'danger');
				return;
			}
			window.location.href = '/users';
		});
	}

	// Password reset modal
	function openPasswordResetModal(){
		app.modal.open({
			title: 'Reset Password for ' + currentUser.uid,
			bodyHtml:
				'<div class="actionMessage mb-3" style="display:none"></div>'
				+ '<form id="passwordResetForm" action="user/' + currentUser.uid + '/password" method="put" onsubmit="formAJAX(this)" evalAJAX="app.modal.close(); app.messages.toast(\'Password updated\', \'success\');">'
				+   '<div class="mb-3">'
				+     '<label class="form-label">New Password</label>'
				+     '<input type="password" class="form-control shadow" name="userPassword" placeholder="8+ chars; mix upper/lower/number/symbol" validate="password">'
				+   '</div>'
				+   '<div class="mb-3">'
				+     '<label class="form-label">Confirm Password</label>'
				+     '<input type="password" class="form-control shadow" name="password" placeholder="Retype password" validate="eq:userPassword">'
				+   '</div>'
				+ '</form>',
			footer: {
				buttonsHtml: '<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>'
					+ '<button type="submit" form="passwordResetForm" class="btn btn-warning"><i class="fa-solid fa-key"></i> Reset Password</button>',
			},
		});
	}

	$(document).ready(async function(){
		currentUser = await determinUser();

		renderProfile(currentUser);
		renderUserGroups(currentUser);
		renderPersonalGroupMembers(currentUser);
		renderMyServices();
		if(!isOwnProfile) {
			renderMyMetrics();
			$('#tab-metrics').parent().show();
		}
		$('#personal-group-uid-label').text(currentUser.uid);

		addGroupSelect = app.ui.groupSelect('#add-group-select', {
			name: 'groups', values: [], placeholder: 'Type a group name…',
		});
		addPersonalGroupMemberSelect = app.ui.userSelect('#add-personal-group-member-select', {
			name: 'members', values: [], placeholder: 'Type a username…',
		});

		if(isOwnProfile){
			$('#own-api-tokens-section').show();
			tableAJAX();
		}
	});
</script>

<div class="container mt-4">
<div class="row" style="display:none">
	<div class="col-12">
		<div id="userProfile" class="shadow-lg card card-default mb-4">
			<div class="card-header shadow d-flex justify-content-between align-items-center">
				<div>
					<i class="fa-regular fa-id-card"></i>
					Profile: <strong id="profile-uid-header"></strong>
				</div>
				<div class="d-flex gap-2">
					<button type="button" onclick="openPasswordResetModal()" class="btn btn-outline-warning btn-sm">
						<i class="fa-solid fa-key"></i> Reset Password
					</button>
					<button type="button" onclick="editUser()" class="btn btn-warning btn-sm">
						<i class="fa-solid fa-user-pen"></i> Edit
					</button>
				</div>
			</div>
			<div class="card-header shadow actionMessage" style="display:none"></div>

			<div class="px-3 pt-3 border-bottom">
				<ul class="nav nav-tabs border-bottom-0" role="tablist">
					<li class="nav-item" role="presentation">
						<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#tab-profile" type="button" role="tab">
							<i class="fa-solid fa-user"></i> Profile
						</button>
					</li>
					<li class="nav-item" role="presentation">
						<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tab-groups" type="button" role="tab">
							<i class="fa-solid fa-users"></i> My Groups
						</button>
					</li>
					<li class="nav-item" role="presentation">
						<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tab-services" type="button" role="tab">
							<i class="fa-solid fa-layer-group"></i> My Services
						</button>
					</li>
					<li class="nav-item" role="presentation" id="tab-metrics-parent" style="display:none">
						<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tab-metrics" type="button" role="tab">
							<i class="fa-solid fa-chart-line"></i> Security & Usage
						</button>
					</li>
					<li class="nav-item" role="presentation">
						<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tab-members" type="button" role="tab">
							<i class="fa-solid fa-people-group"></i> Members of <span id="personal-group-uid-label"></span>'s Group
						</button>
					</li>
				</ul>
			</div>

			<div class="card-body">
				<div class="tab-content">
					<!-- Profile Tab -->
					<div class="tab-pane fade show active" id="tab-profile" role="tabpanel">
						<div jq-repeat="user">
							<div class="row">
								<div class="col-md-6">
									<p><i>Name:</i> <b>{{givenName}} {{sn}}</b></p>
									<p><i>Email:</i> <b>{{mail}}</b>
										{{#emailVerified}}<span class="badge bg-success ms-1"><i class="fa-solid fa-circle-check"></i> Verified</span>{{/emailVerified}}
									</p>
									<p><i>Phone:</i> <b>{{mobile}}</b>
										{{#phoneVerified}}<span class="badge bg-success ms-1"><i class="fa-solid fa-circle-check"></i> Verified</span>{{/phoneVerified}}
									</p>
									<p><i>Location (Site):</i> <b>{{location}}</b></p>
									<p><i>LDAP DN:</i> <b>{{dn}}</b></p>
									<p><i>Home Directory:</i> <b>{{homeDirectory}}</b></p>
								</div>
								<div class="col-md-6">
									<p><i>Login Shell:</i> <b>{{loginShell}}</b></p>
									<p><i>Manager(s):</i>
										{{#managerUids}}<span class="badge bg-secondary me-1">{{.}}</span>{{/managerUids}}
									</p>
									<p><i>Status:</i>
										{{#isActive}}<span class="badge bg-success">Active</span>{{/isActive}}
										{{#isInactive}}<span class="badge bg-danger">Inactive</span>{{/isInactive}}
									</p>
									<p><i>Date of Birth:</i> <b>{{dateOfBirth}}</b></p>
									<p><i>TOS:</i>
										{{#tosAccepted}}<span class="badge bg-success">Accepted</span>{{/tosAccepted}}
										{{#tosNotAccepted}}<span class="badge bg-warning text-dark">Pending</span>{{/tosNotAccepted}}
									</p>
									<p><i>SSH Public Key:</i> <b>{{sshPublicKey}}</b></p>
									<p><i>Unix User ID:</i> <b>{{uidNumber}}</b></p>
									<p><i>Unix Group ID:</i> <b>{{gidNumber}}</b></p>
								</div>
							</div>
							{{#description}}
							<hr>
							<p><i>Description:</i><br>{{description}}</p>
							{{/description}}
							<hr>
							<p class="text-muted small mb-0">
								<i>Joined:</i> <b>{{createTimestamp}}</b> | <i>Edited:</i> <b>{{modifyTimestamp}}</b>
							</p>

							<div class="mt-3 border-top pt-3">
								<h6 class="text-muted">Admin Actions</h6>
								<div class="d-flex gap-2 flex-wrap group-required group-required-app_sso_admin">
									{{#isActive}}
									<button type="button" class="btn btn-outline-warning" title="Deactivate user" onclick="toggleActive('{{uid}}', false)">
										<i class="fa-solid fa-lock"></i> Deactivate
									</button>
									{{/isActive}}
									{{#isInactive}}
									<button type="button" class="btn btn-warning" title="Activate user" onclick="toggleActive('{{uid}}', true)">
										<i class="fa-solid fa-lock-open"></i> Activate
									</button>
									{{/isInactive}}
									<button type="button" class="btn btn-secondary" title="Impersonate this user" onclick="startImpersonate('{{uid}}')">
										<i class="fa-solid fa-user-secret"></i> Impersonate
									</button>
									<button type="button" class="btn btn-danger" onclick="deleteUser('{{uid}}', this)">
										<i class="fa-solid fa-user-slash"></i> Delete User
									</button>
								</div>
							</div>
						</div>
					</div>

					<!-- My Groups Tab -->
					<div class="tab-pane fade" id="tab-groups" role="tabpanel">
						<div class="table-responsive">
							<table class="table table-striped">
								<thead>
									<th>Name</th>
									<th>Description</th>
									<th class="group-required group-required-app_sso_admin text-end">Actions</th>
								</thead>
								<tbody jq-repeat="mygroups">
									<tr>
										<td>{{cn}}</td>
										<td>{{description}}</td>
										<td class="text-end group-required group-required-app_sso_admin">
											<button type="button" class="btn btn-sm btn-outline-danger" title="Remove from group" onclick="removeFromGroup('{{cn}}', this)">
												<i class="fa-solid fa-xmark"></i>
											</button>
										</td>
									</tr>
								</tbody>
							</table>
						</div>
						<div class="group-required group-required-app_sso_admin mt-3">
							<label class="form-label small">Add to group</label>
							<div class="d-flex gap-2 align-items-start">
								<div id="add-group-select" class="flex-grow-1"></div>
								<button type="button" class="btn btn-outline-dark" onclick="addToGroups(this)">Add</button>
							</div>
						</div>
					</div>

					<!-- My Services Tab -->
					<div class="tab-pane fade" id="tab-services" role="tabpanel">
						<div class="table-responsive">
							<table class="table table-striped">
								<thead>
									<th>Name</th>
									<th>Address / IP</th>
									<th>Description</th>
									<th>Kind</th>
								</thead>
								<tbody jq-repeat="myservices">
									<tr>
										<td>{{name}} <small class="text-muted">({{slug}})</small></td>
										<td><a href="{{resolvedAddress}}" target="_blank"><code>{{resolvedAddress}}</code></a></td>
										<td>{{description}}</td>
										<td>
											{{#metadata.isProduction}}<span class="badge bg-danger mb-1">Prod</span><br>{{/metadata.isProduction}}
											<span class="badge bg-secondary">{{kind}}{{#metadata.subType}} ({{metadata.subType}}){{/metadata.subType}}</span>
										</td>
									</tr>
								</tbody>
							</table>
						</div>
					</div>

					<!-- Security & Usage Tab -->
					<div class="tab-pane fade" id="tab-metrics" role="tabpanel">
						<div class="row">
							<div class="col-12">
								<h6 class="text-success"><i class="fa-solid fa-plug"></i> Top Services Used (Last 7 Days)</h6>
								<ul class="list-group list-group-flush border rounded" id="metrics-user-services">
									<li class="list-group-item text-muted">Loading...</li>
								</ul>
							</div>
						</div>
					</div>

					<!-- Members Tab -->
					<div class="tab-pane fade" id="tab-members" role="tabpanel">
						<p class="text-muted small">
							Every account gets a personal Unix group (its primary GID) — add
							other accounts here as supplementary members.
						</p>
						<div class="table-responsive">
							<table class="table table-striped">
								<thead>
									<th>Username</th>
									<th class="text-end">Actions</th>
								</thead>
								<tbody jq-repeat="personalGroupMembers">
									<tr>
										<td>{{uid}}</td>
										<td class="text-end">
											<button type="button" class="btn btn-sm btn-outline-danger" title="Remove from group" onclick="removePersonalGroupMember('{{uid}}', this)">
												<i class="fa-solid fa-xmark"></i>
											</button>
										</td>
									</tr>
								</tbody>
							</table>
						</div>
						<div class="mt-3">
							<label class="form-label small">Add member</label>
							<div class="d-flex gap-2 align-items-start">
								<div id="add-personal-group-member-select" class="flex-grow-1"></div>
								<button type="button" class="btn btn-outline-dark" onclick="addPersonalGroupMembers(this)">Add</button>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>

		<!-- Edit Profile Card (hidden by default) -->
		<div id="editProfile" class="shadow-lg card card-default mb-4" style="display:none">
			<div class="card-header shadow">
				<i class="fad fa-id-card"></i>
				Edit Profile
			</div>
			<div class="card-header shadow actionMessage" style="display:none"></div>
			<div class="card-body" jq-repeat="editProfile">
				<h3>Editing {{uid}}</h3>
				<form action="user/{{uid}}" method="put" onsubmit="formAJAX(this)" evalAJAX="editUserSeccess(data)">
					<div class="mb-3">
						<label class="form-label">Date of Birth</label>
						<input type="date" class="form-control shadow" name="dateOfBirth" value="{{dateOfBirth}}" />
					</div>
					<div class="mb-3">
						<label class="form-label">SSH Public Key</label>
						<input type="text" class="form-control" name="sshPublicKey" placeholder="ssh-rsa AAAAB3NzaC1yc2EAAAADAQ..." value="{{sshPublicKey}}" />
					</div>
					<div class="mb-3">
						<label class="form-label">Mobile Phone</label>
						<input type="text" class="form-control" name="mobile" placeholder="9175551234" value="{{mobile}}" />
					</div>
					<div class="mb-3">
						<label class="form-label">Location (Site)</label>
						<input type="text" class="form-control" name="location" placeholder="Site One" value="{{location}}" />
					</div>
					<div class="mb-3">
						<label class="form-label">Home Directory</label>
						<input type="text" class="form-control" name="homeDirectory" placeholder="/home/jsmith" value="{{homeDirectory}}" />
					</div>
					<div class="mb-3">
						<label class="form-label">Login Shell</label>
						<input type="text" class="form-control" name="loginShell" placeholder="/bin/bash" value="{{loginShell}}" />
					</div>
					<div class="mb-3">
						<label class="form-label">Manager(s)</label>
						<div id="edit-manager"></div>
					</div>
					<div class="mb-3">
						<label class="form-label">User Description (optional)</label>
						<textarea class="form-control" name="description" placeholder="Admin group for gitea app">{{description}}</textarea>
					</div>
					<button type="submit" class="btn btn-outline-dark btn-warning">Save Changes</button>
					<button type="button" class="btn btn-secondary" onclick="$('#editProfile').slideUp(); $('#userProfile').slideDown();">Cancel</button>
				</form>
			</div>
		</div>
	</div>
</div>
</div>

<script type="text/javascript">
	// API Tokens section (same as before)
	var tokensById = {};

	function showToken(title, token){
		app.modal.open({title: title, bodyHtml:
			'<p class="text-danger"><i class="fa-solid fa-triangle-exclamation"></i> Save this token now — it will <strong>not</strong> be shown again.</p>'
			+ '<div class="input-group"><input type="text" class="form-control font-monospace" id="revealed-token" readonly value="' + app.util.escapeHtml(token) + '">'
			+   '<button class="btn btn-outline-secondary" onclick="copyFieldValue(\'#revealed-token\')" title="Copy"><i class="fa-solid fa-copy"></i></button></div>'
			+ '<p class="mt-3 mb-0 text-muted small">Use it as a bearer token:<br><code>Authorization: Bearer ' + app.util.escapeHtml(token) + '</code></p>'
		});
	}

	function copyFieldValue(sel){
		var $el = $(sel);
		var text = $el.val();
		if(!text) return;
		navigator.clipboard.writeText(text).then(function(){
			app.messages.toast('Copied to clipboard', 'success');
		}, function(){
			app.messages.toast('Could not copy — select and copy manually', 'danger');
		});
	}

	function fmtTime(ms){
		if(!ms || Number(ms) === 0) return '—';
		var t = moment(ms, "x");
		if(!t.isValid()) return '—';
		return t.fromNow() + ' <span class="text-muted">(' + t.format('YYYY-MM-DD HH:mm') + ')</span>';
	}
	function fmtExpiry(token){
		var exp = Number(token.expires_at);
		if(!exp) return '<span class="badge text-bg-secondary">never</span>';
		if(Date.now() > exp) return '<span class="badge text-bg-danger">expired</span>';
		return '<span class="badge text-bg-warning">' + moment(exp, "x").fromNow() + '</span>';
	}

	function processToken(token){
		tokensById[token.id] = token;
		token.id_short = token.id.slice(0, 12) + '…';
		token.expires_display = fmtExpiry(token);
		token.created_display  = fmtTime(token.created_on);
		token.last_used_display = fmtTime(token.last_used_on);
		return token;
	}

	async function tableAJAX(){
		let data = await app.apiToken.list();
		var tokens = data.results || [];
		$.scope.apiTokenCard.empty();
		tokens.forEach(function(token){
			$.scope.apiTokenCard.push(processToken(token));
		});
		$('#api-tokens-empty').toggle(tokens.length === 0);
	}

	async function revokeToken(id, name, btn){
		var $card = $(btn).closest('.card');
		$card.addClass('table-warning');
		var confirmed = await app.messages.confirm('Revoke API token "' + name + '"? It stops working immediately.', $card, 'warning');
		$card.removeClass('table-warning');
		if(!confirmed) return;
		app.apiToken.remove({id: id}, function(error, data){
			if(error){ app.messages.action('Error: ' + data.message, $card, 'danger'); return; }
			$.scope.apiTokenCard.remove('id', id);
		});
	}

	async function rotateToken(id, name, btn){
		var $card = $(btn).closest('.card');
		var confirmed = await app.messages.confirm('Rotate API token "' + name + '"? The old token stops working immediately.', $card, 'warning');
		if(!confirmed) return;
		app.apiToken.rotate({id: id}, function(error, data){
			if(error){ app.messages.action('Error: ' + data.message, $card, 'danger'); return; }
			showToken('API Token Rotated', data.token);
			tableAJAX();
		});
	}

	function createApiToken(){
		var $body = app.modal.open({
			title: 'New API Token',
			bodyHtml:
				'<div class="actionMessage mb-3" style="display:none"></div>'
				+ '<form id="newTokenForm" action="api-token/" method="post" onsubmit="formAJAX(this)" evalAJAX="showToken(\'API Token Created\', data.token); tableAJAX();">'
				+   '<div class="mb-3">'
				+     '<label class="form-label">Name</label>'
				+     '<input type="text" class="form-control shadow" name="name" placeholder="CI user sync" validate=":1">'
				+   '</div>'
				+   '<div class="mb-3">'
				+     '<label class="form-label">Description</label>'
				+     '<input type="text" class="form-control shadow" name="description" placeholder="Used by the nightly sync job">'
				+   '</div>'
				+   '<div class="mb-3">'
				+     '<label class="form-label">Expires in (days) <small class="text-muted">(0 = never)</small></label>'
				+     '<input type="number" class="form-control shadow" name="expires_in_days" value="0" min="0">'
				+   '</div>'
				+ '</form>',
			footer: {
				buttonsHtml: '<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>'
					+ '<button type="submit" form="newTokenForm" class="btn btn-outline-dark"><i class="fa-solid fa-plus"></i> Create</button>',
			},
		});
		$body.find('[name=name]').focus();
	}

	function editToken(id){
		var t = tokensById[id]; if(!t) return;
		app.modal.open({
			title: 'Edit Token',
			bodyHtml:
				'<input type="hidden" id="edit-token-id" value="' + app.util.escapeHtml(id) + '">'
				+ '<div class="mb-3">'
				+   '<label class="form-label">Name</label>'
				+   '<input type="text" class="form-control shadow" id="edit-token-name" value="' + app.util.escapeHtml(t.name || '') + '">'
				+ '</div>'
				+ '<div class="mb-3">'
				+   '<label class="form-label">Description</label>'
				+   '<input type="text" class="form-control shadow" id="edit-token-description" value="' + app.util.escapeHtml(t.description || '') + '">'
				+ '</div>'
				+ '<div class="mb-3">'
				+   '<label class="form-label">Expires in (days, blank = keep as-is, 0 = never)</label>'
				+   '<input type="number" class="form-control shadow" id="edit-token-days" min="0">'
				+ '</div>',
			footer: {
				metaHtml: 'Created by ' + app.util.escapeHtml(t.created_by || '—') + ' on ' + fmtTime(t.created_on),
				buttonsHtml: app.modal.footerButtons({onSave: 'saveEditToken()', saveLabel: 'Save'}),
			},
		});
	}

	function saveEditToken(){
		var payload = {
			id: $('#edit-token-id').val(),
			name: $('#edit-token-name').val(),
			description: $('#edit-token-description').val(),
			expires_in_days: $('#edit-token-days').val(),
		};
		app.apiToken.update(payload, function(error, data){
			if(error){ app.messages.action((data && data.message) || 'Update failed.', app.modal.body(), 'danger'); return; }
			app.modal.close();
			tableAJAX();
		});
	}
</script>

<!-- Wrapped in the same `.container` as the profile/edit cards above (which
     closes before this block): without it the API Tokens card renders
     full-bleed and is visibly wider than every other card on the site. -->
<div id="own-api-tokens-section" class="container" style="display:none">
<div class="row mt-3">
	<div class="col-12">
		<div class="card shadow-lg">
			<div class="card-header d-flex justify-content-between align-items-center">
				<span><i class="fa-solid fa-key me-1"></i> API Tokens</span>
				<span>
					<a href="/docs/api-tokens" class="text-reset me-2" title="Help"><i class="fa-solid fa-circle-question"></i></a>
					<button class="btn btn-sm btn-primary" onclick="createApiToken()"><i class="fa-solid fa-plus"></i> New token</button>
				</span>
			</div>
			<div class="card-header actionMessage" style="display:none"></div>
			<p class="text-muted small px-3 pt-3 mb-0">A personal access token lets scripts and services call the SSO management API as you, with your permissions. Treat it like a password.</p>
			<div class="card-body">
				<p id="api-tokens-empty" class="text-muted mb-0" style="display:none">No API tokens.</p>
				<div jq-repeat="apiTokenCard" jq-index-key="id" id="apitoken-card-{{id}}" class="card shadow mb-3">
					<div class="card-header">
						<h5><i class="fa-solid fa-key"></i> {{ name }}</h5>
						<small class="text-muted font-monospace">{{ id_short }}</small>
					</div>
					<div class="card-header actionMessage" style="display:none"></div>
					<div class="card-body">
						{{ #description }}<p>{{ description }}</p>{{ /description }}
						<dl class="row mb-0">
							<dt class="col-sm-3">Token ID</dt>
							<dd class="col-sm-9"><code>{{ id_short }}</code></dd>
							<dt class="col-sm-3">Created</dt>
							<dd class="col-sm-9">{{{ created_display }}}</dd>
							<dt class="col-sm-3">Last used</dt>
							<dd class="col-sm-9">{{{ last_used_display }}}</dd>
							<dt class="col-sm-3">Expires</dt>
							<dd class="col-sm-9">{{{ expires_display }}}</dd>
						</dl>
					</div>
					<div class="card-footer">
						<button type="button" onclick="editToken('{{id}}')" class="btn btn-primary btn-sm"><i class="fa-solid fa-pen-to-square"></i> Edit</button>
						<button type="button" onclick="rotateToken('{{id}}', '{{name}}', this)" class="btn btn-warning btn-sm"><i class="fa-solid fa-arrows-rotate"></i> Rotate</button>
						<button type="button" onclick="revokeToken('{{id}}', '{{name}}', this)" class="btn btn-danger btn-sm float-end"><i class="fa-solid fa-trash"></i> Revoke</button>
					</div>
				</div>
			</div>
		</div>
	</div>
</div>
</div>

<%- include('impersonate_modal') %>
<%- include('bottom') %>
