const STORAGE_KEY_STATS = 'sk_cases_stats_v1';
const STORAGE_KEY_CUSTOM = 'sk_cases_custom_words_v1';

let ALL_NOUNS = [...BASE_NOUNS];
let state = {
  drillMode: 'noun',   // 'noun' | 'phrase'
  inputMode: 'type',   // 'type' | 'choice'
  filterPattern: 'all',
  filterCase: 'all',
  filterNumber: 'all',
  hidePattern: false,
  currentQ: null,
  answered: false,
  streak: 0
};

let stats = loadStats();

function loadStats() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY_STATS);
    if (raw) return JSON.parse(raw);
  } catch (_) {}
  return { total: 0, correct: 0, streak: 0, bestStreak: 0, weak: {} };
}

function saveStats() {
  localStorage.setItem(STORAGE_KEY_STATS, JSON.stringify(stats));
}

function loadCustomWords() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY_CUSTOM);
    if (raw) {
      const parsed = JSON.parse(raw);
      if (Array.isArray(parsed)) {
        ALL_NOUNS = [...BASE_NOUNS, ...parsed];
      }
    }
  } catch (_) {}
}

// Инициализация
loadCustomWords();
state.streak = stats.streak || 0;
updateStreakUI();
renderRules();
renderDict();
populatePatternFilter();
nextQuestion();

// Регистрация PWA Service Worker
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('./sw.js').catch(() => {});
  });
}

// Вкладки
document.querySelectorAll('.tab').forEach(btn => {
  btn.addEventListener('click', () => {
    document.querySelectorAll('.tab').forEach(b => b.classList.remove('active'));
    document.querySelectorAll('.tab-panel').forEach(p => p.classList.remove('active'));
    btn.classList.add('active');
    document.getElementById(`tab-${btn.dataset.tab}`).classList.add('active');
    if (btn.dataset.tab === 'dict') renderStats();
  });
});

// Переключатели режимов
document.querySelectorAll('#drill-mode-seg .seg-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    document.querySelectorAll('#drill-mode-seg .seg-btn').forEach(b => b.classList.remove('active'));
    btn.classList.add('active');
    state.drillMode = btn.dataset.mode;
    nextQuestion();
  });
});

document.querySelectorAll('#input-mode-seg .seg-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    document.querySelectorAll('#input-mode-seg .seg-btn').forEach(b => b.classList.remove('active'));
    btn.classList.add('active');
    state.inputMode = btn.dataset.input;
    renderInputArea();
  });
});

document.getElementById('toggle-filters-btn').addEventListener('click', () => {
  document.getElementById('filters-panel').classList.toggle('hidden');
});

document.getElementById('filter-pattern').addEventListener('change', (e) => {
  state.filterPattern = e.target.value;
  nextQuestion();
});
document.getElementById('filter-case').addEventListener('change', (e) => {
  state.filterCase = e.target.value;
  nextQuestion();
});
document.getElementById('filter-number').addEventListener('change', (e) => {
  state.filterNumber = e.target.value;
  nextQuestion();
});
document.getElementById('filter-hide-pattern').addEventListener('change', (e) => {
  state.hidePattern = e.target.checked;
  updatePatternBadge();
});

// Панель диакритики
const answerInput = document.getElementById('answer-input');
document.getElementById('diacritic-bar').addEventListener('click', (e) => {
  const btn = e.target.closest('button[data-ch]');
  if (!btn || state.answered) return;
  const ch = btn.dataset.ch;
  const start = answerInput.selectionStart ?? answerInput.value.length;
  const end = answerInput.selectionEnd ?? answerInput.value.length;
  answerInput.value = answerInput.value.slice(0, start) + ch + answerInput.value.slice(end);
  answerInput.focus();
  answerInput.setSelectionRange(start + 1, start + 1);
});

// Выбор подходящего существительного с весом по ошибкам (SRS)
function pickWeightedNoun(pool) {
  const weights = pool.map(w => {
    const key = `p:${w.pattern}`;
    const err = stats.weak[key] || 0;
    return 1 + Math.min(err, 6);
  });
  const totalW = weights.reduce((a, b) => a + b, 0);
  let r = Math.random() * totalW;
  for (let i = 0; i < pool.length; i++) {
    r -= weights[i];
    if (r <= 0) return pool[i];
  }
  return pool[0];
}

function pickCompatibleAdj(noun) {
  const cats = noun.cats || ['thing'];
  const compatible = ADJECTIVES.filter(a => a.cats.some(c => cats.includes(c)));
  const pool = compatible.length ? compatible : ADJECTIVES;
  return pool[Math.floor(Math.random() * pool.length)];
}

function nextQuestion() {
  state.answered = false;
  document.getElementById('feedback-box').classList.add('hidden');
  answerInput.value = '';
  answerInput.disabled = false;

  const nounPool = state.filterPattern === 'all'
    ? ALL_NOUNS
    : ALL_NOUNS.filter(n => n.pattern === state.filterPattern);

  const noun = pickWeightedNoun(nounPool.length ? nounPool : ALL_NOUNS);
  const casePool = state.filterCase === 'all'
    ? CASES
    : CASES.filter(c => c.id === state.filterCase);
  const caseObj = casePool[Math.floor(Math.random() * casePool.length)];

  const num = state.filterNumber === 'all'
    ? (Math.random() < 0.52 ? 'sg' : 'pl')
    : state.filterNumber;

  let adj = null;
  if (state.drillMode === 'phrase') {
    adj = pickCompatibleAdj(noun);
  }

  const accepted = getAcceptedAnswers(noun, adj, num, caseObj.id);
  const primary = accepted[0];
  const choices = buildDistractors(noun, adj, num, caseObj.id, primary);

  state.currentQ = { noun, adj, caseObj, num, accepted, primary, choices };

  // Отрисовка карточки
  const numLabel = num === 'sg' ? 'Ед.ч.' : 'Мн.ч.';
  document.getElementById('q-case-badge').textContent = `${caseObj.name} (${caseObj.q}) · ${numLabel}`;
  updatePatternBadge();

  document.getElementById('q-trigger').textContent = caseObj.trigger;

  if (adj) {
    const gGroup = getGenderGroup(noun, 'sg');
    const baseAdj = declineAdjective(adj, gGroup, 'sg', 'N');
    document.getElementById('q-base').textContent = `${baseAdj} ${noun.base}`;
    document.getElementById('q-ru').textContent = `${adj.ru} · ${noun.ru} (${num === 'sg' ? 'ед.ч.' : 'мн.ч.'})`;
  } else {
    document.getElementById('q-base').textContent = noun.base;
    document.getElementById('q-ru').textContent = `${noun.ru} (${num === 'sg' ? 'ед.ч.' : 'мн.ч.'})`;
  }

  renderInputArea();
  if (state.inputMode === 'type') {
    answerInput.focus();
  }
}

function updatePatternBadge() {
  if (!state.currentQ) return;
  const badge = document.getElementById('q-pattern-badge');
  badge.textContent = state.hidePattern ? 'образец скрыт' : `vzor ${state.currentQ.noun.pattern}`;
}

function renderInputArea() {
  const typeArea = document.getElementById('type-area');
  const choiceArea = document.getElementById('choice-area');
  if (state.inputMode === 'type') {
    typeArea.classList.remove('hidden');
    choiceArea.classList.add('hidden');
  } else {
    typeArea.classList.add('hidden');
    choiceArea.classList.remove('hidden');
    if (state.currentQ) {
      choiceArea.innerHTML = '';
      state.currentQ.choices.forEach(opt => {
        const b = document.createElement('button');
        b.type = 'button';
        b.className = 'choice-btn';
        b.textContent = opt;
        b.addEventListener('click', () => handleChoice(opt, b));
        choiceArea.appendChild(b);
      });
    }
  }
}

document.getElementById('answer-form').addEventListener('submit', (e) => {
  e.preventDefault();
  if (state.answered) {
    nextQuestion();
    return;
  }
  const userAns = normalizeInput(answerInput.value);
  if (!userAns) return;
  evaluateAnswer(userAns);
});

function handleChoice(opt, btnEl) {
  if (state.answered) return;
  const isOk = state.currentQ.accepted.includes(opt);
  document.querySelectorAll('.choice-btn').forEach(b => {
    b.disabled = true;
    if (state.currentQ.accepted.includes(b.textContent)) b.classList.add('correct');
    else if (b === btnEl && !isOk) b.classList.add('wrong');
  });
  evaluateAnswer(opt);
}

function buildExplanation(q) {
  const { noun, adj, caseObj, num } = q;
  const parts = [];
  parts.push(`Образец: <b>${noun.pattern}</b>, ${caseObj.name} ${num === 'sg' ? 'ед.ч.' : 'мн.ч.'}`);
  if (noun.isAnimal && num === 'pl') {
    parts.push(`Животное во мн.ч. склоняется как неодушевлённое (<b>${noun.plPattern}</b>).`);
  }
  if (noun.longStem || (adj && adj.longStem)) {
    parts.push('Учтите закон ритмического сокращения после долгого слога.');
  }
  if (adj) {
    parts.push(`Прилагательное: образец <b>${adj.pattern}</b>.`);
  }
  return parts.join(' ');
}

function evaluateAnswer(userAns) {
  state.answered = true;
  answerInput.disabled = true;
  const q = state.currentQ;
  const normAccepted = q.accepted.map(a => normalizeInput(a));

  const exact = normAccepted.includes(userAns);
  const foldedMatch = !exact && normAccepted.some(a => foldDiacritics(a) === foldDiacritics(userAns));

  stats.total += 1;
  const weakCaseKey = `c:${q.caseObj.id}`;
  const weakPatKey = `p:${q.noun.pattern}`;

  const fb = document.getElementById('feedback-box');
  const fbHead = document.getElementById('feedback-head');
  const fbAns = document.getElementById('feedback-answer');
  const fbNote = document.getElementById('feedback-note');

  fb.classList.remove('hidden', 'ok', 'warn', 'bad');

  if (exact) {
    stats.correct += 1;
    stats.streak += 1;
    stats.bestStreak = Math.max(stats.bestStreak, stats.streak);
    if (stats.weak[weakPatKey] > 0) stats.weak[weakPatKey] -= 1;
    if (stats.weak[weakCaseKey] > 0) stats.weak[weakCaseKey] -= 1;

    fb.classList.add('ok');
    fbHead.textContent = '✓ Верно!';
  } else if (foldedMatch) {
    stats.streak = 0;
    stats.weak[weakPatKey] = (stats.weak[weakPatKey] || 0) + 1;

    fb.classList.add('warn');
    fbHead.textContent = '⚠ Почти! Проверьте долготу (á/í/ý) или гачек (č/ň/ľ)';
  } else {
    stats.streak = 0;
    stats.weak[weakPatKey] = (stats.weak[weakPatKey] || 0) + 2;
    stats.weak[weakCaseKey] = (stats.weak[weakCaseKey] || 0) + 2;

    fb.classList.add('bad');
    fbHead.textContent = '✕ Ошибка';
  }

  state.streak = stats.streak;
  updateStreakUI();
  saveStats();

  const prepShown = q.caseObj.trigger.replace('___', '');
  fbAns.textContent = `${prepShown}${q.accepted.join(' / ')}`;
  fbNote.innerHTML = buildExplanation(q);
}

function updateStreakUI() {
  document.getElementById('streak-count').textContent = state.streak;
}

document.getElementById('next-btn').addEventListener('click', nextQuestion);
document.getElementById('show-table-btn').addEventListener('click', () => {
  if (state.currentQ) openNounModal(state.currentQ.noun);
});

// Рендер справочника (Правила)
function renderRules() {
  const casesEl = document.getElementById('cases-guide');
  casesEl.innerHTML = CASES.map((c, idx) => `
    <div class="case-row">
      <strong>${idx + 1}. ${c.name}</strong> (${c.ru}) — <em>${c.q}</em> · <code>${c.trigger}</code><br>
      <span class="muted">${c.tip}</span>
    </div>
  `).join('');

  const patEl = document.getElementById('patterns-guide');
  patEl.innerHTML = '';
  PATTERNS.forEach(pat => {
    const sample = BASE_NOUNS.find(n => n.pattern === pat.id);
    const decl = declineNoun(sample);
    const wrap = document.createElement('div');
    wrap.className = 'pattern-item';
    wrap.innerHTML = `
      <button type="button" class="pattern-summary">
        <div>
          <div class="pattern-title">${pat.id} <span class="muted">(${pat.gender})</span></div>
          <div class="pattern-rule">${pat.rule}</div>
          <div class="pattern-ex">Пример: ${pat.example}</div>
        </div>
        <span>▾</span>
      </button>
      <div class="pattern-table-wrap hidden">
        <p class="muted" style="margin-bottom:8px;">${pat.note}</p>
        ${renderDeclTableHTML(decl)}
      </div>
    `;
    wrap.querySelector('.pattern-summary').addEventListener('click', () => {
      wrap.querySelector('.pattern-table-wrap').classList.toggle('hidden');
    });
    patEl.appendChild(wrap);
  });

  // Таблица прилагательных pekný / cudzí
  const adjEl = document.getElementById('adj-guide');
  const pekny = ADJECTIVES.find(a => a.base === 'pekný');
  const cudzi = ADJECTIVES.find(a => a.base === 'cudzí');
  adjEl.innerHTML = `
    <table class="decl-table">
      <thead>
        <tr><th>Падеж</th><th>pekný (М/Ср ед.ч.)</th><th>pekná (Ж ед.ч.)</th><th>Мн.ч. (одуш. / ост.)</th></tr>
      </thead>
      <tbody>
        ${CASES.map(c => `
          <tr>
            <td><strong>${c.name}</strong></td>
            <td>${declineAdjective(pekny, 'Ma', 'sg', c.id)} / ${declineAdjective(pekny, 'N', 'sg', c.id)}</td>
            <td>${declineAdjective(pekny, 'F', 'sg', c.id)}</td>
            <td>${declineAdjective(pekny, 'Ma', 'pl', c.id)} / ${declineAdjective(pekny, 'Mi', 'pl', c.id)}</td>
          </tr>
        `).join('')}
      </tbody>
    </table>
    <p class="muted" style="margin-top:8px;">
      Мягкий образец <strong>cudzí</strong>: <em>cudzí / cudzia / cudzie, cudzieho, cudziemu, cudzom, cudzím</em>; мн.ч. <em>cudzí / cudzie, cudzích, cudzím, cudzími</em>.
    </p>
  `;
}

function renderDeclTableHTML(decl) {
  return `
    <table class="decl-table">
      <thead>
        <tr><th>Падеж</th><th>Ед. число (Sg)</th><th>Мн. число (Pl)</th></tr>
      </thead>
      <tbody>
        ${CASES.map(c => `
          <tr>
            <td><strong>${c.name}</strong><br><span class="muted">${c.q}</span></td>
            <td>${decl.sg[c.id]}</td>
            <td>${decl.pl[c.id]}</td>
          </tr>
        `).join('')}
      </tbody>
    </table>
  `;
}

// Словарь и статистика
function populatePatternFilter() {
  const sel = document.getElementById('dict-pattern-filter');
  PATTERNS.forEach(p => {
    const opt = document.createElement('option');
    opt.value = p.id;
    opt.textContent = p.id;
    sel.appendChild(opt);
  });
}

function renderDict() {
  const q = document.getElementById('dict-search').value.trim().toLowerCase();
  const pat = document.getElementById('dict-pattern-filter').value;

  const filtered = ALL_NOUNS.filter(n => {
    const matchPat = pat === 'all' || n.pattern === pat;
    const matchQ = !q || n.base.toLowerCase().includes(q) || n.ru.toLowerCase().includes(q);
    return matchPat && matchQ;
  });

  document.getElementById('dict-count').textContent = ALL_NOUNS.length;
  const listEl = document.getElementById('dict-list');
  listEl.innerHTML = '';

  filtered.forEach(word => {
    const row = document.createElement('div');
    row.className = 'dict-row';
    row.innerHTML = `
      <div>
        <strong>${word.base}</strong> <span class="muted">— ${word.ru}</span>
      </div>
      <span class="pattern-badge">${word.pattern}</span>
    `;
    row.addEventListener('click', () => openNounModal(word));
    listEl.appendChild(row);
  });
}

document.getElementById('dict-search').addEventListener('input', renderDict);
document.getElementById('dict-pattern-filter').addEventListener('change', renderDict);

function renderStats() {
  const acc = stats.total ? Math.round((stats.correct / stats.total) * 100) : 0;
  document.getElementById('stats-summary').innerHTML = `
    <div class="stat-box"><div class="stat-val">${stats.total}</div><div class="stat-lbl">Ответов</div></div>
    <div class="stat-box"><div class="stat-val">${acc}%</div><div class="stat-lbl">Точность</div></div>
    <div class="stat-box"><div class="stat-val">${stats.bestStreak || 0}</div><div class="stat-lbl">Рекорд серии</div></div>
  `;

  const weakEntries = Object.entries(stats.weak || {})
    .filter(([, v]) => v > 0)
    .sort((a, b) => b[1] - a[1])
    .slice(0, 4)
    .map(([k]) => k.startsWith('p:') ? `образец «${k.slice(2)}»` : `падеж ${k.slice(2)}`);

  document.getElementById('weak-spots').textContent = weakEntries.length
    ? `Чаще всего повторяем слабые места: ${weakEntries.join(', ')}.`
    : 'Ошибок пока мало — тренажёр подбирает слова равномерно.';
}

document.getElementById('reset-stats-btn').addEventListener('click', () => {
  stats = { total: 0, correct: 0, streak: 0, bestStreak: 0, weak: {} };
  state.streak = 0;
  saveStats();
  updateStreakUI();
  renderStats();
});

// Модалка слова
function openNounModal(word) {
  const decl = declineNoun(word);
  document.getElementById('modal-title').textContent = word.base;
  document.getElementById('modal-subtitle').textContent = `${word.ru} · образец ${word.pattern}`;
  document.getElementById('modal-body').innerHTML = renderDeclTableHTML(decl);
  document.getElementById('modal').classList.remove('hidden');
}

function closeModal() { document.getElementById('modal').classList.add('hidden'); }
document.getElementById('modal-close').addEventListener('click', closeModal);
document.getElementById('modal-backdrop').addEventListener('click', closeModal);

// Модалка импорта JSON
const importModal = document.getElementById('import-modal');
document.getElementById('open-import-btn').addEventListener('click', () => {
  document.getElementById('import-status').textContent = '';
  importModal.classList.remove('hidden');
});
function closeImport() { importModal.classList.add('hidden'); }
document.getElementById('import-close').addEventListener('click', closeImport);
document.getElementById('import-backdrop').addEventListener('click', closeImport);

document.getElementById('save-import-btn').addEventListener('click', () => {
  const raw = document.getElementById('import-json-input').value.trim();
  const statusEl = document.getElementById('import-status');
  try {
    const arr = JSON.parse(raw);
    if (!Array.isArray(arr)) throw new Error('Нужен JSON-массив [...]');
    const validPatterns = new Set(PATTERNS.map(p => p.id));
    const prepared = arr.map(item => {
      if (!item.base || !item.ru || !validPatterns.has(item.pattern)) {
        throw new Error(`Проверьте поля base, ru, pattern у слова: ${item.base || '?'}`);
      }
      return {
        ...item,
        stem: item.stem || item.base.replace(/[aoe]$/i, '')
      };
    });
    const existingCustom = JSON.parse(localStorage.getItem(STORAGE_KEY_CUSTOM) || '[]');
    const merged = [...existingCustom, ...prepared];
    localStorage.setItem(STORAGE_KEY_CUSTOM, JSON.stringify(merged));
    loadCustomWords();
    renderDict();
    statusEl.textContent = `Добавлено слов: ${prepared.length}. Всего в словаре: ${ALL_NOUNS.length}.`;
  } catch (err) {
    statusEl.textContent = `Ошибка: ${err.message}`;
  }
});

document.getElementById('clear-custom-btn').addEventListener('click', () => {
  localStorage.removeItem(STORAGE_KEY_CUSTOM);
  ALL_NOUNS = [...BASE_NOUNS];
  renderDict();
  document.getElementById('import-status').textContent = 'Импортированные слова удалены.';
});