/**
 * Gemeinsame Hotkey-Hilfen – u. a. Dead Keys (^ auf CH-Tastaturen) via event.code.
 */
(function (global) {
  'use strict';

  const PHYSICAL_KEY_LABELS = {
    Equal: '^',
    Backquote: '^',
    IntlBackslash: '§',
    Backslash: '§',
    Minus: '-',
    BracketLeft: '[',
    BracketRight: ']',
    Semicolon: ';',
    Quote: "'",
    Comma: ',',
    Period: '.',
    Slash: '/',
  };

  function physicalKeyLabel(code, fallbackKey) {
    const c = String(code || '').trim();
    if (c && PHYSICAL_KEY_LABELS[c]) return PHYSICAL_KEY_LABELS[c];
    const fk = String(fallbackKey || '').trim();
    if (fk && fk !== 'Dead') return fk;
    return c || fk || '';
  }

  function formatHotkeyKeyLabel(key, code) {
    const labels = {
      ArrowLeft: 'Linkstaste',
      ArrowRight: 'Rechtstaste',
      ArrowUp: 'Oben',
      ArrowDown: 'Unten',
      Enter: 'Enter',
      Tab: 'Tab',
      ' ': 'Leertaste',
    };
    const k = String(key || '').trim();
    if (labels[k]) return labels[k];
    if (k && k !== 'Dead') {
      if (k.length === 1 && /[a-z]/i.test(k)) return k.toUpperCase();
      return k;
    }
    const fromCode = physicalKeyLabel(code, '');
    if (fromCode) return fromCode;
    return k || code || '';
  }

  function hotkeyFromKeyboardEvent(event) {
    if (!event) return null;
    if (['Control', 'Shift', 'Alt', 'Meta'].includes(event.key)) return null;

    const code = String(event.code || '').trim();
    const isDead = event.key === 'Dead';
    if (!isDead && !event.key && !code) return null;

    let key = event.key;
    let deadKey = false;
    if (isDead) {
      deadKey = true;
      key = physicalKeyLabel(code, '') || code;
    } else if (String(key).length === 1 && key !== ' ') {
      key = /[a-z]/i.test(key) ? key.toUpperCase() : key;
    }

    if (!key && code) key = physicalKeyLabel(code, code);

    return {
      key,
      code,
      deadKey,
      ctrlKey: !!event.ctrlKey,
      shiftKey: !!event.shiftKey,
      altKey: !!event.altKey,
      metaKey: !!event.metaKey,
    };
  }

  function hotkeyEventKeyMatches(hk, event, extraKeyChars) {
    const storedCode = String(hk?.code || '').trim();
    if (storedCode && String(event?.code || '') === storedCode) {
      return true;
    }

    const targetKey = String(hk?.key || '').toUpperCase();
    const eventKey = String(event?.key || '');
    const codeMatch = event.code === hk?.key
      || event.code === `Key${targetKey}`
      || event.code === `Digit${targetKey}`;
    const extra = extraKeyChars instanceof Set ? extraKeyChars : null;
    const macAltJQuirk = hk?.altKey && targetKey === 'J'
      && (event.code === 'KeyJ' || (extra && extra.has(eventKey)));
    return eventKey.toUpperCase() === targetKey
      || codeMatch
      || macAltJQuirk;
  }

  function hotkeysStructurallyEqual(a, b) {
    if (!a?.key && !a?.code) return !b?.key && !b?.code;
    if (!b?.key && !b?.code) return false;
    const sameCode = !!(a.code && b.code && a.code === b.code);
    const sameKey = String(a.key || '').toUpperCase() === String(b.key || '').toUpperCase();
    if (!sameCode && !sameKey) return false;
    return !!a.altKey === !!b.altKey
      && !!a.ctrlKey === !!b.ctrlKey
      && !!a.shiftKey === !!b.shiftKey
      && !!a.metaKey === !!b.metaKey;
  }

  global.chillicollectivoPhysicalKeyLabel = physicalKeyLabel;
  global.chillicollectivoFormatHotkeyKeyLabel = formatHotkeyKeyLabel;
  global.chillicollectivoHotkeyFromKeyboardEvent = hotkeyFromKeyboardEvent;
  global.chillicollectivoHotkeyEventKeyMatches = hotkeyEventKeyMatches;
  global.chillicollectivoHotkeysStructurallyEqual = hotkeysStructurallyEqual;
})(typeof globalThis !== 'undefined' ? globalThis : window);
