<script lang="ts">
  import { onMount } from 'svelte';
  import { tooltip } from '$lib/actions/tooltip';
  import { api } from '$lib/api';
  import { clientSession } from '$lib/session';
  import { toast } from '$lib/toast';
  import type { InternalRoleOption, InternalUser } from '$lib/types';
  import { UserPlus, Pencil, KeyRound, Trash2, ShieldCheck, TriangleAlert } from 'lucide-svelte';

  let users = $state<InternalUser[]>([]);
  let roles = $state<InternalRoleOption[]>([]);
  let loading = $state(true);
  let loadError = $state('');

  const currentUserId = $derived($clientSession?.user_id ?? null);

  async function load() {
    loading = true;
    loadError = '';
    try {
      const [userList, roleList] = await Promise.all([
        api.accessUsers(),
        api.accessAssignableRoles()
      ]);
      users = userList;
      roles = roleList;
    } catch (err: unknown) {
      loadError = err instanceof Error ? err.message : 'Failed to load users';
    } finally {
      loading = false;
    }
  }

  onMount(load);

  // ── Create / edit modal ───────────────────────────────────────
  type FormMode = 'create' | 'edit';
  let formOpen = $state(false);
  let formMode = $state<FormMode>('create');
  let formUserId = $state<number | null>(null);
  let formName = $state('');
  let formEmail = $state('');
  let formRoleId = $state<number | null>(null);
  let formActive = $state(true);
  let formPassword = $state('');
  let formSaving = $state(false);
  let formError = $state('');

  function openCreate() {
    formMode = 'create';
    formUserId = null;
    formName = '';
    formEmail = '';
    formRoleId = roles[0]?.id ?? null;
    formActive = true;
    formPassword = '';
    formError = '';
    formOpen = true;
  }

  function openEdit(user: InternalUser) {
    formMode = 'edit';
    formUserId = user.id;
    formName = user.name;
    formEmail = user.email;
    formRoleId = user.role_id;
    formActive = user.is_active;
    formPassword = '';
    formError = '';
    formOpen = true;
  }

  function closeForm() {
    if (formSaving) return;
    formOpen = false;
  }

  const editingSelf = $derived(formMode === 'edit' && formUserId === currentUserId);

  async function saveForm() {
    formError = '';
    const name = formName.trim();
    const email = formEmail.trim().toLowerCase();
    if (!name) {
      formError = 'Name is required';
      return;
    }
    if (!email || !email.includes('@')) {
      formError = 'A valid email is required';
      return;
    }
    if (formMode === 'create' && formPassword && formPassword.length < 8) {
      formError = 'Password must be at least 8 characters';
      return;
    }
    formSaving = true;
    const tid = toast.loading(formMode === 'create' ? 'Creating user…' : 'Saving user…');
    try {
      if (formMode === 'create') {
        await api.createAccessUser({
          name,
          email,
          role_id: formRoleId,
          is_active: formActive,
          password: formPassword ? formPassword : null
        });
      } else if (formUserId != null) {
        await api.updateAccessUser(formUserId, {
          name,
          email,
          role_id: formRoleId,
          is_active: formActive
        });
      }
      toast.dismiss(tid);
      toast.success(formMode === 'create' ? 'User created' : 'User updated');
      formOpen = false;
      await load();
    } catch (err: unknown) {
      toast.dismiss(tid);
      const msg = err instanceof Error ? err.message : 'An error occurred';
      formError = msg;
      toast.error(msg);
    } finally {
      formSaving = false;
    }
  }

  // ── Password reset modal ──────────────────────────────────────
  let pwOpen = $state(false);
  let pwUser = $state<InternalUser | null>(null);
  let pwNew = $state('');
  let pwConfirm = $state('');
  let pwSaving = $state(false);
  let pwError = $state('');

  function openPassword(user: InternalUser) {
    pwUser = user;
    pwNew = '';
    pwConfirm = '';
    pwError = '';
    pwOpen = true;
  }

  function closePassword() {
    if (pwSaving) return;
    pwOpen = false;
  }

  async function savePassword() {
    pwError = '';
    if (pwNew.length < 8) {
      pwError = 'Password must be at least 8 characters';
      return;
    }
    if (pwNew !== pwConfirm) {
      pwError = 'Passwords do not match';
      return;
    }
    if (!pwUser) return;
    pwSaving = true;
    const tid = toast.loading('Updating password…');
    try {
      await api.setAccessUserPassword(pwUser.id, pwNew);
      toast.dismiss(tid);
      toast.success(`Password updated for ${pwUser.name}`);
      pwOpen = false;
    } catch (err: unknown) {
      toast.dismiss(tid);
      const msg = err instanceof Error ? err.message : 'An error occurred';
      pwError = msg;
      toast.error(msg);
    } finally {
      pwSaving = false;
    }
  }

  // ── Delete modal ──────────────────────────────────────────────
  let deleteUser = $state<InternalUser | null>(null);
  let deleting = $state(false);

  function openDelete(user: InternalUser) {
    deleteUser = user;
  }

  function closeDelete() {
    if (deleting) return;
    deleteUser = null;
  }

  async function confirmDelete() {
    if (!deleteUser) return;
    deleting = true;
    const tid = toast.loading('Deleting user…');
    try {
      await api.deleteAccessUser(deleteUser.id);
      toast.dismiss(tid);
      toast.success(`Deleted ${deleteUser.name}`);
      deleteUser = null;
      await load();
    } catch (err: unknown) {
      toast.dismiss(tid);
      toast.error(err instanceof Error ? err.message : 'Failed to delete user');
    } finally {
      deleting = false;
    }
  }

  // ── Quick active toggle ───────────────────────────────────────
  async function toggleActive(user: InternalUser) {
    if (user.id === currentUserId) {
      toast.error('You cannot deactivate your own account');
      return;
    }
    const next = !user.is_active;
    const tid = toast.loading(next ? 'Enabling access…' : 'Disabling access…');
    try {
      const updated = await api.updateAccessUser(user.id, { is_active: next });
      users = users.map((u) => (u.id === user.id ? updated : u));
      toast.dismiss(tid);
      toast.success(next ? `${user.name} can sign in` : `${user.name}'s access is off`);
    } catch (err: unknown) {
      toast.dismiss(tid);
      toast.error(err instanceof Error ? err.message : 'Failed to update access');
    }
  }
</script>

<div class="panel-section">
  <header class="panel-header">
    <div class="header-copy">
      <h2>Users</h2>
      <p>Manage who can sign in to the workspace, their role, and their access.</p>
    </div>
    <button type="button" class="btn-primary" onclick={openCreate}>
      <UserPlus size={16} strokeWidth={2.2} /> Add user
    </button>
  </header>

  {#if loading}
    <p class="state-msg">Loading users…</p>
  {:else if loadError}
    <p class="state-msg error"><TriangleAlert size={15} strokeWidth={2.2} /> {loadError}</p>
  {:else}
    <div class="table-wrap">
      <table class="users-table">
        <thead>
          <tr>
            <th>Name</th>
            <th>Email</th>
            <th>Role</th>
            <th>Access</th>
            <th class="actions-col">Actions</th>
          </tr>
        </thead>
        <tbody>
          {#each users as user (user.id)}
            <tr class:inactive={!user.is_active}>
              <td>
                <span class="user-name">{user.name}</span>
                {#if user.id === currentUserId}<span class="you-chip">You</span>{/if}
                {#if user.is_protected}
                  <span class="lean-chip" use:tooltip={'Lean owner, this account cannot be deleted'}>
                    <ShieldCheck size={12} strokeWidth={2.4} /> Lean
                  </span>
                {/if}
              </td>
              <td class="email-cell">{user.email}</td>
              <td>{user.role ?? '—'}</td>
              <td>
                <button
                  type="button"
                  class="status-toggle"
                  class:on={user.is_active}
                  disabled={user.id === currentUserId}
                  aria-label={user.id === currentUserId ? 'You cannot change your own access' : 'Toggle access'}
                  use:tooltip={user.id === currentUserId
                    ? 'You cannot change your own access'
                    : user.is_active
                      ? 'Turn sign-in access off'
                      : 'Turn sign-in access on'}
                  onclick={() => toggleActive(user)}
                >
                  <span class="dot"></span>
                  {user.is_active ? 'Active' : 'Off'}
                </button>
              </td>
              <td class="actions-col">
                <div class="row-actions">
                  <button
                    type="button"
                    class="icon-btn"
                    aria-label="Edit user"
                    use:tooltip={'Edit user details'}
                    onclick={() => openEdit(user)}
                  >
                    <Pencil size={15} strokeWidth={2.1} />
                  </button>
                  <button
                    type="button"
                    class="icon-btn"
                    aria-label="Reset password"
                    use:tooltip={'Reset password'}
                    onclick={() => openPassword(user)}
                  >
                    <KeyRound size={15} strokeWidth={2.1} />
                  </button>
                  <button
                    type="button"
                    class="icon-btn danger"
                    aria-label="Delete user"
                    use:tooltip={user.is_protected
                      ? 'Lean accounts cannot be deleted'
                      : user.id === currentUserId
                        ? 'You cannot delete your own account'
                        : 'Delete user'}
                    disabled={user.is_protected || user.id === currentUserId}
                    onclick={() => openDelete(user)}
                  >
                    <Trash2 size={15} strokeWidth={2.1} />
                  </button>
                </div>
              </td>
            </tr>
          {/each}
        </tbody>
      </table>
    </div>
  {/if}
</div>

<!-- Create / edit modal -->
{#if formOpen}
  <div class="modal-backdrop" role="presentation" onclick={closeForm}>
    <div
      class="modal-card"
      role="dialog"
      aria-modal="true"
      aria-labelledby="user-form-title"
      tabindex="-1"
      onclick={(e) => e.stopPropagation()}
      onkeydown={(e) => { if (e.key === 'Escape') closeForm(); }}
    >
      <h2 id="user-form-title" class="modal-title">{formMode === 'create' ? 'Add user' : 'Edit user'}</h2>

      <form class="modal-form" onsubmit={(e) => { e.preventDefault(); saveForm(); }}>
        <div class="field">
          <label for="uf-name">Full name</label>
          <input id="uf-name" type="text" bind:value={formName} autocomplete="off" required />
        </div>
        <div class="field">
          <label for="uf-email">Email address</label>
          <input id="uf-email" type="email" bind:value={formEmail} autocomplete="off" required />
        </div>
        <div class="field">
          <label for="uf-role">Role</label>
          <select id="uf-role" bind:value={formRoleId}>
            <option value={null}>No role (no access)</option>
            {#each roles as role (role.id)}
              <option value={role.id}>{role.name}</option>
            {/each}
          </select>
        </div>
        {#if formMode === 'create'}
          <div class="field">
            <label for="uf-pass">Initial password <span class="optional">(optional)</span></label>
            <input id="uf-pass" type="password" bind:value={formPassword} autocomplete="new-password" placeholder="Leave blank to use the shared password" />
          </div>
        {/if}
        <label class="check-row" class:disabled={editingSelf}>
          <input type="checkbox" bind:checked={formActive} disabled={editingSelf} />
          <span>Access enabled {#if editingSelf}<em>(you cannot disable your own access)</em>{/if}</span>
        </label>

        {#if formError}
          <p class="form-error"><TriangleAlert size={15} strokeWidth={2.2} /> {formError}</p>
        {/if}

        <div class="modal-actions">
          <button type="button" class="modal-cancel" onclick={closeForm} disabled={formSaving}>Cancel</button>
          <button type="submit" class="btn-primary" disabled={formSaving}>
            {formSaving ? 'Saving…' : formMode === 'create' ? 'Create user' : 'Save changes'}
          </button>
        </div>
      </form>
    </div>
  </div>
{/if}

<!-- Password reset modal -->
{#if pwOpen && pwUser}
  <div class="modal-backdrop" role="presentation" onclick={closePassword}>
    <div
      class="modal-card"
      role="dialog"
      aria-modal="true"
      aria-labelledby="pw-title"
      tabindex="-1"
      onclick={(e) => e.stopPropagation()}
      onkeydown={(e) => { if (e.key === 'Escape') closePassword(); }}
    >
      <div class="modal-icon"><KeyRound size={20} strokeWidth={2.2} /></div>
      <h2 id="pw-title" class="modal-title">Reset password</h2>
      <p class="modal-text">Set a new password for <strong>{pwUser.name}</strong>. They can change it later in their own settings.</p>

      <form class="modal-form" onsubmit={(e) => { e.preventDefault(); savePassword(); }}>
        <div class="field">
          <label for="pw-new">New password</label>
          <input id="pw-new" type="password" bind:value={pwNew} autocomplete="new-password" required />
        </div>
        <div class="field">
          <label for="pw-confirm">Confirm password</label>
          <input id="pw-confirm" type="password" bind:value={pwConfirm} autocomplete="new-password" required />
        </div>

        {#if pwError}
          <p class="form-error"><TriangleAlert size={15} strokeWidth={2.2} /> {pwError}</p>
        {/if}

        <div class="modal-actions">
          <button type="button" class="modal-cancel" onclick={closePassword} disabled={pwSaving}>Cancel</button>
          <button type="submit" class="btn-primary" disabled={pwSaving}>
            {pwSaving ? 'Updating…' : 'Set password'}
          </button>
        </div>
      </form>
    </div>
  </div>
{/if}

<!-- Delete confirmation -->
{#if deleteUser}
  <div class="modal-backdrop" role="presentation" onclick={closeDelete}>
    <div
      class="modal-card"
      role="dialog"
      aria-modal="true"
      aria-labelledby="del-title"
      tabindex="-1"
      onclick={(e) => e.stopPropagation()}
      onkeydown={(e) => { if (e.key === 'Escape') closeDelete(); }}
    >
      <div class="modal-icon danger"><Trash2 size={20} strokeWidth={2.2} /></div>
      <h2 id="del-title" class="modal-title">Delete user?</h2>
      <p class="modal-text">
        This permanently removes <strong>{deleteUser.name}</strong> ({deleteUser.email}) and their
        access. This cannot be undone.
      </p>
      <div class="modal-actions">
        <button type="button" class="modal-cancel" onclick={closeDelete} disabled={deleting}>Cancel</button>
        <button type="button" class="modal-confirm" onclick={confirmDelete} disabled={deleting}>
          {deleting ? 'Deleting…' : 'Delete user'}
        </button>
      </div>
    </div>
  </div>
{/if}

<style>
  .panel-section {
    display: flex;
    flex-direction: column;
  }

  .panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 1.5rem 1.75rem 1.25rem;
    border-bottom: 1px solid var(--line);
  }

  .header-copy h2 {
    margin: 0 0 0.3rem;
    font-size: 1.1rem;
    font-weight: 700;
  }

  .header-copy p {
    margin: 0;
    font-size: 0.85rem;
    color: var(--muted);
  }

  .btn-primary {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    flex-shrink: 0;
    padding: 0.55rem 1.1rem;
    background: var(--color-brand);
    color: #fff;
    border: none;
    border-radius: 0.6rem;
    font-size: 0.86rem;
    font-weight: 600;
    cursor: pointer;
    transition: opacity 140ms ease;
  }

  .btn-primary:hover:not(:disabled) {
    opacity: 0.88;
  }

  .btn-primary:disabled {
    opacity: 0.6;
    cursor: not-allowed;
  }

  .state-msg {
    padding: 1.5rem 1.75rem;
    margin: 0;
    font-size: 0.9rem;
    color: var(--muted);
  }

  .state-msg.error {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    color: #c53030;
  }

  /* ── Table ──────────────────────────────────────────────────── */

  .table-wrap {
    overflow-x: auto;
    padding: 0.5rem 1.75rem 1.75rem;
  }

  .users-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.88rem;
  }

  .users-table th {
    text-align: left;
    padding: 0.7rem 0.75rem;
    font-size: 0.74rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted);
    border-bottom: 1px solid var(--line);
  }

  .users-table td {
    padding: 0.75rem;
    border-bottom: 1px solid var(--line);
    color: var(--text);
    vertical-align: middle;
  }

  .users-table tr.inactive td {
    color: var(--muted);
  }

  .user-name {
    font-weight: 600;
  }

  .email-cell {
    color: var(--muted);
  }

  .you-chip,
  .lean-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    margin-left: 0.4rem;
    padding: 0.08rem 0.42rem;
    border-radius: 0.5rem;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    vertical-align: middle;
  }

  .you-chip {
    background: var(--panel-soft);
    border: 1px solid var(--line);
    color: var(--muted);
  }

  .lean-chip {
    background: color-mix(in srgb, var(--color-brand) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--color-brand) 30%, transparent);
    color: var(--color-brand);
  }

  .actions-col {
    text-align: right;
    white-space: nowrap;
  }

  .row-actions {
    display: inline-flex;
    gap: 0.3rem;
  }

  .icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: 1px solid var(--line);
    border-radius: 0.55rem;
    background: var(--panel);
    color: var(--muted);
    cursor: pointer;
    transition: color 140ms ease, border-color 140ms ease, background-color 140ms ease;
  }

  .icon-btn:hover:not(:disabled) {
    color: var(--text);
    border-color: var(--color-brand);
  }

  .icon-btn.danger:hover:not(:disabled) {
    color: #c53030;
    border-color: color-mix(in srgb, #e53e3e 45%, transparent);
  }

  .icon-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
  }

  .status-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.42rem;
    padding: 0.32rem 0.7rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--panel-soft);
    color: var(--muted);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    transition: border-color 140ms ease, color 140ms ease;
  }

  .status-toggle .dot {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--muted);
  }

  .status-toggle.on {
    color: var(--color-brand);
    border-color: color-mix(in srgb, var(--color-brand) 35%, transparent);
  }

  .status-toggle.on .dot {
    background: var(--color-brand);
  }

  .status-toggle:disabled {
    cursor: not-allowed;
    opacity: 0.7;
  }

  /* ── Modal ──────────────────────────────────────────────────── */

  .modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: 80;
    display: grid;
    place-items: center;
    padding: 1.5rem;
    background: color-mix(in srgb, var(--color-text-primary, #000) 32%, transparent);
    backdrop-filter: blur(6px);
  }

  .modal-card {
    width: min(30rem, 100%);
    display: grid;
    gap: 0.7rem;
    padding: 1.6rem;
    border: 1px solid var(--line);
    border-radius: 1rem;
    background: var(--panel);
    box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.45);
  }

  .modal-card:focus {
    outline: none;
  }

  .modal-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.6rem;
    height: 2.6rem;
    border-radius: 0.8rem;
    background: color-mix(in srgb, var(--color-brand) 12%, transparent);
    color: var(--color-brand);
  }

  .modal-icon.danger {
    background: #fdecee;
    color: #b3261e;
  }

  .modal-title {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--text);
  }

  .modal-text {
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--muted);
  }

  .modal-form {
    display: grid;
    gap: 0.85rem;
    margin-top: 0.3rem;
  }

  .field {
    display: grid;
    gap: 0.4rem;
  }

  .field label {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text);
  }

  .field .optional {
    font-weight: 400;
    color: var(--muted);
  }

  .field input,
  .field select {
    width: 100%;
    padding: 0.58rem 0.8rem;
    border: 1px solid var(--line);
    border-radius: 0.55rem;
    background: var(--panel-soft);
    color: var(--text);
    font-size: 0.9rem;
    box-sizing: border-box;
  }

  .field input:focus,
  .field select:focus {
    outline: none;
    border-color: var(--color-brand);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-brand) 18%, transparent);
  }

  .check-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
    color: var(--text);
    cursor: pointer;
  }

  .check-row.disabled {
    color: var(--muted);
    cursor: not-allowed;
  }

  .check-row em {
    color: var(--muted);
    font-style: normal;
  }

  .form-error {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0;
    padding: 0.6rem 0.8rem;
    background: color-mix(in srgb, #e53e3e 8%, transparent);
    border: 1px solid color-mix(in srgb, #e53e3e 25%, transparent);
    border-radius: 0.55rem;
    color: #c53030;
    font-size: 0.83rem;
  }

  .modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.6rem;
    margin-top: 0.4rem;
  }

  .modal-cancel,
  .modal-confirm {
    padding: 0.55rem 1.1rem;
    border-radius: 0.6rem;
    font-size: 0.88rem;
    font-weight: 600;
    cursor: pointer;
    transition: background-color 150ms ease, opacity 150ms ease;
  }

  .modal-cancel {
    background: var(--panel);
    border: 1px solid var(--line);
    color: var(--muted);
  }

  .modal-cancel:hover:not(:disabled) {
    color: var(--text);
  }

  .modal-confirm {
    background: #b3261e;
    border: 1px solid #b3261e;
    color: #fff;
  }

  .modal-confirm:hover:not(:disabled) {
    background: #95201a;
  }

  .modal-confirm:disabled,
  .modal-cancel:disabled {
    opacity: 0.55;
    cursor: not-allowed;
  }

  @media (max-width: 720px) {
    .panel-header {
      flex-direction: column;
      align-items: flex-start;
    }
  }
</style>
