function createCommentActions({ fetchJson, getLogin, confirmDelete = () => false }) {
  const encodedRepository = repository => String(repository || '').split('/')
    .map(encodeURIComponent).join('/');

  function pathFor(context, commentId) {
    const item = context?.item || {};
    if (context?.kind === 'update') {
      return 'api/v1/notifications/' + encodeURIComponent(item.notification_id) +
        '/comments/' + encodeURIComponent(commentId);
    }
    if (!['issue', 'pull'].includes(context?.kind)) throw new Error('Comment conversation is unavailable.');
    return 'api/v1/repos/' + encodedRepository(item.repository) + '/' +
      (context.kind === 'pull' ? 'pulls/' : 'issues/') + encodeURIComponent(item.number) +
      '/comments/' + encodeURIComponent(commentId);
  }

  const controller = {
    isOwned(comment) {
      const login = String(getLogin() || '').trim();
      return Boolean(login && comment && comment.author === login);
    },
    async edit(context, pager, commentId, body) {
      const draft = String(body || '').trim();
      if (!draft) throw new Error('Comment must not be blank.');
      const comment = await fetchJson(pathFor(context, commentId), {
        method: 'PATCH',
        headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
        body: JSON.stringify({ body: draft }),
      });
      pager.replace(comment);
      return pager.snapshot();
    },
    async remove(context, pager, commentId) {
      if (!confirmDelete('Delete this comment permanently?')) return null;
      const result = await fetchJson(pathFor(context, commentId), {
        method: 'DELETE', headers: { Accept: 'application/json' },
      });
      if (!result?.deleted || Number(result.id) !== Number(commentId)) {
        throw new Error('Comment deletion was not confirmed.');
      }
      pager.remove(commentId);
      return pager.snapshot();
    },
    actionHtml(comment) {
      return controller.isOwned(comment) ?
        '<div class="comment-owned-actions" aria-label="Your comment actions">' +
        '<button type="button" data-comment-action="edit">Edit</button>' +
        '<button type="button" data-comment-action="delete">Delete</button></div>' : '';
    },
    wire({ root, getSurface, isOffline, escapeHtml }) {
      root.addEventListener('click', async event => {
        const button = event.target.closest('[data-comment-action]');
        if (!button) return;
        const card = button.closest('.issue-comment');
        const commentId = Number(card?.dataset.commentId);
        const surface = getSurface();
        const comment = surface.pager?.snapshot().comments.find(item => item.id === commentId);
        if (!comment || !controller.isOwned(comment)) return;
        if (isOffline()) {
          surface.status.textContent = 'Reconnect to edit or delete this comment.';
          return;
        }
        if (button.dataset.commentAction === 'delete') {
          try {
            const state = await controller.remove(surface.context, surface.pager, commentId);
            if (state) {
              surface.render(state);
              surface.status.textContent = 'Comment deleted.';
            }
          } catch (error) {
            surface.status.textContent = error.message || 'Comment deletion failed. Retry or open it in Gitea.';
          }
          return;
        }
        card.innerHTML = '<div class="small">Editing your comment</div>' +
          '<textarea class="comment-edit-textarea" maxlength="10000" aria-label="Edit comment">' +
          escapeHtml(comment.body || '') + '</textarea>' +
          '<div class="comment-owned-actions"><button type="button" data-comment-edit-save>Save</button>' +
          '<button type="button" data-comment-edit-cancel>Cancel</button></div>';
        const textarea = card.querySelector('.comment-edit-textarea');
        textarea.focus();
        card.querySelector('[data-comment-edit-cancel]').addEventListener('click', () => surface.render(surface.pager.snapshot()));
        card.querySelector('[data-comment-edit-save]').addEventListener('click', async saveEvent => {
          const save = saveEvent.currentTarget;
          save.disabled = true;
          surface.status.textContent = 'Saving comment…';
          try {
            const state = await controller.edit(surface.context, surface.pager, commentId, textarea.value);
            surface.render(state);
            surface.status.textContent = 'Comment updated.';
          } catch (error) {
            save.disabled = false;
            surface.status.textContent = error.message || 'Comment update failed. Your edit is safe; retry or open it in Gitea.';
            textarea.focus();
          }
        });
      });
    },
  };
  return controller;
}

if (typeof module !== 'undefined' && module.exports) module.exports = createCommentActions;