<%- include('top') %>
<script id="rowTemplate" type="text/html">

</script>
<script type="text/javascript">
	function renderUsers(){
		app.user.list(function(error, data){
			if(error){
				app.messages.action(data.message, $('#tab-people'), 'danger');
				return;
			}
			$.scope.userRow.empty();
			$.scope.serviceAccountRow.empty();
			const results = data.results || [];
			$.scope.userRow.push(...results.filter(u => !u.isServiceAccount));
			$.scope.serviceAccountRow.push(...results.filter(u => u.isServiceAccount));
		});
	}

	function toggleActive(uid, active){
		app.user.setActive(uid, active, function(error, data){
			if(error) return app.messages.toast('Failed to update user status', 'danger');
			renderUsers();
		});
	}
	
	function inviteStatus(t) {
		if (t.claimed_by && t.claimed_by !== '__NONE__') return { label: 'Claimed', cls: 'text-secondary' };
		if (!t.is_valid)                                   return { label: 'Revoked', cls: 'text-danger'   };
		return                                                    { label: 'Pending', cls: 'text-success'  };
	}

	function groupsDisplay(groups) {
		try {
			const arr = JSON.parse(groups || '[]');
			return arr.length ? arr.join(', ') : '—';
		} catch(_) { return '—'; }
	}

	async function loadInvites() {
		try {
			const data = await app.api.get('user/invite');
			const tbody = document.getElementById('invite-tbody');
			tbody.innerHTML = '';
			(data.results || [])
				.sort((a, b) => (b.created_on || 0) - (a.created_on || 0))
				.forEach(function(t) {
					const status = inviteStatus(t);
					const canEdit = true; // all users on this page are admins
					const mail = (!t.mail || t.mail === '__NONE__') ? '—' : t.mail;
					const isPending = t.is_valid && (!t.claimed_by || t.claimed_by === '__NONE__');

					const tr = document.createElement('tr');
					tr.dataset.token = t.token;
					tr.innerHTML = `
						<td><small class="text-muted">${moment(Number(t.created_on)).fromNow()}</small></td>
						<td><small>${t.created_by}</small></td>
						<td><small>${mail}</small></td>
						<td><small class="text-muted">${groupsDisplay(t.groups)}</small></td>
						<td><small class="${status.cls}">${status.label}</small></td>
						<td class="text-nowrap text-end">
							${canEdit && isPending ? `
								<button class="btn btn-sm btn-outline-secondary me-1" onclick="openEdit('${t.token}')">
									<i class="fa-solid fa-pen"></i>
								</button>
								<button class="btn btn-sm btn-outline-danger" onclick="revokeInvite('${t.token}', this)">
									<i class="fa-solid fa-ban"></i>
								</button>
							` : ''}
							${isPending ? `
								<button class="btn btn-sm btn-outline-dark ms-1" onclick="copyLink('${t.token}', this)">
									<i class="fa-solid fa-copy"></i>
								</button>
							` : ''}
						</td>
					`;
					tbody.appendChild(tr);
				});
		} catch(e) {
			if (e && e.status === 401) location.replace('/');
			else console.error('Failed to load invites:', e);
		}
	}

	function populateGroupSelect(id, groups, selected) {
		const sel = document.getElementById(id);
		sel.innerHTML = '';
		groups.forEach(function(cn) {
			const opt = document.createElement('option');
			opt.value = cn;
			opt.textContent = cn;
			opt.selected = selected.includes(cn);
			sel.appendChild(opt);
		});
	}

	function openEdit(tokenId) {
		app.api.get('user/invite').then(function(data) {
			const t = (data.results || []).find(x => x.token === tokenId);
			if (!t) return;
			document.getElementById('edit-token').value = tokenId;
			document.getElementById('edit-email').value  = (t.mail && t.mail !== '__NONE__') ? t.mail : '';
			const selected = JSON.parse(t.groups || '[]');
			const allGroups = [...document.getElementById('invite-groups').options].map(o => o.value);
			populateGroupSelect('edit-groups', allGroups, selected);
			const modal = new bootstrap.Modal(document.getElementById('editModal'));
			modal.show();
		});
	}

	async function saveEdit() {
		const tokenId = document.getElementById('edit-token').value;
		const mail    = document.getElementById('edit-email').value.trim();
		const groups  = [...document.getElementById('edit-groups').selectedOptions].map(o => o.value);
		const result  = document.getElementById('edit-result');
		result.style.display = 'none';
		try {
			await app.api.put(`user/invite/${tokenId}`, { mail, groups });
			bootstrap.Modal.getInstance(document.getElementById('editModal')).hide();
			loadInvites();
		} catch(e) {
			result.style.display = '';
			result.className = 'alert alert-danger mt-2';
			result.textContent = 'Failed: ' + ((e.responseJSON && e.responseJSON.message) || 'Unknown error');
		}
	}

	async function revokeInvite(tokenId, btn) {
		$thisRow = $(btn).closest('tr');
		$thisRow.addClass('table-warning');
		let confirmation = await app.messages.confirm('Revoke selected invite token?', $thisRow, 'warning');
		if(!confirmation){
			$thisRow.removeClass('table-warning');
			return;
		}
		try {
			await app.api.delete(`user/invite/${tokenId}`);
			loadInvites();
		} catch(e) {
			app.messages.action('Failed to revoke invite.', $thisRow, 'danger');
		}
	}

	function copyLink(tokenId, btn) {
		const link = `${location.origin}/login/invite/${tokenId}`;
		navigator.clipboard.writeText(link).then(function() {
			const orig = btn.innerHTML;
			btn.innerHTML = '<i class="fa-solid fa-check"></i>';
			setTimeout(() => btn.innerHTML = orig, 1500);
		});
	}

	async function deleteUser(uid, btn){
		const $row = $(btn).closest('tr');
		$row.addClass('table-warning');
		const confirmed = await app.messages.confirm(`Delete user "${uid}"?`, $row, 'warning');
		$row.removeClass('table-warning');
		if (!confirmed) return;
		app.api.delete('user/' + uid, function(error, data){
			if (error) {
				app.messages.action(data.message || 'Failed to delete user', $row, 'danger');
				return;
			}
			renderUsers();
		});
	}

	function fuzzyMatch(query, text) {
		query = query.toLowerCase();
		text  = text.toLowerCase();
		let qi = 0;
		for (let i = 0; i < text.length && qi < query.length; i++) {
			if (text[i] === query[qi]) qi++;
		}
		return qi === query.length;
	}

	function filterGroups(inputEl, selectId) {
		const query = inputEl.value;
		[...document.getElementById(selectId).options].forEach(function(opt) {
			opt.hidden = query ? !fuzzyMatch(query, opt.value) : false;
		});
	}

	async function loadInviteGroups(){
		const data = await app.api.get('group/');
		const sel = document.getElementById('invite-groups');
		(data.results || []).forEach(function(cn){
			const opt = document.createElement('option');
			opt.value = cn;
			opt.textContent = cn;
			sel.appendChild(opt);
		});
	}

	async function sendInvite(){
		const mail   = document.getElementById('invite-email').value.trim();
		const groups = [...document.getElementById('invite-groups').selectedOptions].map(o => o.value);
		const result = document.getElementById('invite-result');
		result.style.display = 'none';
		try{
			const data = await app.api.post('user/invite', { mail, groups });
			result.style.display = '';
			if(data.mail_sent){
				result.className = 'alert alert-success mt-2';
				result.textContent = `Invite sent to ${mail}`;
			} else {
				result.className = 'alert alert-info mt-2';
				result.innerHTML = `Link: <a href="${data.link}" target="_blank">${data.link}</a>`;
			}
			document.getElementById('invite-email').value = '';
			[...document.getElementById('invite-groups').options].forEach(o => o.selected = false);
			loadInvites();
			setTimeout(() => {
			    bootstrap.Modal.getInstance(document.getElementById("inviteUserModal"))?.hide();
			    result.style.display = 'none';
			}, 3000);
		}catch(e){
			result.style.display = '';
			result.className = 'alert alert-danger mt-2';
			result.textContent = 'Failed: ' + ((e.responseJSON && e.responseJSON.message) || 'Unknown error');
		}
	}

	(async function(){
		await app.auth.forceLogin('app_sso_admin');

		$(document).ready(function(){
			renderUsers();
			loadInviteGroups();
			loadInvites();
			$('form[action="user/"]').attr('evalAJAX', 'renderUsers("User added", "success"); bootstrap.Modal.getInstance(document.getElementById("addUserModal"))?.hide();')
		});
	})();

</script>
<div class="container mt-4">

	<div class="row">
		<div class="col-md-12">
			<div class="card shadow">
				<div class="card-header d-flex justify-content-between align-items-center">
				    <div>
    					<i class="fa-solid fa-users"></i>
    					User List
    				</div>
					<div>
					    <button class="btn btn-sm btn-outline-primary me-2 group-required group-required-app_sso_admin" data-bs-toggle="modal" data-bs-target="#inviteUserModal">
					        <i class="fas fa-envelope"></i> Invite User
					    </button>
					    <button class="btn btn-sm btn-primary me-2" data-bs-toggle="modal" data-bs-target="#addUserModal">
					        <i class="fas fa-user-plus"></i> Add User
					    </button>
					    <a href="/docs/accounts" class="text-reset" title="Help"><i class="fa-solid fa-circle-question"></i></a>
					</div>
				</div>
				<div class="card-header 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" id="tab-people-btn" data-bs-toggle="tab" data-bs-target="#tab-people" type="button" role="tab">
    							<i class="fa-solid fa-user"></i> People
    						</button>
    					</li>
    					<li class="nav-item" role="presentation">
    						<button class="nav-link" id="tab-service-accounts-btn" data-bs-toggle="tab" data-bs-target="#tab-service-accounts" type="button" role="tab">
    							<i class="fa-solid fa-gears"></i> Service Accounts
    						</button>
    					</li>
    					<li class="nav-item" role="presentation">
    						<button class="nav-link" id="tab-invites-btn" data-bs-toggle="tab" data-bs-target="#tab-invites" type="button" role="tab">
    							<i class="fa-solid fa-envelope-open-text"></i> Invites
    						</button>
    					</li>
    				</ul>
				</div>
				
				<div class="tab-content">
					<div class="tab-pane fade show active" id="tab-people" role="tabpanel">
						<div class="table-responsive">
            				<table class="card-body table table-striped" style="margin-bottom:0">
            					<thead>
            						<th>ID</th>
            						<th>Name</th>
            						<th>eMail</th>
            						<th>Key</th>
            						<th>Active</th>
            						<th>TOS</th>
            						<th></th>
            					</thead>
            					<tbody id="tableAJAX">
            						<tr jq-repeat="userRow">
            							<td>
            								{{ uidNumber }}
            							</td>
            							<td>
            								<a href='/users/{{uid}}'>{{givenName}} {{sn}}</a>
            							</td>
            							<td>
            								{{mail}}
            							</td>
            							<td>
            								{{#sshPublicKey}}<i class="fa-regular fa-circle-check text-success"></i>{{/sshPublicKey}}
            							</td>
            							<td>
            								{{#isActive}}<i class="fa-regular fa-circle-check text-success"></i>{{/isActive}}
            								{{#isInactive}}<i class="fa-solid fa-circle-xmark text-danger"></i>{{/isInactive}}
            							</td>
            							<td>
            								{{#tosAccepted}}<i class="fa-solid fa-circle-check text-success" title="TOS accepted"></i>{{/tosAccepted}}
            								{{#tosNotAccepted}}<i class="fa-solid fa-circle-xmark text-danger" title="TOS not accepted"></i>{{/tosNotAccepted}}
            							</td>
            							<td class="text-nowrap">
            								{{#isActive}}
            								<button class="btn btn-sm btn-outline-warning me-1" title="Deactivate" onclick="toggleActive('{{uid}}', false)">
            									<i class="fa-solid fa-lock"></i>
            								</button>
            								{{/isActive}}
            								{{#isInactive}}
            								<button class="btn btn-sm btn-warning me-1" title="Activate" onclick="toggleActive('{{uid}}', true)">
            									<i class="fa-solid fa-lock-open"></i>
            								</button>
            								{{/isInactive}}
            								<button class="btn btn-sm btn-outline-secondary me-1" title="Impersonate" onclick="startImpersonate('{{uid}}')">
            									<i class="fa-solid fa-user-secret"></i>
            								</button>
            								<button class="btn btn-sm btn-danger" onclick="deleteUser('{{uid}}', this)">
            									<i class="fa-solid fa-user-slash"></i>
            								</button>
            							</td>
            						</tr>
            					</tbody>
            				</table>
						</div>
					</div>
					
					<div class="tab-pane fade" id="tab-service-accounts" role="tabpanel">
					    <div class="p-3 pb-0 text-muted small border-bottom">
					        <i class="fa-solid fa-circle-info"></i> Unix/POSIX accounts something runs as, not a person. Create one from the People tab's "Add User" form.
					    </div>
						<div class="table-responsive">
            				<table class="card-body table table-striped" style="margin-bottom:0">
            					<thead>
            						<th>Username</th>
            						<th>Description</th>
            						<th>Manager(s)</th>
            						<th>Created</th>
            						<th>Active</th>
            						<th></th>
            					</thead>
            					<tbody>
            						<tr jq-repeat="serviceAccountRow">
            							<td>
            								<a href='/users/{{uid}}'>{{uid}}</a>
            							</td>
            							<td>
            								{{description}}
            							</td>
            							<td>
            								{{#managerUids}}<span class="badge bg-secondary me-1">{{.}}</span>{{/managerUids}}
            							</td>
            							<td>
            								{{createTimestamp}}
            							</td>
            							<td>
            								{{#isActive}}<i class="fa-regular fa-circle-check text-success"></i>{{/isActive}}
            								{{#isInactive}}<i class="fa-solid fa-circle-xmark text-danger"></i>{{/isInactive}}
            							</td>
            							<td class="text-nowrap">
            								{{#isActive}}
            								<button class="btn btn-sm btn-outline-warning me-1" title="Deactivate" onclick="toggleActive('{{uid}}', false)">
            									<i class="fa-solid fa-lock"></i>
            								</button>
            								{{/isActive}}
            								{{#isInactive}}
            								<button class="btn btn-sm btn-warning me-1" title="Activate" onclick="toggleActive('{{uid}}', true)">
            									<i class="fa-solid fa-lock-open"></i>
            								</button>
            								{{/isInactive}}
            								<button class="btn btn-sm btn-danger" onclick="deleteUser('{{uid}}', this)">
            									<i class="fa-solid fa-user-slash"></i>
            								</button>
            							</td>
            						</tr>
            					</tbody>
            				</table>
						</div>
					</div>
					
					<div class="tab-pane fade" id="tab-invites" role="tabpanel">
						<div class="table-responsive">
            				<table class="card-body table table-striped" style="margin-bottom:0">
            					<thead>
            						<th>Created</th>
            						<th>By</th>
            						<th>Email</th>
            						<th>Groups</th>
            						<th>Status</th>
            						<th></th>
            					</thead>
            					<tbody id="invite-tbody">
            					    <tr><td colspan="6" class="text-center text-muted py-3">Loading…</td></tr>
            					</tbody>
            				</table>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
</div>

<!-- Invite User Modal -->
<div class="modal fade" id="inviteUserModal" tabindex="-1" aria-labelledby="inviteUserModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header shadow">
        <h5 class="modal-title" id="inviteUserModalLabel"><i class="fas fa-user-plus"></i> Invite User</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <div class="mb-2">
            <label class="form-label small">Email <small class="text-muted">(optional — sends invite immediately)</small></label>
            <input type="email" id="invite-email" class="form-control form-control-sm shadow" placeholder="user@example.com" />
        </div>
        <div class="mb-2">
            <label class="form-label small">Groups <small class="text-muted">(optional — hold Ctrl/⌘ for multiple)</small></label>
            <input type="text" class="form-control form-control-sm shadow mb-1" placeholder="Filter groups…" oninput="filterGroups(this, 'invite-groups')" />
            <select id="invite-groups" class="form-select form-select-sm shadow" multiple size="4"></select>
        </div>
        <div id="invite-result" style="display:none" class="mt-2"></div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" onclick="sendInvite()" class="btn btn-primary shadow">
            <i class="fa-solid fa-envelope"></i> Send Invite
        </button>
      </div>
    </div>
  </div>
</div>

<!-- Add User Modal -->
<div class="modal fade" id="addUserModal" tabindex="-1" aria-labelledby="addUserModalLabel" aria-hidden="true">
  <div class="modal-dialog modal-lg">
    <div class="modal-content">
      <div class="modal-header shadow">
        <h5 class="modal-title" id="addUserModalLabel">
            <i class="fas fa-user-plus"></i> Add new user
        </h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <p class="small text-muted mb-3">Check <b>This is a service account</b> below to create one — it'll show up under the Service Accounts tab.</p>
        <%- include('user_form', {adminMode: true}) %>
      </div>
    </div>
  </div>
</div>

<!-- Edit Invite Modal -->
<div class="modal fade" id="editModal" tabindex="-1">
	<div class="modal-dialog">
		<div class="modal-content">
			<div class="modal-header shadow">
				<h5 class="modal-title"><i class="fa-solid fa-pen"></i> Edit Invite</h5>
				<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
			</div>
			<div class="modal-body">
				<input type="hidden" id="edit-token" />
				<div class="mb-3">
					<label class="form-label">Email <small class="text-muted">(leave blank to clear; changing sends a new verification email)</small></label>
					<input type="email" id="edit-email" class="form-control shadow" placeholder="user@example.com" />
				</div>
				<div class="mb-3">
					<label class="form-label">Groups <small class="text-muted">(Ctrl/⌘ for multiple)</small></label>
					<input type="text" class="form-control form-control-sm shadow mb-1" placeholder="Filter groups…" oninput="filterGroups(this, 'edit-groups')" />
					<select id="edit-groups" class="form-select shadow" multiple size="6"></select>
				</div>
				<div id="edit-result" style="display:none"></div>
			</div>
			<div class="modal-footer">
				<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
				<button type="button" class="btn btn-primary" onclick="saveEdit()">
					<i class="fa-solid fa-floppy-disk"></i> Save
				</button>
			</div>
		</div>
	</div>
</div>

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