/**
 * kanban.js
 * ──────────────────────────────────────────────────────────────────────────────
 * Voll funktionsfähiges Kanban-Board (Trello-Style)
 *  • Spalten anlegen / umbenennen / löschen
 *  • Karten anlegen (contenteditable) / löschen
 *  • Drag & Drop zwischen Spalten + Reihenfolge innerhalb einer Spalte
 *  • Drop-Zonen-Visualisierung (dragenter / dragleave)
 *  • Farbige Labels per Rechtsklick-Kontextmenü
 *  • Vollständige Persistenz in localStorage
 *  • Export als JSON-Datei (Blob + createObjectURL)
 *  • Reset auf leeres Board
 * ──────────────────────────────────────────────────────────────────────────────
 */

(function () {
  'use strict';

  /* ═══════════════════════════════════════════════════════════════════════════
     Konstanten & State
  ═══════════════════════════════════════════════════════════════════════════ */
  const STORAGE_KEY = 'kanban_board_v2';

  const DEFAULT_BOARD = {
    columns: [
      {
        id: uid(),
        title: '📝 To Do',
        cards: [
          { id: uid(), text: 'Aufgabe 1 – Beispiel', label: '#60a5fa' },
          { id: uid(), text: 'Aufgabe 2 – Beispiel', label: 'none' },
        ],
      },
      {
        id: uid(),
        title: '⚙️ In Arbeit',
        cards: [
          { id: uid(), text: 'fetch & API integrieren', label: '#a78bfa' },
        ],
      },
      {
        id: uid(),
        title: '✅ Erledigt',
        cards: [
          { id: uid(), text: 'Dark Mode implementieren', label: '#4ade80' },
          { id: uid(), text: 'Hamburger-Menü Mobile', label: '#4ade80' },
        ],
      },
    ],
  };

  /* Laufender State (wird aus localStorage oder Default geladen) */
  let state = loadState();

  /* Drag-Kontext */
  let dragCardId   = null;   // ID der gezogenen Karte
  let dragColumnId = null;   // Quell-Spalte

  /* Label-Picker Kontext */
  let labelTargetCardId = null;

  /* ═══════════════════════════════════════════════════════════════════════════
     Utility
  ═══════════════════════════════════════════════════════════════════════════ */
  function uid () {
    return Date.now().toString(36) + Math.random().toString(36).slice(2, 7);
  }

  function loadState () {
    try {
      const raw = localStorage.getItem(STORAGE_KEY);
      if (raw) return JSON.parse(raw);
    } catch (_) {}
    // Deep-clone default so UIDs werden nur einmal erzeugt
    return JSON.parse(JSON.stringify(DEFAULT_BOARD));
  }

  function saveState () {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
  }

  function findColumn (colId) {
    return state.columns.find(c => c.id === colId);
  }

  function findCard (cardId) {
    for (const col of state.columns) {
      const card = col.cards.find(c => c.id === cardId);
      if (card) return { card, column: col };
    }
    return null;
  }

  /* ═══════════════════════════════════════════════════════════════════════════
     Board rendern
  ═══════════════════════════════════════════════════════════════════════════ */
  const board = document.getElementById('kanban-board');

  function renderBoard () {
    board.innerHTML = '';
    state.columns.forEach(col => board.appendChild(buildColumn(col)));
    // "Spalte hinzufügen"-Ghost am Ende (für Drop-Hint, optional)
  }

  /* ── Spalte bauen ────────────────────────────────────────────────────── */
  function buildColumn (colData) {
    const col = document.createElement('div');
    col.className = 'kanban-column';
    col.dataset.colId = colData.id;

    /* Header */
    const header = document.createElement('div');
    header.className = 'kanban-col-header';

    const titleEl = document.createElement('h2');
    titleEl.className = 'kanban-col-title';
    titleEl.textContent = colData.title;
    titleEl.title = 'Doppelklick zum Umbenennen';
    titleEl.addEventListener('dblclick', () => renameColumn(colData.id, titleEl));

    const badge = document.createElement('span');
    badge.className = 'kanban-col-badge';
    badge.textContent = colData.cards.length;

    const deleteColBtn = document.createElement('button');
    deleteColBtn.type = 'button';
    deleteColBtn.className = 'kanban-col-delete';
    deleteColBtn.title = 'Spalte löschen';
    deleteColBtn.innerHTML = '✕';
    deleteColBtn.addEventListener('click', () => deleteColumn(colData.id));

    header.appendChild(titleEl);
    header.appendChild(badge);
    header.appendChild(deleteColBtn);

    /* Karten-Liste */
    const cardList = document.createElement('ul');
    cardList.className = 'kanban-card-list';
    cardList.dataset.colId = colData.id;

    colData.cards.forEach(cardData => {
      cardList.appendChild(buildCard(cardData, colData.id));
    });

    /* Drop-Placeholder (sichtbar beim Drag) */
    const placeholder = document.createElement('li');
    placeholder.className = 'kanban-drop-placeholder';
    placeholder.dataset.placeholder = 'true';

    /* Drag-Events auf cardList */
    cardList.addEventListener('dragover',  e => onCardListDragOver(e, cardList));
    cardList.addEventListener('dragenter', e => onColumnDragEnter(e, col));
    cardList.addEventListener('dragleave', e => onColumnDragLeave(e, col));
    cardList.addEventListener('drop',      e => onCardListDrop(e, colData.id, cardList));

    /* Footer: + Karte Button */
    const footer = document.createElement('div');
    footer.className = 'kanban-col-footer';
    const addCardBtn = document.createElement('button');
    addCardBtn.type = 'button';
    addCardBtn.className = 'btn-add-card';
    addCardBtn.textContent = '+ Karte';
    addCardBtn.addEventListener('click', () => addCard(colData.id, cardList, badge, colData));
    footer.appendChild(addCardBtn);

    col.appendChild(header);
    col.appendChild(cardList);
    col.appendChild(footer);
    return col;
  }

  /* ── Karte bauen ─────────────────────────────────────────────────────── */
  function buildCard (cardData, colId) {
    const li = document.createElement('li');
    li.className = 'kanban-card';
    li.draggable = true;
    li.dataset.cardId = cardData.id;
    li.dataset.colId  = colId;

    /* Label-Streifen */
    const labelBar = document.createElement('div');
    labelBar.className = 'kanban-card-label';
    if (cardData.label && cardData.label !== 'none') {
      labelBar.style.background = cardData.label;
    } else {
      labelBar.style.display = 'none';
    }

    /* Text (contenteditable) */
    const textEl = document.createElement('div');
    textEl.className = 'kanban-card-text';
    textEl.contentEditable = 'true';
    textEl.spellcheck = false;
    textEl.textContent = cardData.text;
    textEl.setAttribute('aria-label', 'Kartentext bearbeiten');

    textEl.addEventListener('blur', () => {
      const result = findCard(cardData.id);
      if (result) {
        result.card.text = textEl.textContent.trim() || result.card.text;
        saveState();
      }
    });
    // Enter → Blur statt Zeilenumbruch
    textEl.addEventListener('keydown', e => {
      if (e.key === 'Enter') { e.preventDefault(); textEl.blur(); }
    });

    /* Löschen-Button */
    const deleteBtn = document.createElement('button');
    deleteBtn.type = 'button';
    deleteBtn.className = 'kanban-card-delete';
    deleteBtn.title = 'Karte löschen';
    deleteBtn.innerHTML = '✕';
    deleteBtn.addEventListener('click', () => deleteCard(cardData.id));

    li.appendChild(labelBar);
    li.appendChild(textEl);
    li.appendChild(deleteBtn);

    /* Drag Events */
    li.addEventListener('dragstart', e => onCardDragStart(e, cardData.id, colId, li));
    li.addEventListener('dragend',   () => onCardDragEnd());

    /* Rechtsklick → Label Picker */
    li.addEventListener('contextmenu', e => {
      e.preventDefault();
      openLabelPicker(e, cardData.id);
    });

    return li;
  }

  /* ═══════════════════════════════════════════════════════════════════════════
     Spalten-Operationen
  ═══════════════════════════════════════════════════════════════════════════ */
  function addColumn () {
    const name = prompt('Name der neuen Spalte:');
    if (!name || !name.trim()) return;
    const colData = { id: uid(), title: name.trim(), cards: [] };
    state.columns.push(colData);
    saveState();
    renderBoard();
  }

  function renameColumn (colId, titleEl) {
    const col = findColumn(colId);
    if (!col) return;
    const oldTitle = col.title;
    titleEl.contentEditable = 'true';
    titleEl.focus();
    // Cursor ans Ende
    const range = document.createRange();
    range.selectNodeContents(titleEl);
    range.collapse(false);
    window.getSelection().removeAllRanges();
    window.getSelection().addRange(range);

    function finish () {
      titleEl.contentEditable = 'false';
      col.title = titleEl.textContent.trim() || oldTitle;
      titleEl.textContent = col.title;
      saveState();
    }
    titleEl.addEventListener('blur',    finish, { once: true });
    titleEl.addEventListener('keydown', e => {
      if (e.key === 'Enter') { e.preventDefault(); titleEl.blur(); }
      if (e.key === 'Escape') { titleEl.textContent = oldTitle; titleEl.blur(); }
    }, { once: true });
  }

  function deleteColumn (colId) {
    const col = findColumn(colId);
    if (!col) return;
    const count = col.cards.length;
    const msg = count > 0
      ? `Spalte "${col.title}" mit ${count} Karte(n) löschen?`
      : `Spalte "${col.title}" löschen?`;
    if (!confirm(msg)) return;
    state.columns = state.columns.filter(c => c.id !== colId);
    saveState();
    renderBoard();
  }

  /* ═══════════════════════════════════════════════════════════════════════════
     Karten-Operationen
  ═══════════════════════════════════════════════════════════════════════════ */
  function addCard (colId, cardList, badge, colData) {
    const cardData = { id: uid(), text: 'Neue Karte…', label: 'none' };
    colData.cards.push(cardData);
    saveState();

    const li = buildCard(cardData, colId);
    // Vor dem Placeholder (falls vorhanden), sonst ans Ende
    const ph = cardList.querySelector('[data-placeholder]');
    if (ph) cardList.insertBefore(li, ph);
    else cardList.appendChild(li);

    badge.textContent = colData.cards.length;

    // Direkt zum Bearbeiten fokussieren
    const textEl = li.querySelector('.kanban-card-text');
    textEl.focus();
    // Alles selektieren
    document.execCommand('selectAll', false, null);
  }

  function deleteCard (cardId) {
    for (const col of state.columns) {
      const idx = col.cards.findIndex(c => c.id === cardId);
      if (idx !== -1) {
        col.cards.splice(idx, 1);
        saveState();
        renderBoard();
        return;
      }
    }
  }

  /* ═══════════════════════════════════════════════════════════════════════════
     Drag & Drop
  ═══════════════════════════════════════════════════════════════════════════ */
  function onCardDragStart (e, cardId, colId, li) {
    dragCardId   = cardId;
    dragColumnId = colId;
    li.classList.add('dragging');
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.setData('text/plain', cardId); // Firefox fix
  }

  function onCardDragEnd () {
    dragCardId   = null;
    dragColumnId = null;
    // Alle Highlights entfernen
    document.querySelectorAll('.kanban-column.drag-over').forEach(c => c.classList.remove('drag-over'));
    document.querySelectorAll('.kanban-card.dragging').forEach(c => c.classList.remove('dragging'));
    document.querySelectorAll('.kanban-drop-placeholder').forEach(p => p.remove());
  }

  function onColumnDragEnter (e, colEl) {
    e.preventDefault();
    colEl.classList.add('drag-over');
  }

  function onColumnDragLeave (e, colEl) {
    // Nur entfernen, wenn wirklich die Spalte verlassen wird (nicht ein Kind)
    if (!colEl.contains(e.relatedTarget)) {
      colEl.classList.remove('drag-over');
    }
  }

  /**
   * Bestimmt, vor welchem Element die Karte eingesetzt werden soll.
   * Gibt null zurück → ans Ende der Liste.
   */
  function getDragAfterElement (cardList, clientY) {
    const draggableEls = [...cardList.querySelectorAll('.kanban-card:not(.dragging)')];
    let closest = { offset: Number.NEGATIVE_INFINITY, element: null };
    for (const el of draggableEls) {
      const box    = el.getBoundingClientRect();
      const offset = clientY - box.top - box.height / 2;
      if (offset < 0 && offset > closest.offset) {
        closest = { offset, element: el };
      }
    }
    return closest.element;
  }

  function onCardListDragOver (e, cardList) {
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';

    // Placeholder bewegen
    let ph = cardList.querySelector('.kanban-drop-placeholder');
    if (!ph) {
      ph = document.createElement('li');
      ph.className = 'kanban-drop-placeholder';
      ph.dataset.placeholder = 'true';
    }
    const after = getDragAfterElement(cardList, e.clientY);
    if (after) cardList.insertBefore(ph, after);
    else        cardList.appendChild(ph);
  }

  function onCardListDrop (e, targetColId, cardList) {
    e.preventDefault();
    if (!dragCardId) return;

    const targetCol = findColumn(targetColId);
    const result    = findCard(dragCardId);
    if (!result || !targetCol) return;

    const { card, column: sourceCol } = result;

    // Aus Quell-Spalte entfernen
    sourceCol.cards = sourceCol.cards.filter(c => c.id !== dragCardId);

    // Einfügeposition bestimmen (anhand Placeholder)
    const ph = cardList.querySelector('.kanban-drop-placeholder');
    let insertIndex = targetCol.cards.length; // Default: ans Ende

    if (ph) {
      // Placeholder-Position im DOM → entsprechende Index im State
      const siblings = [...cardList.querySelectorAll('.kanban-card')];
      const phIndex  = [...cardList.children].indexOf(ph);
      // Karten vor dem Placeholder zählen
      let count = 0;
      for (const sib of cardList.children) {
        if (sib === ph) break;
        if (sib.classList.contains('kanban-card')) count++;
      }
      insertIndex = count;
    }

    targetCol.cards.splice(insertIndex, 0, card);
    saveState();
    renderBoard();
  }

  /* ═══════════════════════════════════════════════════════════════════════════
     Label Picker
  ═══════════════════════════════════════════════════════════════════════════ */
  const labelPicker = document.getElementById('label-picker');

  function openLabelPicker (e, cardId) {
    labelTargetCardId = cardId;
    labelPicker.removeAttribute('hidden');

    // Positionieren
    const x = Math.min(e.clientX, window.innerWidth  - labelPicker.offsetWidth  - 12);
    const y = Math.min(e.clientY, window.innerHeight - labelPicker.offsetHeight - 12);
    labelPicker.style.left = (x + window.scrollX) + 'px';
    labelPicker.style.top  = (y + window.scrollY) + 'px';
  }

  function closeLabelPicker () {
    labelPicker.setAttribute('hidden', '');
    labelTargetCardId = null;
  }

  labelPicker.querySelectorAll('.label-swatch').forEach(swatch => {
    swatch.addEventListener('click', () => {
      if (!labelTargetCardId) return;
      const result = findCard(labelTargetCardId);
      if (!result) return;
      result.card.label = swatch.dataset.color;
      saveState();
      renderBoard();
      closeLabelPicker();
    });
  });

  document.addEventListener('click', e => {
    if (!labelPicker.hasAttribute('hidden') && !labelPicker.contains(e.target)) {
      closeLabelPicker();
    }
  });

  document.addEventListener('keydown', e => {
    if (e.key === 'Escape') closeLabelPicker();
  });

  /* ═══════════════════════════════════════════════════════════════════════════
     Toolbar-Aktionen
  ═══════════════════════════════════════════════════════════════════════════ */

  /* + Spalte */
  document.getElementById('btn-add-column').addEventListener('click', addColumn);

  /* Export JSON */
  document.getElementById('btn-export').addEventListener('click', () => {
    const json     = JSON.stringify(state, null, 2);
    const blob     = new Blob([json], { type: 'application/json' });
    const url      = URL.createObjectURL(blob);
    const a        = document.createElement('a');
    a.href         = url;
    a.download     = 'kanban-board-' + new Date().toISOString().slice(0, 10) + '.json';
    document.body.appendChild(a);
    a.click();
    a.remove();
    URL.revokeObjectURL(url);
  });

  /* Reset */
  document.getElementById('btn-reset').addEventListener('click', () => {
    if (!confirm('Board komplett zurücksetzen? Alle Daten gehen verloren!')) return;
    localStorage.removeItem(STORAGE_KEY);
    state = JSON.parse(JSON.stringify(DEFAULT_BOARD));
    // Neue IDs erzeugen damit UIDs nicht doppelt sind
    state.columns.forEach(col => {
      col.id = uid();
      col.cards.forEach(card => { card.id = uid(); });
    });
    saveState();
    renderBoard();
  });

  /* ═══════════════════════════════════════════════════════════════════════════
     Init
  ═══════════════════════════════════════════════════════════════════════════ */
  renderBoard();

})();
