export function createConfirmDialogController({ documentTarget }) {
  let activeDialog = null;

  function close() {
    if (!activeDialog) return;
    const { overlay, previousFocus, onKeyDown } = activeDialog;
    documentTarget.removeEventListener('keydown', onKeyDown);
    overlay.remove();
    activeDialog = null;
    previousFocus?.focus?.();
  }

  return {
    show({ id, title, message, details = [], confirmLabel = 'Confirm', onConfirm }) {
      close();
      const overlay = documentTarget.createElement('div');
      overlay.className = 'demo-modal-overlay show';
      overlay.id = id;
      overlay.setAttribute('role', 'dialog');
      overlay.setAttribute('aria-modal', 'true');
      overlay.setAttribute('aria-labelledby', `${id}Title`);
      overlay.innerHTML = `
        <div class="demo-modal" style="min-width:350px;max-width:400px;">
          <div class="demo-modal-header">
            <h2 id="${id}Title" data-dialog-title></h2>
            <button class="demo-modal-close" data-dialog-close aria-label="Close dialog">&times;</button>
          </div>
          <div class="demo-modal-body" style="padding:20px;">
            <p data-dialog-message style="margin:0 0 16px 0;color:var(--text);line-height:1.5;"></p>
            <p data-dialog-details style="margin:0;color:var(--muted);font-size:12px;white-space:pre-line;"></p>
          </div>
          <div class="demo-modal-footer" style="display:flex;gap:8px;justify-content:flex-end;padding:16px 20px;border-top:1px solid var(--line);">
            <button class="nav-btn" data-dialog-cancel>Cancel</button>
            <button class="nav-btn primary" data-dialog-confirm></button>
          </div>
        </div>`;
      overlay.querySelector('[data-dialog-title]').textContent = title;
      overlay.querySelector('[data-dialog-message]').textContent = message;
      overlay.querySelector('[data-dialog-details]').textContent = details.join('\n');
      const confirmButton = overlay.querySelector('[data-dialog-confirm]');
      confirmButton.textContent = confirmLabel;
      const previousFocus = documentTarget.activeElement;
      const onKeyDown = event => {
        if (event.key === 'Escape') close();
      };
      activeDialog = { overlay, previousFocus, onKeyDown };
      overlay.querySelector('[data-dialog-close]').addEventListener('click', close);
      overlay.querySelector('[data-dialog-cancel]').addEventListener('click', close);
      overlay.addEventListener('click', event => {
        if (event.target === overlay) close();
      });
      confirmButton.addEventListener('click', async () => {
        confirmButton.disabled = true;
        close();
        await onConfirm?.();
      });
      documentTarget.addEventListener('keydown', onKeyDown);
      documentTarget.body.appendChild(overlay);
      confirmButton.focus();
      return { close };
    },
    close,
  };
}

export function createTextInputDialogController({ documentTarget }) {
  let activeDialog = null;

  function close() {
    if (!activeDialog) return;
    const { overlay, previousFocus, onKeyDown } = activeDialog;
    documentTarget.removeEventListener('keydown', onKeyDown);
    overlay.remove();
    activeDialog = null;
    previousFocus?.focus?.();
  }

  return {
    show({
      id,
      title,
      label,
      value = '',
      placeholder = '',
      confirmLabel = 'Save',
      emptyMessage = 'Enter a name.',
      inputType = 'text',
      inputMode = '',
      min,
      max,
      step,
      validate,
      onSubmit,
    }) {
      close();
      const overlay = documentTarget.createElement('div');
      overlay.className = 'demo-modal-overlay show';
      overlay.id = id;
      overlay.setAttribute('role', 'dialog');
      overlay.setAttribute('aria-modal', 'true');
      overlay.setAttribute('aria-labelledby', `${id}Title`);
      overlay.innerHTML = `
        <div class="demo-modal" style="min-width:350px;max-width:400px;">
          <div class="demo-modal-header">
            <h2 id="${id}Title" data-dialog-title></h2>
            <button class="demo-modal-close" data-dialog-close aria-label="Close dialog">&times;</button>
          </div>
          <form data-dialog-form>
            <div class="demo-modal-body" style="padding:20px;">
              <div class="form-group" style="margin:0;">
                <label data-dialog-label for="${id}Input"></label>
                <input id="${id}Input" data-dialog-input type="text" maxlength="120" autocomplete="off">
                <div data-dialog-error role="alert" style="display:none;margin-top:8px;color:#ff8d8d;font-size:12px;"></div>
              </div>
            </div>
            <div class="demo-modal-footer">
              <button class="nav-btn" data-dialog-cancel type="button">Cancel</button>
              <button class="nav-btn primary" data-dialog-confirm type="submit"></button>
            </div>
          </form>
        </div>`;

      overlay.querySelector('[data-dialog-title]').textContent = title;
      overlay.querySelector('[data-dialog-label]').textContent = label;
      const input = overlay.querySelector('[data-dialog-input]');
      input.type = inputType;
      input.value = String(value ?? '');
      input.placeholder = placeholder;
      if (inputMode) input.inputMode = inputMode;
      if (min !== undefined) input.min = String(min);
      if (max !== undefined) input.max = String(max);
      if (step !== undefined) input.step = String(step);
      const error = overlay.querySelector('[data-dialog-error]');
      const confirmButton = overlay.querySelector('[data-dialog-confirm]');
      confirmButton.textContent = confirmLabel;
      const previousFocus = documentTarget.activeElement;

      const submit = async event => {
        event?.preventDefault?.();
        const nextValue = input.value.trim();
        if (!nextValue) {
          input.setAttribute('aria-invalid', 'true');
          error.textContent = emptyMessage;
          error.style.display = 'block';
          input.focus();
          return;
        }
        const validationMessage = await validate?.(nextValue);
        if (validationMessage) {
          input.setAttribute('aria-invalid', 'true');
          error.textContent = validationMessage;
          error.style.display = 'block';
          input.focus();
          input.select();
          return;
        }
        confirmButton.disabled = true;
        close();
        await onSubmit?.(nextValue);
      };
      const onKeyDown = event => {
        if (
          event.altKey
          && !event.metaKey
          && !event.ctrlKey
          && event.code === 'KeyR'
        ) {
          event.preventDefault();
          return;
        }
        if (event.key === 'Enter' && event.target === input) {
          submit(event);
          return;
        }
        if (event.key === 'Escape') {
          event.preventDefault();
          close();
        }
      };

      activeDialog = { overlay, previousFocus, onKeyDown };
      overlay.querySelector('[data-dialog-close]').addEventListener('click', close);
      overlay.querySelector('[data-dialog-cancel]').addEventListener('click', close);
      overlay.querySelector('[data-dialog-form]').addEventListener('submit', submit);
      overlay.addEventListener('click', event => {
        if (event.target === overlay) close();
      });
      input.addEventListener('input', () => {
        input.removeAttribute('aria-invalid');
        error.style.display = 'none';
      });
      documentTarget.addEventListener('keydown', onKeyDown);
      documentTarget.body.appendChild(overlay);
      input.focus();
      input.select();
      return { close, input };
    },
    close,
  };
}
