(function() {
  // 1. Detecția automată a URL-ului serverului Node.js
  const currentScript = document.currentScript;
  let SERVER_URL = 'http://localhost:3000'; // Portul implicit

  if (currentScript && currentScript.src) {
    try {
      const urlObj = new URL(currentScript.src);
      SERVER_URL = urlObj.origin;
    } catch (e) {
      console.error("Eroare detecție URL server:", e);
    }
  }

  // 2. Constante Rebus
  const HORIZONTAL = 0;
  const VERTICAL = 1;

  // 3. Librărie Base64 nativă (înlocuiește scriptul de pe CDN)
  const Base64 = {
    encode: (str) => btoa(unescape(encodeURIComponent(str))),
    decode: (str) => decodeURIComponent(escape(atob(str)))
  };

function injectStyles() {
    const styles = `
      div.crossword {
          display: inline-block;
          clear: both;
          margin: 0 auto;
      }
      div.crossword > div.endRow {
          display: block;
          width: 100%;
          height: 0;
          clear: both;
      }
      div.crossword > div.box {
          float: left;
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          position: relative;
          width: 50px !important;
          height: 50px !important;
          box-sizing: border-box;
          border: 1px solid black;
          overflow: hidden;
      }
      div.crossword > div.box.empty {
          background-color: black;
          border-color: black;
      }
      div.crossword > div.box .cluenum-in-box {
          position: absolute;
          top: 2px;
          left: 3px;
          font-size: 10px !important;
          line-height: 1;
          z-index: 10;
          pointer-events: none;
          color: #555;
          font-family: sans-serif;
      }
      .box.letter input {
          position: absolute;
          top: 0;
          left: 0;
          width: 50px !important;
          height: 50px !important;
          box-sizing: border-box;
          margin: 0;
          padding: 0;
          border: none;
          background-color: white;
          color: black;
          text-align: center;
          font-size: 24px;
          outline: none;
          text-transform: uppercase;
          transition: background-color 0.2s ease;
      }
      .box.letter input.correct {
          background-color: #d4edda !important;
          color: #155724 !important;
      }
      .box.letter input.wrong {
          background-color: #f8d7da !important;
          color: #721c24 !important;
      }
      .box.letter input:disabled {
          cursor: default;
      }
      .clues-panel {
          display: flex;
          gap: 32px;
          margin-top: 24px;
          font-family: sans-serif;
          text-align: left;
      }
      .clues-panel div {
          flex: 1;
      }

      .rebus-trigger-btn {
          padding: 14px 28px;
          font-size: 16px;
          font-weight: bold;
          color: #fff;
          background-color: #007bff;
          border: none;
          border-radius: 6px;
          cursor: pointer;
          font-family: sans-serif;
          box-shadow: 0 4px 6px rgba(0,0,0,0.1);
          transition: all 0.2s ease;
      }
      .rebus-trigger-btn:hover {
          background-color: #0056b3;
          transform: translateY(-1px);
      }
      .rebus-modal-overlay {
          position: fixed;
          top: 0; left: 0;
          width: 100%; height: 100%;
          background: rgba(0, 0, 0, 0.7);
          display: flex;
          justify-content: center;
          align-items: center;
          z-index: 999999;
          opacity: 0;
          visibility: hidden;
          transition: opacity 0.3s ease, visibility 0.3s ease;
      }
      .rebus-modal-overlay.active {
          opacity: 1;
          visibility: visible;
      }
      .rebus-modal-window {
          background: #fff;
          padding: 30px;
          border-radius: 12px;
          max-width: 95%;
          max-height: 90vh;
          overflow-y: auto;
          position: relative;
          box-shadow: 0 10px 30px rgba(0,0,0,0.25);
          animation: rebusScaleUp 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
          text-align: center;
      }
      .rebus-modal-close {
          position: absolute;
          top: 10px;
          right: 20px;
          font-size: 36px;
          background: none;
          border: none;
          cursor: pointer;
          color: #aaa;
          line-height: 1;
      }
      .rebus-modal-close:hover {
          color: #333;
      }
      @keyframes rebusScaleUp {
          from { transform: scale(0.9); opacity: 0; }
          to { transform: scale(1); opacity: 1; }
      }
    `;
    const styleSheet = document.createElement("style");
    styleSheet.innerText = styles;
    document.head.appendChild(styleSheet);
  }
  injectStyles();

// ─── Helper grid ──────────────────────────────────────────────────────────

function makeGrid(rows, cols) {
  return Array.from({ length: rows }, () => Array(cols).fill(null));
}

function gridRows(g) { return g.length; }
function gridCols(g) { return g[0]?.length ?? 0; }

function shuffle(arr) {
  for (let i = arr.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [arr[i], arr[j]] = [arr[j], arr[i]];
  }
  return arr;
}

// ─── Plasare ──────────────────────────────────────────────────────────────

// un caz boolean pt daca cuvantul are origine verticala sau orizontala pt vali

function place(word, grid, x, y, direction) {
  if (!grid) grid = makeGrid(30, 30);
  const g = grid.map(r => [...r]);
  for (let i = 0; i < word.length; i++) {
    if (direction === HORIZONTAL) g[y][x + i] = word[i];
    else                          g[y + i][x] = word[i];
  }
  return g;
}

function canPlace(word, grid, x, y) {
  const R = gridRows(grid);
  const C = gridCols(grid);

  // ── ORIZONTAL ──
  if (x + word.length <= C) {
    let ok = true, intersects = false;

    // Verifică celula din stânga capătului
    if (x > 0 && grid[y][x - 1] !== null) ok = false;

    // Verifică celula din dreapta capătului
    if (ok && x + word.length < C && grid[y][x + word.length] !== null) ok = false;

    if (ok) {
      for (let i = 0; i < word.length; i++) {
        const cx = x + i;
        const cell = grid[y][cx];

        if (cell !== null && cell !== word[i]) { ok = false; break; }
        if (cell === word[i]) {
          intersects = true;
          // La intersecție, cuvântul vertical existent "acoperă" celula — ok
          continue;
        }

        // Celulă goală — verifică vecini sus/jos (nu cumva facem un cuvânt nou)
        if (y > 0     && grid[y - 1][cx] !== null) { ok = false; break; }
        if (y < R - 1 && grid[y + 1][cx] !== null) { ok = false; break; }
      }
    }

    if (ok && intersects) return { ok: true, placement: { x, y, direction: HORIZONTAL } };
  }

  // ── VERTICAL ──
  if (y + word.length <= R) {
    let ok = true, intersects = false;

    // Verifică celula de deasupra capătului
    if (y > 0 && grid[y - 1][x] !== null) ok = false;

    // Verifică celula de sub capăt
    if (ok && y + word.length < R && grid[y + word.length][x] !== null) ok = false;

    if (ok) {
      for (let i = 0; i < word.length; i++) {
        const cy = y + i;
        const cell = grid[cy][x];

        if (cell !== null && cell !== word[i]) { ok = false; break; }
        if (cell === word[i]) {
          intersects = true;
          // La intersecție, cuvântul orizontal existent "acoperă" celula — ok
          continue;
        }

        // Celulă goală — verifică vecini stânga/dreapta (nu cumva facem un cuvânt nou)
        if (x > 0     && grid[cy][x - 1] !== null) { ok = false; break; }
        if (x < C - 1 && grid[cy][x + 1] !== null) { ok = false; break; }
      }
    }

    if (ok && intersects) return { ok: true, placement: { x, y, direction: VERTICAL } };
  }

  return { ok: false };
}
// ─── Scoring ──────────────────────────────────────────────────────────────

function getCells({ word, x, y, direction }) {
  return word.split('').map((_, i) =>
    direction === HORIZONTAL ? [y, x + i] : [y + i, x]
  );
}

function countIntersections(placements) {
  let count = 0;
  for (let i = 0; i < placements.length; i++) {
    for (let j = i + 1; j < placements.length; j++) {
      const cellsA = getCells(placements[i]);
      const cellsB = getCells(placements[j]);
      if (cellsA.some(([r1, c1]) => cellsB.some(([r2, c2]) => r1 === r2 && c1 === c2))) {
        count++;
      }
    }
  }
  return count;
}

function computeCompactness(placements) {
  let minR = Infinity, maxR = -Infinity, minC = Infinity, maxC = -Infinity;
  for (const p of placements) {
    for (const [r, c] of getCells(p)) {
      if (r < minR) minR = r; if (r > maxR) maxR = r;
      if (c < minC) minC = c; if (c > maxC) maxC = c;
    }
  }
  const area = (maxR - minR + 1) * (maxC - minC + 1);
  const wordCells = placements.reduce((s, p) => s + p.word.length, 0);
  return wordCells / area;
}

function generateScore(placements, wIntersect = 0.6, wCompact = 0.4) {
  const n = placements.length;
  if (n === 0) return 0;
  const intersectNorm = countIntersections(placements) / n;
  const compactNorm   = computeCompactness(placements);
  return wIntersect * intersectNorm + wCompact * compactNorm;
}

// function generateScore(placements) {
//   if (placements.length === 0) return 0;
//   return countIntersections(placements);
// }

// ─── Algoritm plasare (greedy local per cuvânt) ───────────────────────────

function iterativePlacement(wordList, maxWords = 10) {
  const ws = shuffle([...wordList]);

  const first = ws.shift();
  let crossword = place(first, null, 0, 0, HORIZONTAL);
  const placementsList = [{ word: first, x: 0, y: 0, direction: HORIZONTAL }];
  let count = 1;

  while (count < maxWords && ws.length > 0) {
    const word = ws.shift();

    // Colectează toți candidații posibili
    const candidates = [];
    for (const letter of word) {
      for (let y = 0; y < gridRows(crossword); y++) {
        for (let x = 0; x < gridCols(crossword); x++) {
          if (crossword[y][x] === letter) {
            const { ok, placement } = canPlace(word, crossword, x, y);
            if (ok) candidates.push(placement);
          }
        }
      }
    }

    // Alege candidatul cu scorul cel mai bun
    let bestScore = 0;
    let bestBoard = null;
    let bestPlacement = null;

    for (const candidate of candidates) {
      const newBoard = place(word, crossword, candidate.x, candidate.y, candidate.direction);
      const tempPlacements = [...placementsList, { word, ...candidate }];
      const newScore = generateScore(tempPlacements);
      if (newScore > bestScore) {
        bestScore     = newScore;
        bestBoard     = newBoard;
        bestPlacement = candidate;
      }
    }

    if (bestScore > 0 && bestBoard !== null) {
      crossword = bestBoard;
      placementsList.push({ word, ...bestPlacement });
      count++;
    }
  }

  return { crossword, placements: placementsList };
}

// ─── RepeatedGeneration (greedy global) ───────────────────────────────────

function repeatedGeneration(words, maxWords, iterations, wIntersect = 0.6, wCompact = 0.4) {
  let maxScore = 0;
  let bestCrossword = null;
  let bestPlacements = null;

  for (let i = 0; i < iterations; i++) {
    const { crossword, placements } = iterativePlacement(words, maxWords);
    const score = generateScore(placements, wIntersect, wCompact);
    if (score > maxScore) {
      maxScore      = score;
      bestCrossword = crossword;
      bestPlacements = placements;
    }
  }

  return { crossword: bestCrossword, placements: bestPlacements, score: maxScore };
}

// ─── toRows ───────────────────────────────────────────────────────────────

function toRows(grid, placements) {
  let minR = Infinity, maxR = -Infinity, minC = Infinity, maxC = -Infinity;

  // Calculate grid boundaries
  for (let r = 0; r < gridRows(grid); r++) {
    for (let c = 0; c < gridCols(grid); c++) {
      if (grid[r][c] !== null) {
        if (r < minR) minR = r; if (r > maxR) maxR = r;
        if (c < minC) minC = c; if (c > maxC) maxC = c;
      }
    }
  }

  const cellMeta = {};
  const sorted = [...placements].sort((a, b) => a.y !== b.y ? a.y - b.y : a.x - b.x);
  let numCounter = 1;

  sorted.forEach((p, idx) => {
    p.id = idx;
    const startKey = `${p.y},${p.x}`;
    
    if (!cellMeta[startKey]) {
      cellMeta[startKey] = { wordHoriz: null, wordVert: null, num: null };
    }
    
    // Dacă această căsuță de pornire nu are încă un număr atribuit, îi dăm unul
    if (!cellMeta[startKey].num) {
      cellMeta[startKey].num = numCounter++;
    }
    
    p.num = cellMeta[startKey].num; 
  });

  // Pass 2: Tag every individual letter coordinate with its specific Word ID
  sorted.forEach((p) => {
    for (let i = 0; i < p.word.length; i++) {
      const r = p.direction === VERTICAL ? p.y + i : p.y;
      const c = p.direction === HORIZONTAL ? p.x + i : p.x;
      const key = `${r},${c}`;
      
      if (!cellMeta[key]) {
        cellMeta[key] = { wordHoriz: null, wordVert: null, num: null };
      }
      
      if (p.direction === HORIZONTAL) cellMeta[key].wordHoriz = p.id;
      if (p.direction === VERTICAL) cellMeta[key].wordVert = p.id;
    }
  });

  const rows = [];
  for (let r = minR; r <= maxR; r++) {
    const row = [];
    for (let c = minC; c <= maxC; c++) {
      const cell = grid[r][c];
      if (cell === null) {
        row.push({ empty: true });
      } else {
        const meta = cellMeta[`${r},${c}`] || { wordHoriz: null, wordVert: null, num: null };
        row.push({
          letter: cell,
          num: meta.num,
          wordHoriz: meta.wordHoriz,
          wordVert: meta.wordVert
        });
      }
    }
    rows.push(row);
  }
  return rows;
}

// ─── createCrossword ──────────────────────────────────────────────────────

function createCrossword(words) {
  const { crossword, placements } = iterativePlacement(words);
  return toRows(crossword, placements);
}

// ─── View ─────────────────────────────────────────────────────────────────
function createCrossword_view(rows) {
    const container = document.createElement('div');
    container.className = 'crossword'; // Va primi stilul inline-block din CSS
    const totalRows = rows.length; const totalCols = rows[0]?.length ?? 0;

    rows.forEach((row, rIdx) => {
      row.forEach((cell, cIdx) => {
        const box = document.createElement('div');
        box.dataset.row = rIdx; box.dataset.col = cIdx;
        // Se aplică clasele tale care au float: left și dimensiunile de 50px
        box.className = cell.empty ? 'box empty' : 'box letter';

        if (!cell.empty) {
          // Numărul indiciului în colțul căsuței
          if (cell.num) {
            const num = document.createElement('span');
            num.className = 'cluenum-in-box';
            num.textContent = cell.num;
            box.appendChild(num);
          }

          // Căsuța de text (Input-ul)
          const input = document.createElement('input');
          input.type = 'text'; input.maxLength = 1;
          input.dataset.row = rIdx; input.dataset.col = cIdx;
          
          // Securizare răspuns în Base64 nativ
          input.dataset.answer = Base64.encode(cell.letter.toUpperCase());

          if (cell.wordHoriz !== null) input.dataset.wordHoriz = cell.wordHoriz;
          if (cell.wordVert !== null) input.dataset.wordVert = cell.wordVert;

          // Navigarea din săgeți și validarea la tastare
          input.addEventListener('keydown', (e) => handleNavigation(e, rIdx, cIdx, totalRows, totalCols));
          input.addEventListener('input', () => validate(rIdx, cIdx));
          box.appendChild(input);
        }
        container.appendChild(box);
      });

      // Rândul s-a terminat, injectăm div-ul tău de „clear: both”
      const endRow = document.createElement('div');
      endRow.className = 'endRow';
      container.appendChild(endRow);
    });

    return container;
  }

  // ─── VALIDARE, DIACRITICE & NAVIGARE DIN SĂGEȚI ───────────────────────────
  function normalizeRomanian(str) {
    if (!str) return '';
    return str.toUpperCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '')
      .replace(/[ĂÂ]/g, 'A').replace(/[ȘŞ]/g, 'S').replace(/[ȚŢ]/g, 'T').replace(/[Î]/g, 'I').trim();
  }

  // Verifică dacă un cuvânt întreg este completat corect
  function checkWordStatus(wordId, direction, container) {
    const attr = direction === 'horiz' ? `data-word-horiz` : `data-word-vert`;
    const inputs = container.querySelectorAll(`input[${attr}="${wordId}"]`);
    let allCorrect = true; let anyEmpty = false;

    inputs.forEach(input => {
      const userValue = input.value.trim().toUpperCase();
      if (userValue === '') anyEmpty = true;
      // Folosește noul Base64 nativ din script
      const correctAnswer = Base64.decode(input.dataset.answer);
      if (normalizeRomanian(userValue) !== normalizeRomanian(correctAnswer)) { allCorrect = false; }
    });
    return allCorrect && !anyEmpty;
  }

  // Colorează căsuțele în verde (correct) sau roșu (wrong)
  function validateWord(wordId, direction, container) {
    const attr = direction === 'horiz' ? `data-word-horiz` : `data-word-vert`;
    const inputs = container.querySelectorAll(`input[${attr}="${wordId}"]`);
    let allCorrect = true; let anyEmpty = false;

    inputs.forEach(input => {
      const userValue = input.value.trim().toUpperCase();
      if (userValue === '') anyEmpty = true;
      const correctAnswer = Base64.decode(input.dataset.answer);
      if (normalizeRomanian(userValue) !== normalizeRomanian(correctAnswer)) { allCorrect = false; }
    });

    inputs.forEach(input => {
      if (allCorrect && !anyEmpty) {
        input.classList.add('correct'); input.classList.remove('wrong');
        const horizId = input.dataset.wordHoriz; const vertId = input.dataset.wordVert;
        if (horizId !== undefined && vertId !== undefined) {
          if (checkWordStatus(horizId, 'horiz', container) && checkWordStatus(vertId, 'vert', container)) { input.disabled = true; }
        } else { input.disabled = true; }
      } else if (!anyEmpty && !allCorrect) {
        input.classList.add('wrong'); input.classList.remove('correct');
      } else {
        input.classList.remove('correct', 'wrong'); input.disabled = false;
      }
    });
  }

  function validate(rowIndex, colIndex) {
    const input = document.querySelector(`input[data-row="${rowIndex}"][data-col="${colIndex}"]`);
    if (!input) return;
    const container = input.closest('.crossword');
    const horizWordId = input.dataset.wordHoriz; const vertWordId = input.dataset.wordVert;
    if (horizWordId !== undefined) validateWord(horizWordId, 'horiz', container);
    if (vertWordId !== undefined)  validateWord(vertWordId, 'vert', container);
  }

  function handleNavigation(e, row, col, maxR, maxC) {
    const directions = { 'ArrowUp': [-1, 0], 'ArrowDown': [1, 0], 'ArrowLeft': [0, -1], 'ArrowRight': [0, 1] };
    if (!directions[e.key]) return;
    const [dr, dc] = directions[e.key];
    let currR = row + dr; let currC = col + dc;
    let targetInput = null; let attempts = 0; const maxAttempts = maxR * maxC;

    while (attempts < maxAttempts) {
      if (currR < 0) currR = maxR - 1; else if (currR >= maxR) currR = 0;
      if (currC < 0) currC = maxC - 1; else if (currC >= maxC) currC = 0;
      const nextBox = document.querySelector(`.box[data-row="${currR}"][data-col="${currC}"]`);
      const inputFound = nextBox ? nextBox.querySelector('input') : null;
      if (inputFound && !inputFound.disabled) { targetInput = inputFound; break; }
      currR += dr; currC += dc; attempts++;
    }
    if (targetInput) { e.preventDefault(); targetInput.focus(); }
  }

  // ─── PANOUL DE INDICII (Orizontal / Vertical) ────────────────────────────

  function createCluesPanel(data, placements) {

    const horizontal = placements.filter(p => p.direction === HORIZONTAL).sort((a, b) => a.y !== b.y ? a.y - b.y : a.x - b.x);
    const vertical = placements.filter(p => p.direction === VERTICAL).sort((a, b) => a.y !== b.y ? a.y - b.y : a.x - b.x);
    const clueMap = Object.fromEntries(data.map(item => [item.word, item.clue]));

    const panel = document.createElement('div');
    panel.className = 'clues-panel';

    function buildList(title, list) {
      const col = document.createElement('div');
      const h3 = document.createElement('h3'); h3.textContent = title;
      h3.style.cssText = 'margin-bottom:8px;font-size:16px;border-bottom:1px solid #ccc;padding-bottom:4px;';
      col.appendChild(h3);
      
    
      const ul = document.createElement('ul'); 
      ul.style.cssText = 'padding-left:0; margin:0; list-style-type: none;'; 

      list.forEach(p => {
        const li = document.createElement('li'); 
        li.style.cssText = 'margin-bottom:6px; font-size:14px; line-height: 1.4;';
        
        // Luăm indiciul corespunzător cuvântului
        const clueText = clueMap[p.word] ?? p.word; 
        
        const realNumber = p.num ?? "?"; 

        // Adăugăm numărul îngroșat în fața indiciului
        li.innerHTML = `<strong>${realNumber}.</strong> ${clueText}`; 
        
        ul.appendChild(li);
      });
      
      col.appendChild(ul); 
      return col;
    }

    panel.appendChild(buildList('Orizontal', horizontal));
    panel.appendChild(buildList('Vertical', vertical));
    return panel;
  }

  // Cererea HTTP automată către serverul local
  async function getWordsandClues() {
    const response = await fetch(`${SERVER_URL}/`);
    return await response.json();
  }


// ─── FUNCȚIA MAIN (Generare Interfață Modul Pop-up) ────────────────────────
  async function main() {
  
    injectStyles();

    const targetContainer = document.getElementById('rebus-container');
    if (!targetContainer) return;
    targetContainer.innerHTML = ''; 

    // 2. Creăm butonul declanșator pentru widget care va apărea pe site
    const openBtn = document.createElement('button');
    openBtn.className = 'rebus-trigger-btn';
    openBtn.textContent = 'Rezolvă Rebus Medical';
    targetContainer.appendChild(openBtn);

    // 3. Creăm structura de pop-up (fundalul întunecat)
    const overlay = document.createElement('div');
    overlay.className = 'rebus-modal-overlay';

    // Fereastra albă din interiorul pop-up-ului
    const modalWindow = document.createElement('div');
    modalWindow.className = 'rebus-modal-window';

    // Butonul de închidere (X)
    const closeBtn = document.createElement('button');
    closeBtn.className = 'rebus-modal-close';
    closeBtn.innerHTML = '&times;';
    modalWindow.appendChild(closeBtn);

    // Titlul din interiorul pop-up-ului
    const title = document.createElement('h2');
    title.textContent = 'Rebus Medical';
    title.style.cssText = 'margin-top:0;margin-bottom:25px;font-family:sans-serif;color:#333;';
    modalWindow.appendChild(title);

    try {
      // Chemăm datele de la server
      const data = await getWordsandClues();
      const words = data.map(item => item.word);

      // Generăm rebusul în memorie
      const { crossword, placements } = repeatedGeneration(words, 10, 20);
      const rows = toRows(crossword, placements);
      
      // Creăm elementele vizuale (grila și indiciile)
      const view = createCrossword_view(rows);
      const cluesPanel = createCluesPanel(data, placements);

      // Le asamblăm în interiorul ferestrei modale
      modalWindow.appendChild(view);
      modalWindow.appendChild(cluesPanel);
      overlay.appendChild(modalWindow);
      document.body.appendChild(overlay);

      // 4. Evenimente deschidere / închidere modal
      openBtn.addEventListener('click', () => overlay.classList.add('active'));
      closeBtn.addEventListener('click', () => overlay.classList.remove('active'));
      
      // Închide pop-up-ul dacă utilizatorul dă click pe fundalul negru din exterior
      overlay.addEventListener('click', (e) => { 
        if (e.target === overlay) overlay.classList.remove('active'); 
      });

    } catch (err) {
      console.error("Eroare la pornirea widget-ului:", err);
      openBtn.textContent = 'Server indisponibil';
      openBtn.disabled = true;
    }
  }

  // Pornim automat funcția main
  main();

})();