<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Заебиз — Умная аналитика бизнеса</title>
<script src="https://unpkg.com/vis-network@9.1.6/standalone/umd/vis-network.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --bg: #0d0d0d;
  --surface: #1a1a1a;
  --surface2: #2a2a2a;
  --surface3: #222;
  --border: #333;
  --text: #ececec;
  --text-muted: #888;
  --accent: #7c6fe0;
  --accent-light: #9d93e8;
  --green: #4ade80;
  --red: #f87171;
  --yellow: #fbbf24;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* Header */
.header {
  padding: 16px 24px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}
.header .logo {
  font-size: 18px;
  font-weight: 600;
  color: var(--accent-light);
  cursor: pointer;
}
.header .badge {
  font-size: 11px;
  background: var(--surface2);
  color: var(--text-muted);
  padding: 2px 8px;
  border-radius: 10px;
}

/* Main area */
.main {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
  transition: justify-content 0.5s ease;
}
.main.has-results {
  justify-content: flex-start;
}

/* Welcome */
.welcome {
  text-align: center;
  margin-bottom: 32px;
  transition: opacity 0.6s ease, transform 0.6s ease, max-height 0.6s ease, margin 0.6s ease;
  max-height: 200px;
  overflow: hidden;
}
.welcome h1 {
  font-size: 28px;
  font-weight: 500;
  color: var(--text);
  margin-bottom: 8px;
}
.welcome p {
  color: var(--text-muted);
  font-size: 15px;
}
.welcome.hidden {
  opacity: 0;
  transform: translateY(-20px);
  max-height: 0;
  margin: 0;
}

/* Search box */
.search-container {
  width: 100%;
  max-width: 680px;
  position: relative;
  z-index: 10;
}
.search-box {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 16px 56px 16px 20px;
  font-size: 16px;
  color: var(--text);
  outline: none;
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.search-box::placeholder { color: var(--text-muted); }
.search-box:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(124,111,224,0.12);
}
.search-btn {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  width: 40px;
  height: 40px;
  border-radius: 10px;
  border: none;
  background: var(--accent);
  color: white;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s, opacity 0.3s, transform 0.2s;
}
.search-btn:hover { background: var(--accent-light); transform: translateY(-50%) scale(1.05); }
.search-btn:disabled { opacity: 0.3; cursor: default; transform: translateY(-50%); }
.search-btn svg { width: 20px; height: 20px; }

/* Suggestions dropdown */
.suggestions {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  max-height: 340px;
  overflow-y: auto;
  z-index: 100;
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease;
  box-shadow: 0 12px 40px rgba(0,0,0,0.4);
}
.suggestions.visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: all;
}
.suggestion-item {
  padding: 14px 20px;
  cursor: pointer;
  transition: background 0.2s ease;
  border-bottom: 1px solid rgba(255,255,255,0.04);
}
.suggestion-item:last-child { border-bottom: none; }
.suggestion-item:hover { background: var(--surface2); }
.suggestion-item .name { font-weight: 500; font-size: 14px; }
.suggestion-item .meta {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 3px;
}
.suggestion-item .status-badge {
  display: inline-block;
  font-size: 10px;
  padding: 2px 7px;
  border-radius: 6px;
  margin-left: 8px;
  font-weight: 500;
}
.status-active { background: rgba(74,222,128,0.12); color: var(--green); }
.status-inactive { background: rgba(248,113,113,0.12); color: var(--red); }

/* Results area */
.results {
  width: 100%;
  max-width: 680px;
  margin-top: 32px;
}

/* Loading animation */
.loading {
  padding: 32px 0;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.4s ease, transform 0.4s ease;
  display: none;
}
.loading.visible {
  display: block;
  opacity: 1;
  transform: translateY(0);
}
.loading-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 8px;
}
.spinner {
  width: 20px;
  height: 20px;
  border: 2px solid var(--surface2);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.loading-text {
  font-size: 14px;
  color: var(--text-muted);
  transition: opacity 0.3s ease;
}
.loading-steps {
  margin-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.loading-step {
  font-size: 13px;
  color: var(--text-muted);
  opacity: 0;
  transform: translateX(-8px);
  transition: opacity 0.5s ease, transform 0.5s ease, color 0.3s ease;
  display: flex;
  align-items: center;
  gap: 8px;
}
.loading-step.visible {
  opacity: 1;
  transform: translateX(0);
}
.loading-step.done { color: var(--green); }
.loading-step .step-icon {
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
}

/* Company card */
.company-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  overflow: hidden;
  opacity: 0;
  transform: translateY(16px);
  animation: cardIn 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes cardIn {
  to { opacity: 1; transform: translateY(0); }
}

.card-header {
  padding: 28px 24px 20px;
  border-bottom: 1px solid var(--border);
}
.card-header .company-name {
  font-size: 22px;
  font-weight: 600;
  margin-bottom: 6px;
  line-height: 1.3;
}
.card-header .company-type {
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.4;
}

.card-section {
  padding: 0 24px;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1), transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
.card-section.visible {
  opacity: 1;
  transform: translateY(0);
}
.card-section:last-child { padding-bottom: 24px; }

.section-title {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1.2px;
  color: var(--accent-light);
  padding-top: 24px;
  padding-bottom: 12px;
  border-top: 1px solid rgba(255,255,255,0.04);
}
.card-section:first-child .section-title { border-top: none; }

.info-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px 16px;
}
@media (max-width: 500px) { .info-grid { grid-template-columns: 1fr; } }

.info-item { padding: 8px 0; }
.info-item.full { grid-column: 1 / -1; }
.info-label {
  font-size: 12px;
  color: var(--text-muted);
  margin-bottom: 3px;
}
.info-value {
  font-size: 14px;
  color: var(--text);
  word-break: break-word;
}
.info-value.accent { color: var(--accent-light); }

.status-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 500;
  padding: 4px 12px;
  border-radius: 8px;
}
.status-chip.active { background: rgba(74,222,128,0.1); color: var(--green); }
.status-chip.inactive { background: rgba(248,113,113,0.1); color: var(--red); }
.status-chip .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

/* Map */
.map-container {
  margin-top: 10px;
  height: 180px;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid var(--border);
}

/* Affiliated companies */
.affiliated-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.affiliated-item {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 16px;
  cursor: pointer;
  transition: background 0.2s ease, border-color 0.3s ease, transform 0.2s ease;
}
.affiliated-item:hover {
  background: var(--surface3);
  border-color: var(--accent);
  transform: translateX(4px);
}
.affiliated-item .aff-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
}
.affiliated-item .aff-name {
  font-size: 14px;
  font-weight: 500;
  flex: 1;
}
.affiliated-item .aff-status {
  font-size: 10px;
  padding: 2px 7px;
  border-radius: 6px;
  font-weight: 500;
  white-space: nowrap;
}
.affiliated-item .aff-meta {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 4px;
}
.affiliated-item .aff-role {
  font-size: 11px;
  color: var(--accent-light);
  margin-top: 3px;
}

/* Graph */
.graph-container {
  width: 100%;
  height: 480px;
  border-radius: 12px;
  border: 1px solid var(--border);
  background: #0a0a0a;
  position: relative;
  overflow: hidden;
}
.graph-legend {
  position: absolute;
  bottom: 10px;
  left: 12px;
  display: flex;
  gap: 14px;
  z-index: 5;
  font-size: 10px;
  color: rgba(255,255,255,0.3);
  pointer-events: none;
}
.graph-legend .gl-item {
  display: flex;
  align-items: center;
  gap: 5px;
}
.graph-legend .gl-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}
.graph-hint {
  font-size: 11px;
  color: rgba(255,255,255,0.2);
  margin-top: 8px;
  text-align: center;
}

/* Contracts */
.contract-item {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 16px;
  transition: border-color 0.3s ease;
}
.contract-item:hover { border-color: var(--accent); }
.contract-item .contract-name {
  font-size: 14px;
  font-weight: 500;
  line-height: 1.4;
  margin-bottom: 6px;
}
.contract-item .contract-meta {
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.5;
}
.contract-item .contract-price {
  font-size: 15px;
  font-weight: 600;
  color: var(--green);
  margin-top: 6px;
}
.contract-item .contract-link {
  font-size: 11px;
  color: var(--accent-light);
  text-decoration: none;
  margin-top: 4px;
  display: inline-block;
}
.contract-item .contract-link:hover { text-decoration: underline; }
.contracts-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.contracts-summary {
  display: flex;
  gap: 24px;
  margin-bottom: 14px;
}
.contracts-summary .cs-item {
  text-align: center;
}
.contracts-summary .cs-value {
  font-size: 20px;
  font-weight: 600;
  color: var(--accent-light);
}
.contracts-summary .cs-label {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 2px;
}

/* AI Summary */
.ai-summary-text {
  font-size: 14px;
  line-height: 1.7;
  color: var(--text);
  white-space: pre-wrap;
}
.ai-summary-text .cursor {
  display: inline-block;
  width: 2px;
  height: 1em;
  background: var(--accent);
  margin-left: 2px;
  vertical-align: text-bottom;
  animation: blink 0.8s step-end infinite;
}
@keyframes blink { 50% { opacity: 0; } }
.ai-sources {
  margin-top: 14px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.ai-source-link {
  font-size: 11px;
  color: var(--accent-light);
  background: rgba(124,111,224,0.08);
  padding: 4px 10px;
  border-radius: 8px;
  text-decoration: none;
  transition: background 0.2s;
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ai-source-link:hover { background: rgba(124,111,224,0.18); }
.ai-loading {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 0;
  color: var(--text-muted);
  font-size: 13px;
}
.ai-loading .spinner {
  width: 16px;
  height: 16px;
}

/* Footer */
.footer {
  text-align: center;
  padding: 16px;
  font-size: 12px;
  color: var(--text-muted);
  border-top: 1px solid var(--border);
}
</style>
</head>
<body>

<div class="header">
  <div class="logo" onclick="location.reload()">Заебиз</div>
  <div class="badge">beta</div>
</div>

<div class="main" id="main">
  <div class="welcome" id="welcome">
    <h1>Умная аналитика бизнеса</h1>
    <p>Введите название организации или ИНН</p>
  </div>

  <div class="search-container">
    <input
      type="text"
      class="search-box"
      id="searchInput"
      placeholder="Название компании или ИНН..."
      autocomplete="off"
    />
    <button class="search-btn" id="searchBtn" disabled>
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
        <line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/>
      </svg>
    </button>
    <div class="suggestions" id="suggestions"></div>
  </div>

  <div class="results" id="results">
    <div class="loading" id="loading">
      <div class="loading-bar">
        <div class="spinner"></div>
        <div class="loading-text" id="loadingText">Ищем компанию...</div>
      </div>
      <div class="loading-steps" id="loadingSteps"></div>
    </div>
    <div id="cardContainer"></div>
  </div>
</div>

<div class="footer">
  Заебиз &mdash; умная аналитика бизнеса
</div>

<script>
const input = document.getElementById('searchInput');
const btn = document.getElementById('searchBtn');
const suggestionsEl = document.getElementById('suggestions');
const loading = document.getElementById('loading');
const loadingText = document.getElementById('loadingText');
const loadingSteps = document.getElementById('loadingSteps');
const cardContainer = document.getElementById('cardContainer');
const welcome = document.getElementById('welcome');
const main = document.getElementById('main');

let debounceTimer;
let selectedInn = null;

input.addEventListener('input', () => {
  const q = input.value.trim();
  btn.disabled = q.length < 2;
  selectedInn = null;
  clearTimeout(debounceTimer);
  if (q.length < 2) { suggestionsEl.classList.remove('visible'); return; }
  debounceTimer = setTimeout(() => fetchSuggestions(q), 200);
});

input.addEventListener('keydown', (e) => {
  if (e.key === 'Enter' && !btn.disabled) {
    e.preventDefault();
    if (selectedInn) loadCompany(selectedInn);
    else { const f = suggestionsEl.querySelector('.suggestion-item'); if (f) f.click(); }
  }
  if (e.key === 'Escape') suggestionsEl.classList.remove('visible');
});

btn.addEventListener('click', () => {
  if (selectedInn) loadCompany(selectedInn);
  else { const f = suggestionsEl.querySelector('.suggestion-item'); if (f) f.click(); }
});

// EN→RU keyboard layout map
const enToRu = {'q':'й','w':'ц','e':'у','r':'к','t':'е','y':'н','u':'г','i':'ш','o':'щ','p':'з','[':'х',']':'ъ','a':'ф','s':'ы','d':'в','f':'а','g':'п','h':'р','j':'о','k':'л','l':'д',';':'ж',"'":'э','z':'я','x':'ч','c':'с','v':'м','b':'и','n':'т','m':'ь',',':'б','.':'ю','/':'.','`':'ё'};
function fixLayout(str) {
  // If string looks like latin chars (wrong layout), convert to cyrillic
  if (/^[a-z\[\];',./`\s]+$/i.test(str)) {
    return str.split('').map(c => {
      const low = c.toLowerCase();
      const mapped = enToRu[low];
      if (!mapped) return c;
      return c === low ? mapped : mapped.toUpperCase();
    }).join('');
  }
  return str;
}

async function fetchSuggestions(q) {
  q = fixLayout(q);
  try {
    const resp = await fetch(`/api/v1/company/search?q=${encodeURIComponent(q)}`);
    const data = await resp.json();
    renderSuggestions(data.results || []);
  } catch(e) { suggestionsEl.classList.remove('visible'); }
}

function renderSuggestions(items) {
  if (!items.length) { suggestionsEl.classList.remove('visible'); return; }
  suggestionsEl.innerHTML = items.map(item => {
    const statusCls = item.status === 'ACTIVE' ? 'status-active' : 'status-inactive';
    const statusText = item.status === 'ACTIVE' ? 'Действует' : 'Недействующая';
    return `<div class="suggestion-item" data-inn="${item.inn}">
      <div class="name">${esc(item.name)} <span class="status-badge ${statusCls}">${statusText}</span></div>
      <div class="meta">ИНН ${item.inn}${item.address ? ' &bull; ' + esc(item.address) : ''}${item.director ? ' &bull; ' + esc(item.director) : ''}</div>
    </div>`;
  }).join('');

  suggestionsEl.querySelectorAll('.suggestion-item').forEach(el => {
    el.addEventListener('click', () => {
      selectedInn = el.dataset.inn;
      const companyName = el.querySelector('.name').textContent.replace(/Действует|Недействующая/g, '').trim();
      input.value = companyName + ' · ИНН ' + selectedInn;
      suggestionsEl.classList.remove('visible');
      loadCompany(selectedInn);
    });
  });
  suggestionsEl.classList.add('visible');
}

async function loadCompany(inn) {
  suggestionsEl.classList.remove('visible');
  welcome.classList.add('hidden');
  main.classList.add('has-results');
  cardContainer.innerHTML = '';
  loadingSteps.innerHTML = '';
  loading.classList.add('visible');

  const steps = [
    'Подключаемся к реестру данных',
    'Запрашиваем реквизиты компании',
    'Загружаем сведения о руководстве',
    'Проверяем адрес регистрации',
    'Ищем связанные организации',
    'Загружаем госконтракты',
    'Запускаем AI-анализ компании',
  ];

  // Animate loading steps one by one
  for (let i = 0; i < steps.length; i++) {
    const el = document.createElement('div');
    el.className = 'loading-step';
    el.innerHTML = `<span class="step-icon">○</span>${steps[i]}`;
    loadingSteps.appendChild(el);
    await sleep(120);
    el.classList.add('visible');
    if (i < steps.length - 1) {
      await sleep(400);
      el.innerHTML = `<span class="step-icon">✓</span>${steps[i]}`;
      el.classList.add('done');
    }
  }

  try {
    const [detailsResp, affiliatedResp, contractsResp] = await Promise.all([
      fetch(`/api/v1/company/${inn}/details`),
      fetch(`/api/v1/company/${inn}/affiliated`),
      fetch(`/api/v1/company/${inn}/contracts`),
    ]);

    if (!detailsResp.ok) throw new Error('Not found');
    const data = await detailsResp.json();
    const affiliated = affiliatedResp.ok ? await affiliatedResp.json() : null;
    const contracts = contractsResp.ok ? await contractsResp.json() : null;

    // Build AI query params from company data
    const aiName = data.name_short || data.name_full || '';
    const aiRegion = (data.address && data.address.region) || '';
    const aiPromise = fetch(`/api/v1/company/${inn}/ai-summary?name=${encodeURIComponent(aiName)}&region=${encodeURIComponent(aiRegion)}`)
      .then(r => r.ok ? r.json() : null).catch(() => null);

    // Mark last step done
    const lastStep = loadingSteps.lastElementChild;
    if (lastStep) { lastStep.innerHTML = `<span class="step-icon">✓</span>${steps[steps.length-1]}`; lastStep.classList.add('done'); }

    await sleep(300);
    loading.classList.remove('visible');

    await sleep(100);
    renderCard(data, affiliated, contracts, aiPromise);
  } catch(e) {
    loading.classList.remove('visible');
    cardContainer.innerHTML = `<div class="company-card" style="animation-delay:0s"><div class="card-header"><div class="company-name">Компания не найдена</div><div class="company-type">Проверьте ИНН и попробуйте ещё раз</div></div></div>`;
  }
}

function renderCard(d, affiliated, contracts, aiPromise) {
  const isActive = d.status === 'ACTIVE';
  const statusClass = isActive ? 'active' : 'inactive';
  const statusText = isActive ? 'Действующая' : (d.liquidation_date ? 'Ликвидирована ' + d.liquidation_date : 'Ликвидирована');
  const mgmt = d.management || {};
  const addr = d.address || {};
  const sections = [];

  // Status & Requisites
  sections.push({
    title: 'Статус и реквизиты',
    html: `<div class="info-grid">
      <div class="info-item full"><div class="info-label">Статус</div><div class="info-value"><span class="status-chip ${statusClass}"><span class="dot"></span>${statusText}</span></div></div>
      <div class="info-item"><div class="info-label">ИНН</div><div class="info-value accent">${d.inn || '—'}</div></div>
      <div class="info-item"><div class="info-label">КПП</div><div class="info-value">${d.kpp || '—'}</div></div>
      <div class="info-item"><div class="info-label">ОГРН</div><div class="info-value accent">${d.ogrn || '—'}</div></div>
      <div class="info-item"><div class="info-label">Дата регистрации</div><div class="info-value">${d.registration_date || '—'}</div></div>
      <div class="info-item"><div class="info-label">ОКПО</div><div class="info-value">${d.okpo || '—'}</div></div>
      <div class="info-item"><div class="info-label">ОКВЭД</div><div class="info-value">${d.okved || '—'}</div></div>
      <div class="info-item"><div class="info-label">ОКАТО</div><div class="info-value">${d.okato || '—'}</div></div>
      <div class="info-item"><div class="info-label">ОКТМО</div><div class="info-value">${d.oktmo || '—'}</div></div>
    </div>`
  });

  // Management
  if (mgmt.name) {
    sections.push({
      title: 'Руководство',
      html: `<div class="info-grid">
        <div class="info-item full"><div class="info-label">${esc(mgmt.post) || 'Руководитель'}</div><div class="info-value">${esc(mgmt.name)}</div></div>
        ${mgmt.start_date ? `<div class="info-item"><div class="info-label">Дата назначения</div><div class="info-value">${mgmt.start_date}</div></div>` : ''}
      </div>`
    });
  }

  // Address
  if (addr.full) {
    let mapHtml = '';
    if (addr.geo_lat && addr.geo_lon) {
      const lat = parseFloat(addr.geo_lat), lon = parseFloat(addr.geo_lon);
      mapHtml = `<div class="map-container"><iframe width="100%" height="100%" frameborder="0" style="border:0;filter:invert(0.92) hue-rotate(180deg) saturate(0.8);" loading="lazy" src="https://www.openstreetmap.org/export/embed.html?bbox=${lon-0.005}%2C${lat-0.003}%2C${lon+0.005}%2C${lat+0.003}&layer=mapnik&marker=${lat}%2C${lon}"></iframe></div>`;
    }
    sections.push({
      title: 'Адрес',
      html: `<div class="info-grid">
        <div class="info-item full"><div class="info-label">Юридический адрес</div><div class="info-value">${esc(addr.full)}</div></div>
        ${addr.postal_code ? `<div class="info-item"><div class="info-label">Индекс</div><div class="info-value">${addr.postal_code}</div></div>` : ''}
        ${addr.region ? `<div class="info-item"><div class="info-label">Регион</div><div class="info-value">${esc(addr.region)}</div></div>` : ''}
      </div>${mapHtml}`
    });
  }

  // Finance
  if (d.finance) {
    const f = d.finance;
    sections.push({
      title: `Финансы${f.year ? ' за ' + f.year + ' год' : ''}`,
      html: `<div class="info-grid">
        ${f.income != null ? `<div class="info-item"><div class="info-label">Доходы</div><div class="info-value">${formatMoney(f.income)}</div></div>` : ''}
        ${f.expense != null ? `<div class="info-item"><div class="info-label">Расходы</div><div class="info-value">${formatMoney(f.expense)}</div></div>` : ''}
        ${f.revenue != null ? `<div class="info-item"><div class="info-label">Выручка</div><div class="info-value accent">${formatMoney(f.revenue)}</div></div>` : ''}
        ${f.debt != null ? `<div class="info-item"><div class="info-label">Задолженность</div><div class="info-value">${formatMoney(f.debt)}</div></div>` : ''}
        ${f.penalty != null ? `<div class="info-item"><div class="info-label">Штрафы</div><div class="info-value">${formatMoney(f.penalty)}</div></div>` : ''}
      </div>`
    });
  }

  // Connection Graph
  const hasAffiliated = affiliated && affiliated.affiliated && affiliated.affiliated.length > 0;
  const hasContracts = contracts && contracts.status === 'ok' && contracts.contracts && contracts.contracts.length > 0;
  if (hasAffiliated || hasContracts) {
    const graphId = 'graph-' + Date.now();
    sections.push({
      title: 'Граф связей',
      html: `<div class="graph-container" id="${graphId}"></div>
        <div class="graph-legend">
          <div class="gl-item"><div class="gl-dot" style="background:#7c6fe0"></div>Компания</div>
          <div class="gl-item"><div class="gl-dot" style="background:#4ade80"></div>Связанная</div>
          <div class="gl-item"><div class="gl-dot" style="background:#fbbf24"></div>Заказчик</div>
          <div class="gl-item"><div class="gl-dot" style="background:#f472b6"></div>Поставщик</div>
          <div class="gl-item"><div class="gl-dot" style="background:#60a5fa"></div>Руководитель</div>
        </div>
        <div class="graph-hint">Перетаскивайте узлы и прокручивайте для масштабирования</div>`,
      afterRender: () => buildGraph(graphId, d, affiliated, contracts)
    });
  }

  // Contracts (TenderGuru)
  if (hasContracts) {
    const summaryHtml = `<div class="contracts-summary">
      <div class="cs-item"><div class="cs-value">${contracts.total}</div><div class="cs-label">контрактов</div></div>
      <div class="cs-item"><div class="cs-value">${formatMoney(contracts.total_value)}</div><div class="cs-label">общая сумма</div></div>
    </div>`;
    const listHtml = contracts.contracts.slice(0, 10).map(c => {
      const price = c.price ? formatMoney(Number(c.price)) : '—';
      return `<div class="contract-item">
        <div class="contract-name">${esc(c.name)}</div>
        <div class="contract-meta">${esc(c.customer)}${c.region ? ' &bull; ' + esc(c.region) : ''}${c.sign_date ? ' &bull; ' + c.sign_date : ''}${c.law ? ' &bull; ' + c.law : ''}</div>
        <div class="contract-price">${price}</div>
        ${c.tender_link ? `<a class="contract-link" href="${esc(c.tender_link)}" target="_blank" rel="noopener">zakupki.gov.ru &rarr;</a>` : ''}
      </div>`;
    }).join('');
    const moreHtml = contracts.contracts.length > 10 ? `<div style="color:var(--text-muted);font-size:12px;margin-top:8px;">Показаны первые 10 из ${contracts.total}</div>` : '';
    sections.push({
      title: `Госконтракты (${contracts.total})`,
      html: `${summaryHtml}<div class="contracts-list">${listHtml}</div>${moreHtml}`
    });
  }

  // Customer contracts (where company is the buyer)
  const custData = contracts && contracts.as_customer;
  if (custData && custData.status === 'ok' && custData.suppliers && custData.suppliers.length > 0) {
    const summaryHtml2 = `<div class="contracts-summary">
      <div class="cs-item"><div class="cs-value">${custData.total}</div><div class="cs-label">закупок</div></div>
      <div class="cs-item"><div class="cs-value">${formatMoney(custData.total_value)}</div><div class="cs-label">общая сумма</div></div>
    </div>`;
    const listHtml2 = custData.suppliers.slice(0, 10).map(c => {
      const price = c.price ? formatMoney(Number(c.price)) : '—';
      return `<div class="contract-item">
        <div class="contract-name">${esc(c.name)}</div>
        <div class="contract-meta">Поставщик: ${esc(c.supplier)}${c.sign_date ? ' &bull; ' + c.sign_date : ''}${c.law ? ' &bull; ' + c.law : ''}</div>
        <div class="contract-price">${price}</div>
        ${c.tender_link ? `<a class="contract-link" href="${esc(c.tender_link)}" target="_blank" rel="noopener">zakupki.gov.ru &rarr;</a>` : ''}
      </div>`;
    }).join('');
    sections.push({
      title: `Закупки компании (${custData.total})`,
      html: `${summaryHtml2}<div class="contracts-list">${listHtml2}</div>`
    });
  }

  // AI Summary (placeholder, filled async)
  const aiSectionIdx = sections.length;
  sections.push({
    title: 'AI-анализ компании',
    html: `<div class="ai-loading"><div class="spinner"></div>Анализируем данные из открытых источников...</div><div class="ai-summary-text" id="aiText"></div><div class="ai-sources" id="aiSources"></div>`
  });

  // Affiliated companies
  if (affiliated && affiliated.affiliated && affiliated.affiliated.length > 0) {
    const personHtml = affiliated.person ? `<div class="info-item full" style="margin-bottom:12px"><div class="info-label">Связи по</div><div class="info-value">${esc(affiliated.person)}</div></div>` : '';
    const itemsHtml = affiliated.affiliated.map(a => {
      const statusCls = a.status === 'ACTIVE' ? 'status-active' : 'status-inactive';
      const statusText = a.status === 'ACTIVE' ? 'Действует' : 'Недействующая';
      const confBadge = a.same_region
        ? '<span style="font-size:10px;background:rgba(74,222,128,0.12);color:var(--green);padding:2px 7px;border-radius:6px;margin-left:6px;">тот же регион</span>'
        : '';
      return `<div class="affiliated-item" data-inn="${a.inn}">
        <div class="aff-header">
          <div class="aff-name">${esc(a.name)}${confBadge}</div>
          <span class="aff-status ${statusCls}">${statusText}</span>
        </div>
        <div class="aff-meta">ИНН ${a.inn}${a.address ? ' &bull; ' + esc(a.address) : ''}</div>
        ${a.role ? `<div class="aff-role">${esc(a.role)}</div>` : ''}
      </div>`;
    }).join('');

    sections.push({
      title: `Связанные организации (${affiliated.affiliated.length})`,
      html: `${personHtml}<div class="affiliated-list">${itemsHtml}</div>`
    });
  }

  const sectionsHtml = sections.map((s, i) =>
    `<div class="card-section" data-idx="${i}">
      <div class="section-title">${s.title}</div>
      ${s.html}
    </div>`
  ).join('');

  cardContainer.innerHTML = `
    <div class="company-card">
      <div class="card-header">
        <div class="company-name">${esc(d.name_short || d.name_full || '—')}</div>
        <div class="company-type">${esc(d.name_full || '')}</div>
      </div>
      ${sectionsHtml}
    </div>`;

  // Staggered reveal of sections + trigger afterRender callbacks
  const secs = cardContainer.querySelectorAll('.card-section');
  secs.forEach((sec, i) => {
    setTimeout(() => {
      sec.classList.add('visible');
      const idx = parseInt(sec.dataset.idx);
      if (sections[idx] && sections[idx].afterRender) sections[idx].afterRender();
    }, 300 + i * 350);
  });

  // Scroll to card
  setTimeout(() => cardContainer.scrollIntoView({ behavior: 'smooth', block: 'start' }), 200);

  // Load AI summary async with typewriter effect
  if (aiPromise) {
    aiPromise.then(async (ai) => {
      const aiTextEl = document.getElementById('aiText');
      const aiSourcesEl = document.getElementById('aiSources');
      const aiLoadingEl = aiTextEl?.previousElementSibling;
      if (!aiTextEl) return;

      if (!ai || ai.status !== 'ok' || !ai.content) {
        if (aiLoadingEl) aiLoadingEl.innerHTML = '<span style="color:var(--text-muted);font-size:13px;">AI-анализ недоступен</span>';
        return;
      }

      // Hide loading spinner
      if (aiLoadingEl) aiLoadingEl.style.display = 'none';

      // Clean markdown: **bold**, [1][2] refs, extra whitespace
      const cleanMd = (s) => s.replace(/\*\*/g, '').replace(/\[\d+\]/g, '').replace(/\n{3,}/g, '\n\n').trim();

      // Typewriter effect
      const text = cleanMd(ai.content);
      let i = 0;
      aiTextEl.innerHTML = '<span class="cursor"></span>';
      const type = () => {
        if (i < text.length) {
          const chunk = text.substring(i, Math.min(i + 3, text.length));
          i += chunk.length;
          aiTextEl.innerHTML = esc(text.substring(0, i)) + '<span class="cursor"></span>';
          requestAnimationFrame(() => setTimeout(type, 12));
        } else {
          aiTextEl.innerHTML = esc(text);
          // Show sources
          if (ai.sources && ai.sources.length && aiSourcesEl) {
            aiSourcesEl.innerHTML = ai.sources.map(s =>
              `<a class="ai-source-link" href="${esc(s.url)}" target="_blank" rel="noopener">${esc(s.title || s.url)}</a>`
            ).join('');
          }
        }
      };
      type();

      // Scroll AI section into view
      const aiSection = aiTextEl.closest('.card-section');
      if (aiSection) setTimeout(() => aiSection.scrollIntoView({ behavior: 'smooth', block: 'center' }), 500);
    });
  }
}

function formatMoney(val) {
  if (val == null) return '—';
  const n = Number(val);
  if (isNaN(n)) return String(val);
  if (Math.abs(n) >= 1e9) return (n / 1e9).toFixed(1) + ' млрд ₽';
  if (Math.abs(n) >= 1e6) return (n / 1e6).toFixed(1) + ' млн ₽';
  if (Math.abs(n) >= 1e3) return (n / 1e3).toFixed(0) + ' тыс ₽';
  return n.toLocaleString('ru-RU') + ' ₽';
}

function esc(s) {
  if (!s) return '';
  const d = document.createElement('div');
  d.textContent = s;
  return d.innerHTML;
}

function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }

function buildGraph(containerId, company, affiliated, contracts) {
  const container = document.getElementById(containerId);
  if (!container || typeof vis === 'undefined') return;

  const nodes = [];
  const edges = [];
  const nodeIds = new Set();
  const nodeMeta = {};

  const sn = (name) => !name ? '?' : name.length > 35 ? name.substring(0, 33) + '...' : name;

  // Color palette (Obsidian-like muted glows)
  const C = {
    main:    { bg: 'rgba(124,111,224,0.9)', glow: 'rgba(124,111,224,0.35)' },
    person:  { bg: 'rgba(96,165,250,0.85)', glow: 'rgba(96,165,250,0.25)' },
    affil:   { bg: 'rgba(74,222,128,0.8)',  glow: 'rgba(74,222,128,0.2)' },
    dead:    { bg: 'rgba(120,120,120,0.6)',  glow: 'rgba(120,120,120,0.1)' },
    cust:    { bg: 'rgba(251,191,36,0.8)',   glow: 'rgba(251,191,36,0.2)' },
    suppl:   { bg: 'rgba(244,114,182,0.8)', glow: 'rgba(244,114,182,0.2)' },
    edge:    'rgba(255,255,255,0.18)',
    edgeHi:  'rgba(255,255,255,0.45)',
  };

  const mkNode = (id, label, type, size) => {
    const c = C[type] || C.affil;
    return {
      id, label, size,
      shape: 'dot',
      color: { background: c.bg, border: 'transparent', highlight: { background: c.bg, border: 'rgba(255,255,255,0.3)' }, hover: { background: c.bg, border: 'rgba(255,255,255,0.2)' } },
      font: { color: 'rgba(255,255,255,0.75)', size: 11, face: '-apple-system, sans-serif', vadjust: -size - 8 },
      borderWidth: 0,
      shadow: { enabled: true, color: c.glow, size: size * 1.5, x: 0, y: 0 },
      chosen: {
        node: (values) => { values.shadow = true; values.shadowSize = size * 2.5; values.shadowColor = c.glow; values.size = size * 1.15; },
        label: (values) => { values.color = '#fff'; values.size = 13; }
      },
    };
  };

  const mkEdge = (from, to, opts = {}) => ({
    from, to,
    width: opts.width || 1,
    color: { color: C.edge, highlight: C.edgeHi, hover: C.edgeHi, opacity: 1 },
    smooth: { enabled: true, type: opts.curve || 'continuous', roundness: opts.roundness || 0.5 },
    hoverWidth: 0.8,
    selectionWidth: 1,
    arrows: opts.arrow ? { to: { enabled: true, scaleFactor: 0.35, type: 'arrow' } } : undefined,
    chosen: { edge: (values) => { values.width = 1.2; } },
  });

  // --- Central company ---
  const companyId = company.inn || 'main';
  const companyLabel = sn(company.name_short || company.name_full);
  nodes.push(mkNode(companyId, companyLabel, 'main', 24));
  nodeIds.add(companyId);
  nodeMeta[companyId] = { label: companyLabel };

  // --- Director ---
  const mgmt = company.management || {};
  if (mgmt.name) {
    const dirId = 'dir-' + companyId;
    nodes.push(mkNode(dirId, sn(mgmt.name), 'person', 14));
    edges.push(mkEdge(dirId, companyId, { width: 1.5 }));
    nodeMeta[dirId] = { label: mgmt.name, type: 'person' };
  }

  // --- Affiliated ---
  if (affiliated && affiliated.affiliated) {
    affiliated.affiliated.forEach((a, i) => {
      if (nodeIds.has(a.inn)) return;
      nodeIds.add(a.inn);
      const isActive = a.status === 'ACTIVE';
      const size = isActive ? 10 + Math.random() * 4 : 7;
      nodes.push(mkNode(a.inn, sn(a.name), isActive ? 'affil' : 'dead', size));
      nodeMeta[a.inn] = { label: a.name };
      const fromNode = mgmt.name ? 'dir-' + companyId : companyId;
      edges.push(mkEdge(fromNode, a.inn, { curve: 'curvedCW', roundness: 0.3 + (i % 4) * 0.15 }));
    });
  }

  // --- Contract customers (top 10 unique) ---
  if (contracts && contracts.contracts) {
    const seen = new Set();
    let count = 0;
    for (const c of contracts.contracts) {
      if (count >= 10) break;
      const custInn = c.customer_inn;
      if (!custInn || seen.has(custInn) || nodeIds.has(custInn)) continue;
      seen.add(custInn);
      nodeIds.add(custInn);
      count++;
      const size = 8 + Math.min(Math.log10(Number(c.price) || 1), 7) * 1.5;
      nodes.push(mkNode(custInn, sn(c.customer), 'cust', size));
      nodeMeta[custInn] = { label: c.customer };
      edges.push(mkEdge(companyId, custInn, { arrow: true, curve: 'curvedCCW', roundness: 0.25 + (count % 3) * 0.15 }));
    }
  }

  // --- Suppliers (company as customer) ---
  const custContracts = contracts && contracts.as_customer;
  if (custContracts && custContracts.suppliers) {
    const seen = new Set();
    let count = 0;
    for (const c of custContracts.suppliers) {
      if (count >= 8) break;
      const supplInn = c.supplier_inn;
      if (!supplInn || seen.has(supplInn) || nodeIds.has(supplInn)) continue;
      seen.add(supplInn);
      nodeIds.add(supplInn);
      count++;
      const size = 8 + Math.min(Math.log10(Number(c.price) || 1), 7) * 1.5;
      nodes.push(mkNode(supplInn, sn(c.supplier), 'suppl', size));
      nodeMeta[supplInn] = { label: c.supplier };
      edges.push(mkEdge(supplInn, companyId, { arrow: true, curve: 'curvedCW', roundness: 0.2 + (count % 3) * 0.15 }));
    }
  }

  const data = { nodes: new vis.DataSet(nodes), edges: new vis.DataSet(edges) };
  const options = {
    physics: {
      solver: 'forceAtlas2Based',
      forceAtlas2Based: {
        gravitationalConstant: -45,
        centralGravity: 0.005,
        springLength: 140,
        springConstant: 0.025,
        damping: 0.6,
        avoidOverlap: 0.5,
      },
      stabilization: { iterations: 150, fit: true },
      maxVelocity: 25,
      minVelocity: 0.3,
    },
    interaction: {
      hover: true,
      dragNodes: true,
      zoomView: true,
      dragView: true,
      tooltipDelay: 100,
      hideEdgesOnDrag: false,
      hideEdgesOnZoom: false,
    },
    nodes: {
      font: { multi: false },
    },
    edges: {
      smooth: { enabled: true },
    },
  };

  const network = new vis.Network(container, data, options);

  // Keep labels hidden by default, show on hover (Obsidian style)
  // After stabilization, hide labels and show only on hover
  network.once('stabilized', () => {
    // Fade labels to very small
    data.nodes.forEach(n => {
      data.nodes.update({ id: n.id, font: { ...n.font, color: 'transparent', size: 1 } });
    });

    // Show label on hover
    network.on('hoverNode', (params) => {
      const n = nodes.find(x => x.id === params.node);
      if (n) {
        data.nodes.update({ id: params.node, font: { color: 'rgba(255,255,255,0.9)', size: 13, vadjust: -(n.size || 12) - 10 } });
      }
    });
    network.on('blurNode', (params) => {
      data.nodes.update({ id: params.node, font: { color: 'transparent', size: 1 } });
    });

    // Always show main node label
    const mainNode = nodes.find(x => x.id === companyId);
    if (mainNode) {
      data.nodes.update({ id: companyId, font: { color: 'rgba(255,255,255,0.85)', size: 13, vadjust: -mainNode.size - 10 } });
    }

    // Gentle float after stabilization
    network.setOptions({ physics: { enabled: true, solver: 'forceAtlas2Based', forceAtlas2Based: { gravitationalConstant: -20, centralGravity: 0.003, springLength: 140, springConstant: 0.02, damping: 0.9 }, maxVelocity: 3, minVelocity: 0.1 } });
  });

  // Click to navigate
  network.on('click', (params) => {
    if (params.nodes.length > 0) {
      const clickedId = params.nodes[0];
      if (clickedId !== companyId && !clickedId.startsWith('dir-')) {
        const meta = nodeMeta[clickedId];
        const label = meta ? meta.label : '';
        input.value = (label ? label + ' · ' : '') + 'ИНН ' + clickedId;
        selectedInn = clickedId;
        loadCompany(clickedId);
      }
    }
  });
}

document.addEventListener('click', (e) => {
  if (!e.target.closest('.search-container')) suggestionsEl.classList.remove('visible');

  const affItem = e.target.closest('.affiliated-item');
  if (affItem) {
    const inn = affItem.dataset.inn;
    const nameEl = affItem.querySelector('.aff-name');
    const name = nameEl ? nameEl.firstChild.textContent.trim() : '';
    if (inn) {
      input.value = (name ? name + ' · ' : '') + 'ИНН ' + inn;
      selectedInn = inn;
      loadCompany(inn);
    }
  }
});
</script>
</body>
</html>
