/**
 * activity-feed.mjs — AI-Do v4.0 activity feed component
 * Displays a chronological feed of agent events with expand/collapse detail,
 * type-colored icons, stagger animation, and refresh from API.
 */

import store from '../store.mjs';
import api from '../api.mjs';
import { $, createElement, icon, empty } from '../utils/dom.mjs';
import { relativeTime, truncate } from '../utils/format.mjs';
import { openPreview } from './preview-panel.mjs';

// ── DOM references ──
let container = null;
let listEl = null;
let emptyEl = null;
let refreshBtn = null;

// ── Kind-to-icon mapping ──
const KIND_ICONS = {
  chat: 'chat',
  skill: 'skills',
  system: 'info',
  error: 'info',
  memory: 'focus',
  journal: 'journal',
  file: 'create',
  ingestion: 'globe',
  cognitive: 'focus'
};

// ── Filter tabs ──
const FILTER_TABS = [
  { id: 'all', label: 'All' },
  { id: 'chat', label: 'Chat' },
  { id: 'skill', label: 'Skills' },
  { id: 'system', label: 'System' },
  { id: 'error', label: 'Errors' }
];
let activeFilter = 'all';

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

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

  buildDOM();
  subscribeToStore();

  // Render initial feed from store, or show skeletons and fetch
  const feed = store.getState().activity.feed;
  if (feed.length > 0) {
    renderFeed(feed, true);
  } else {
    showInitialSkeletons();
    handleRefresh();
  }
}

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

function buildDOM() {
  empty(container);
  container.classList.add('activity-feed');

  // Header
  const header = createElement('div', { className: 'activity-feed-header' });
  header.appendChild(createElement('h2', {}, ['Activity']));

  refreshBtn = createElement('button', {
    className: 'refresh-btn',
    'aria-label': 'Refresh activity feed'
  });
  refreshBtn.appendChild(icon('refresh', { size: 16 }));
  refreshBtn.addEventListener('click', handleRefresh);
  header.appendChild(refreshBtn);

  container.appendChild(header);

  // Filter tabs
  const tabs = createElement('div', { className: 'activity-feed-tabs' });
  for (const tab of FILTER_TABS) {
    const btn = createElement('button', {
      className: `activity-tab${tab.id === activeFilter ? ' active' : ''}`,
      dataset: { filter: tab.id }
    }, [tab.label]);
    btn.addEventListener('click', () => {
      activeFilter = tab.id;
      // Update active tab styling
      tabs.querySelectorAll('.activity-tab').forEach(t => t.classList.remove('active'));
      btn.classList.add('active');
      // Re-render with filter
      const feed = store.getState().activity.feed;
      renderFeed(feed, false);
    });
    tabs.appendChild(btn);
  }
  container.appendChild(tabs);

  // List container
  listEl = createElement('div', { className: 'activity-feed-list' });
  container.appendChild(listEl);

  // Empty state (hidden by default, shown when list is empty)
  emptyEl = createElement('div', { className: 'activity-feed-empty' });
  emptyEl.appendChild(icon('activity', { size: 48 }));
  emptyEl.appendChild(createElement('p', {}, ['No activity yet']));
  emptyEl.style.display = 'none';
  container.appendChild(emptyEl);
}

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

function subscribeToStore() {
  // Full feed replacement (e.g. from refresh)
  store.subscribe(
    (s) => s.activity.feed,
    (feed, prevFeed) => {
      // Determine if this is a new single item prepended or a full replacement
      if (feed.length > 0 && prevFeed && feed.length === prevFeed.length + 1) {
        // Single new item added at top
        prependItem(feed[0]);
      } else {
        // Full re-render (initial load or refresh)
        renderFeed(feed, false);
      }
    }
  );
}

// ──────────────────────────────────────
// Rendering
// ──────────────────────────────────────

function showInitialSkeletons() {
  if (!listEl) return;
  empty(listEl);
  listEl.style.display = 'flex';
  if (emptyEl) emptyEl.style.display = 'none';
  for (let i = 0; i < 3; i++) {
    listEl.appendChild(createElement('div', { className: 'skeleton skeleton-card' }));
  }
}

function renderFeed(feed, stagger) {
  if (!listEl) return;
  empty(listEl);

  // Apply active filter
  let filtered = feed || [];
  if (activeFilter !== 'all') {
    filtered = filtered.filter(e => (e.kind || 'system') === activeFilter);
  }

  if (filtered.length === 0) {
    listEl.style.display = 'none';
    if (emptyEl) emptyEl.style.display = 'flex';
    return;
  }

  listEl.style.display = 'flex';
  if (emptyEl) emptyEl.style.display = 'none';

  // Apply stagger class for initial load animation
  if (stagger) {
    listEl.classList.add('stagger-load');
  } else {
    listEl.classList.remove('stagger-load');
  }

  for (const event of filtered) {
    const item = buildActivityItem(event, false);
    listEl.appendChild(item);
  }

  // Remove stagger class after animation completes
  if (stagger) {
    setTimeout(() => {
      listEl.classList.remove('stagger-load');
    }, 400);
  }
}

function prependItem(event) {
  if (!listEl) return;

  // Hide empty state
  if (emptyEl) emptyEl.style.display = 'none';
  listEl.style.display = 'flex';

  const item = buildActivityItem(event, true);
  if (listEl.firstChild) {
    listEl.insertBefore(item, listEl.firstChild);
  } else {
    listEl.appendChild(item);
  }

  // Trim list to maxItems
  const maxItems = store.getState().activity.maxItems || 100;
  while (listEl.children.length > maxItems) {
    listEl.removeChild(listEl.lastChild);
  }
}

function buildActivityItem(event, animate) {
  const kind = event.kind || 'system';
  const content = event.content || '';
  const timestamp = event.timestamp;
  const source = event.source || '';
  let metadata = event.metadata || {};
  if (typeof metadata === 'string') {
    try { metadata = JSON.parse(metadata); } catch { metadata = {}; }
  }

  const item = createElement('div', {
    className: `activity-item${animate ? ' animate-in' : ''}`
  });

  // Main row wrapper (for expanded layout)
  const row = createElement('div', { className: 'activity-item-row' });

  // Type icon
  const iconName = KIND_ICONS[kind] || 'info';
  const iconEl = createElement('div', { className: `activity-item-icon kind-${kind}` });
  iconEl.appendChild(icon(iconName, { size: 16 }));
  row.appendChild(iconEl);

  // Content area
  const contentArea = createElement('div', { className: 'activity-item-content' });

  const desc = createElement('div', { className: 'activity-item-desc' }, [
    truncate(content, 80) || 'No description'
  ]);
  contentArea.appendChild(desc);

  const ts = createElement('div', { className: 'activity-item-timestamp' }, [
    timestamp ? relativeTime(timestamp) : ''
  ]);
  contentArea.appendChild(ts);

  row.appendChild(contentArea);
  item.appendChild(row);

  // Detail section (hidden until expanded)
  const detail = createElement('div', { className: 'activity-item-detail' });

  // Full content text
  if (content) {
    detail.appendChild(document.createTextNode(content));
  }

  // Metadata tags
  const metaTags = [];
  if (source) metaTags.push(`source: ${source}`);
  if (kind) metaTags.push(`type: ${kind}`);
  if (metadata && typeof metadata === 'object') {
    for (const [key, val] of Object.entries(metadata)) {
      if (val == null) continue;
      if (typeof val === 'object') {
        metaTags.push(`${key}: ${JSON.stringify(val)}`);
      } else {
        metaTags.push(`${key}: ${val}`);
      }
    }
  }

  if (metaTags.length > 0) {
    const metaContainer = createElement('div', { className: 'activity-item-meta' });
    for (const tag of metaTags) {
      metaContainer.appendChild(
        createElement('span', { className: 'activity-item-meta-tag' }, [tag])
      );
    }
    detail.appendChild(metaContainer);
  }

  item.appendChild(detail);

  // Click to expand/collapse (or preview file)
  item.addEventListener('click', () => {
    if (kind === 'file' && metadata?.path) {
      openPreview(metadata.path);
      store.dispatch('SET_VIEW', 'chat');
      return;
    }
    item.classList.toggle('expanded');
  });

  return item;
}

// ──────────────────────────────────────
// Refresh handler
// ──────────────────────────────────────

async function handleRefresh() {
  if (!refreshBtn) return;

  refreshBtn.classList.add('refreshing');

  try {
    const events = await api.getEvents(200);

    // Map API events to activity feed format, newest first
    const feed = (Array.isArray(events) ? events : []).map(evt => ({
      id: evt.id,
      kind: evt.type || evt.kind || 'system',
      source: evt.source || '',
      content: evt.content || '',
      timestamp: evt.created_at || evt.timestamp || Date.now(),
      metadata: evt.metadata ? (typeof evt.metadata === 'string' ? tryParseJSON(evt.metadata) : evt.metadata) : {}
    })).reverse();

    // Dedup by id
    const seen = new Set();
    const deduped = feed.filter(e => {
      if (!e.id || seen.has(e.id)) return false;
      seen.add(e.id);
      return true;
    });

    store.dispatch('SET_ACTIVITY_FEED', deduped);
  } catch (err) {
    console.error('[activity-feed] Refresh failed:', err);
  } finally {
    refreshBtn.classList.remove('refreshing');
  }
}

function tryParseJSON(str) {
  try { return JSON.parse(str); } catch { return {}; }
}
