/**
 * knowledge-explorer.mjs — Knowledge Graph explorer component
 * Search entities, view relations, browse type breakdowns with glassmorphic UI.
 */

import store from '../store.mjs';
import api from '../api.mjs';
import { $, $$, createElement, icon, escapeHtml, empty, debounce } from '../utils/dom.mjs';
import { truncate } from '../utils/format.mjs';

// ── Constants ──

const TYPE_STYLES = {
  person:     { color: 'var(--accent-primary)',      label: 'Person' },
  concept:    { color: 'var(--info)',                 label: 'Concept' },
  technology: { color: 'var(--success)',              label: 'Technology' },
  location:   { color: 'var(--warning)',              label: 'Location' },
  other:      { color: 'var(--text-tertiary)',        label: 'Other' }
};

// ── DOM references ──

let container = null;
let statsHeaderEl = null;
let searchInput = null;
let resultsEl = null;
let detailEl = null;
let statsBreakdownEl = null;
let emptyStateEl = null;
let loadingEl = null;
let selectedEntityId = null;

// ──────────────────────────────────────
// Public init
// ──────────────────────────────────────

export function init() {
  container = $('#view-knowledge');
  if (!container) {
    console.warn('[knowledge-explorer] #view-knowledge not found');
    return;
  }

  buildDOM();
  subscribeToStore();
  loadStats();
}

// ──────────────────────────────────────
// DOM construction
// ──────────────────────────────────────

function buildDOM() {
  empty(container);
  container.classList.add('knowledge-explorer');

  // Header
  const header = createElement('div', {
    style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexWrap: 'wrap', gap: 'var(--space-sm)' }
  });

  const titleRow = createElement('div', {
    style: { display: 'flex', alignItems: 'center', gap: 'var(--space-sm)' }
  }, [
    icon('database', { size: 24 }),
    createElement('h2', {
      style: { margin: '0', fontSize: 'var(--font-size-xl)', color: 'var(--text-primary)' }
    }, ['Knowledge Graph'])
  ]);

  statsHeaderEl = createElement('div', {
    style: { display: 'flex', gap: 'var(--space-sm)', alignItems: 'center' }
  });

  header.appendChild(titleRow);
  header.appendChild(statsHeaderEl);
  container.appendChild(header);

  // Search bar
  const searchRow = createElement('div', {
    style: { position: 'relative', display: 'flex', alignItems: 'center' }
  });

  const searchIconEl = createElement('span', {
    style: {
      position: 'absolute', left: '12px', top: '50%', transform: 'translateY(-50%)',
      color: 'var(--text-tertiary)', pointerEvents: 'none', display: 'flex'
    }
  }, [icon('search', { size: 16 })]);

  searchInput = createElement('input', {
    className: 'glass-input',
    type: 'text',
    placeholder: 'Search entities...',
    'aria-label': 'Search knowledge graph',
    style: { width: '100%', paddingLeft: '40px' }
  });

  searchRow.appendChild(searchIconEl);
  searchRow.appendChild(searchInput);
  container.appendChild(searchRow);

  // Loading state
  loadingEl = createElement('div', {
    className: 'shimmer',
    style: {
      display: 'none', height: '60px', borderRadius: 'var(--radius-md)'
    }
  });
  container.appendChild(loadingEl);

  // Empty state
  emptyStateEl = createElement('div', {
    className: 'glass-subtle animate-fade-in',
    style: {
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
      padding: 'var(--space-xl)', gap: 'var(--space-md)', textAlign: 'center',
      borderRadius: 'var(--radius-lg)', minHeight: '200px'
    }
  }, [
    icon('database', { size: 48, className: '' }),
    createElement('p', {
      style: { color: 'var(--text-secondary)', margin: '0', fontSize: 'var(--font-size-base)' }
    }, ['Search the knowledge graph']),
    createElement('p', {
      style: { color: 'var(--text-tertiary)', margin: '0', fontSize: 'var(--font-size-sm)' }
    }, ['Type a query above to find entities and their relationships'])
  ]);
  emptyStateEl.querySelector('svg').style.color = 'var(--text-tertiary)';
  container.appendChild(emptyStateEl);

  // Results list
  resultsEl = createElement('div', {
    style: { display: 'none', flexDirection: 'column', gap: 'var(--space-sm)' }
  });
  container.appendChild(resultsEl);

  // Entity detail panel
  detailEl = createElement('div', {
    style: { display: 'none', flexDirection: 'column', gap: 'var(--space-sm)' }
  });
  container.appendChild(detailEl);

  // Stats breakdown (bottom)
  statsBreakdownEl = createElement('div', {
    style: { display: 'none', flexDirection: 'column', gap: 'var(--space-sm)', marginTop: 'auto' }
  });
  container.appendChild(statsBreakdownEl);

  // Wire up search input with debounce
  const debouncedSearch = debounce(handleSearch, 300);
  searchInput.addEventListener('input', debouncedSearch);
}

// ──────────────────────────────────────
// Store subscriptions
// ──────────────────────────────────────

function subscribeToStore() {
  store.subscribe(
    (s) => s.knowledge.stats,
    (stats) => renderStats(stats)
  );

  store.subscribe(
    (s) => s.knowledge.searchResults,
    (results) => renderResults(results)
  );
}

// ──────────────────────────────────────
// Data loading
// ──────────────────────────────────────

async function loadStats() {
  try {
    const stats = await api.getKGStats();
    store.dispatch('SET_KG_STATS', stats);
  } catch (err) {
    console.warn('[knowledge-explorer] Failed to load KG stats:', err.message);
  }
}

async function handleSearch() {
  const query = searchInput.value.trim();

  if (!query) {
    store.dispatch('SET_KG_RESULTS', []);
    hideDetail();
    showEmptyState();
    return;
  }

  showLoading();
  hideEmptyState();

  try {
    const results = await api.searchEntities(query);
    store.dispatch('SET_KG_RESULTS', Array.isArray(results) ? results : []);
  } catch (err) {
    console.error('[knowledge-explorer] Search error:', err);
    store.dispatch('SET_KG_RESULTS', []);
  } finally {
    hideLoading();
  }
}

async function loadEntityRelations(entityId) {
  try {
    const relations = await api.getEntityRelations(entityId);
    return Array.isArray(relations) ? relations : [];
  } catch (err) {
    console.error('[knowledge-explorer] Relations error:', err);
    return [];
  }
}

// ──────────────────────────────────────
// Rendering — Stats
// ──────────────────────────────────────

function renderStats(stats) {
  if (!stats) return;

  empty(statsHeaderEl);

  const entities = stats.totalEntities || 0;
  const relations = stats.totalRelations || 0;

  statsHeaderEl.appendChild(
    createElement('span', { className: 'badge badge-accent' }, [`${entities} entities`])
  );
  statsHeaderEl.appendChild(
    createElement('span', { className: 'badge' }, [`${relations} relations`])
  );

  // Stats breakdown section
  renderStatsBreakdown(stats);
}

function renderStatsBreakdown(stats) {
  if (!stats || !stats.types) return;

  empty(statsBreakdownEl);
  statsBreakdownEl.style.display = 'flex';

  const divider = createElement('div', { className: 'divider' });
  statsBreakdownEl.appendChild(divider);

  const breakdownTitle = createElement('div', {
    style: {
      display: 'flex', alignItems: 'center', gap: 'var(--space-sm)',
      color: 'var(--text-secondary)', fontSize: 'var(--font-size-sm)', fontWeight: '500'
    }
  }, ['Entity Types']);
  statsBreakdownEl.appendChild(breakdownTitle);

  const typesGrid = createElement('div', {
    style: { display: 'flex', flexWrap: 'wrap', gap: 'var(--space-sm)' }
  });

  const types = stats.types || {};
  for (const [type, count] of Object.entries(types)) {
    const style = TYPE_STYLES[type] || TYPE_STYLES.other;
    const badge = createElement('span', {
      className: 'badge',
      style: { borderColor: style.color, color: style.color, borderWidth: '1px', borderStyle: 'solid' }
    }, [`${style.label}: ${count}`]);
    typesGrid.appendChild(badge);
  }

  if (Object.keys(types).length === 0) {
    typesGrid.appendChild(
      createElement('span', {
        style: { color: 'var(--text-tertiary)', fontSize: 'var(--font-size-sm)' }
      }, ['No entities yet'])
    );
  }

  statsBreakdownEl.appendChild(typesGrid);
}

// ──────────────────────────────────────
// Rendering — Search results
// ──────────────────────────────────────

function renderResults(results) {
  empty(resultsEl);
  hideDetail();

  if (!results || results.length === 0) {
    resultsEl.style.display = 'none';
    if (searchInput && searchInput.value.trim()) {
      // Query active but no results
      hideEmptyState();
      resultsEl.style.display = 'flex';
      resultsEl.appendChild(
        createElement('div', {
          className: 'glass-subtle',
          style: {
            padding: 'var(--space-lg)', textAlign: 'center',
            borderRadius: 'var(--radius-md)', color: 'var(--text-secondary)'
          }
        }, ['No entities found'])
      );
    } else {
      showEmptyState();
    }
    return;
  }

  hideEmptyState();
  resultsEl.style.display = 'flex';

  const countLabel = createElement('div', {
    style: { color: 'var(--text-tertiary)', fontSize: 'var(--font-size-sm)' }
  }, [`${results.length} result${results.length !== 1 ? 's' : ''}`]);
  resultsEl.appendChild(countLabel);

  for (const entity of results) {
    const card = buildEntityCard(entity);
    resultsEl.appendChild(card);
  }
}

function buildEntityCard(entity) {
  const typeKey = (entity.type || 'other').toLowerCase();
  const style = TYPE_STYLES[typeKey] || TYPE_STYLES.other;

  const typeBadge = createElement('span', {
    className: 'badge',
    style: {
      backgroundColor: style.color + '22',
      color: style.color,
      fontSize: 'var(--font-size-xs)',
      padding: '2px 8px',
      borderRadius: 'var(--radius-sm)'
    }
  }, [style.label]);

  const nameEl = createElement('div', {
    style: {
      display: 'flex', alignItems: 'center', gap: 'var(--space-sm)',
      fontWeight: '500', color: 'var(--text-primary)', fontSize: 'var(--font-size-base)'
    }
  }, [escapeHtml(entity.name || 'Unnamed'), typeBadge]);

  const summaryEl = createElement('div', {
    style: {
      color: 'var(--text-secondary)', fontSize: 'var(--font-size-sm)',
      lineHeight: '1.4'
    }
  }, [truncate(entity.summary || '', 150) || 'No summary available']);

  const card = createElement('div', {
    className: 'glass-card animate-fade-in',
    style: {
      padding: 'var(--space-md)', cursor: 'pointer',
      transition: 'var(--transition-fast)',
      borderRadius: 'var(--radius-md)'
    },
    dataset: { entityId: String(entity.id) }
  }, [nameEl, summaryEl]);

  card.addEventListener('mouseenter', () => {
    card.style.background = 'var(--glass-bg-hover)';
  });
  card.addEventListener('mouseleave', () => {
    card.style.background = '';
  });

  card.addEventListener('click', () => selectEntity(entity));

  return card;
}

// ──────────────────────────────────────
// Rendering — Entity detail + relations
// ──────────────────────────────────────

async function selectEntity(entity) {
  selectedEntityId = entity.id;

  // Highlight the selected card
  const cards = $$('.glass-card', resultsEl);
  for (const c of cards) {
    c.style.borderColor = c.dataset.entityId === String(entity.id)
      ? 'var(--accent-primary)' : '';
  }

  // Show detail panel with loading state
  empty(detailEl);
  detailEl.style.display = 'flex';

  const detailHeader = createElement('div', {
    style: {
      display: 'flex', alignItems: 'center', gap: 'var(--space-sm)',
      color: 'var(--text-secondary)', fontSize: 'var(--font-size-sm)', fontWeight: '500'
    }
  }, [
    icon('expand', { size: 14 }),
    'Entity Detail'
  ]);
  detailEl.appendChild(detailHeader);

  const detailCard = createElement('div', {
    className: 'glass-card',
    style: { padding: 'var(--space-md)', borderRadius: 'var(--radius-md)' }
  });

  const typeKey = (entity.type || 'other').toLowerCase();
  const typeStyle = TYPE_STYLES[typeKey] || TYPE_STYLES.other;

  const detailTitle = createElement('div', {
    style: {
      display: 'flex', alignItems: 'center', gap: 'var(--space-sm)',
      fontWeight: '600', fontSize: 'var(--font-size-lg)', color: 'var(--text-primary)',
      marginBottom: 'var(--space-sm)'
    }
  }, [
    escapeHtml(entity.name || 'Unnamed'),
    createElement('span', {
      className: 'badge',
      style: {
        backgroundColor: typeStyle.color + '22', color: typeStyle.color,
        fontSize: 'var(--font-size-xs)', padding: '2px 8px'
      }
    }, [typeStyle.label])
  ]);

  const detailSummary = createElement('div', {
    style: {
      color: 'var(--text-secondary)', fontSize: 'var(--font-size-sm)',
      lineHeight: '1.5', marginBottom: 'var(--space-md)'
    }
  }, [entity.summary || 'No summary available']);

  detailCard.appendChild(detailTitle);
  detailCard.appendChild(detailSummary);

  // Relations loading indicator
  const relationsLoading = createElement('div', {
    className: 'shimmer',
    style: { height: '40px', borderRadius: 'var(--radius-sm)' }
  });
  detailCard.appendChild(relationsLoading);
  detailEl.appendChild(detailCard);

  // Fetch relations
  const relations = await loadEntityRelations(entity.id);

  // Check if still the selected entity (user may have clicked another)
  if (selectedEntityId !== entity.id) return;

  // Remove loading indicator
  if (relationsLoading.parentNode) relationsLoading.remove();

  if (relations.length === 0) {
    detailCard.appendChild(
      createElement('div', {
        style: { color: 'var(--text-tertiary)', fontSize: 'var(--font-size-sm)', fontStyle: 'italic' }
      }, ['No relations found'])
    );
    return;
  }

  const relationsHeader = createElement('div', {
    style: {
      color: 'var(--text-secondary)', fontSize: 'var(--font-size-sm)',
      fontWeight: '500', marginBottom: 'var(--space-xs)'
    }
  }, [`Relations (${relations.length})`]);
  detailCard.appendChild(relationsHeader);

  const relationsListEl = createElement('div', {
    style: { display: 'flex', flexDirection: 'column', gap: 'var(--space-xs)' }
  });

  for (const rel of relations) {
    const row = buildRelationRow(rel);
    relationsListEl.appendChild(row);
  }

  detailCard.appendChild(relationsListEl);
}

function buildRelationRow(rel) {
  const row = createElement('div', {
    className: 'glass-subtle',
    style: {
      display: 'flex', alignItems: 'center', gap: 'var(--space-xs)',
      padding: 'var(--space-sm)', borderRadius: 'var(--radius-sm)',
      fontSize: 'var(--font-size-sm)', flexWrap: 'wrap'
    }
  });

  const sourceLink = createElement('span', {
    style: { color: 'var(--accent-primary)', cursor: 'pointer', fontWeight: '500' }
  }, [escapeHtml(rel.sourceName || 'Unknown')]);
  sourceLink.addEventListener('click', (e) => {
    e.stopPropagation();
    searchForEntity(rel.sourceName);
  });

  const arrow = createElement('span', {
    style: { color: 'var(--text-tertiary)' }
  }, [' \u2192 ']);

  const relationLabel = createElement('span', {
    style: { color: 'var(--text-secondary)', fontStyle: 'italic' }
  }, [escapeHtml(rel.relation || 'related to')]);

  const targetArrow = createElement('span', {
    style: { color: 'var(--text-tertiary)' }
  }, [' \u2192 ']);

  const targetLink = createElement('span', {
    style: { color: 'var(--accent-primary)', cursor: 'pointer', fontWeight: '500' }
  }, [escapeHtml(rel.targetName || 'Unknown')]);
  targetLink.addEventListener('click', (e) => {
    e.stopPropagation();
    searchForEntity(rel.targetName);
  });

  row.appendChild(sourceLink);
  row.appendChild(arrow);
  row.appendChild(relationLabel);
  row.appendChild(targetArrow);
  row.appendChild(targetLink);

  return row;
}

function searchForEntity(name) {
  if (!name || !searchInput) return;
  searchInput.value = name;
  searchInput.dispatchEvent(new Event('input'));
}

// ──────────────────────────────────────
// Visibility helpers
// ──────────────────────────────────────

function showEmptyState() {
  if (emptyStateEl) emptyStateEl.style.display = 'flex';
}

function hideEmptyState() {
  if (emptyStateEl) emptyStateEl.style.display = 'none';
}

function showLoading() {
  if (loadingEl) loadingEl.style.display = 'block';
}

function hideLoading() {
  if (loadingEl) loadingEl.style.display = 'none';
}

function hideDetail() {
  if (detailEl) {
    detailEl.style.display = 'none';
    empty(detailEl);
  }
  selectedEntityId = null;
}
