import { html, useState, useEffect, useCallback, useRef } from '../lib/preact.js';

/**
 * Lightweight toast notification system.
 * Tracks error counts and surfaces persistent issues.
 */

// Singleton state for toast management (shared across components)
let toastListeners = [];
let toastIdCounter = 0;

export function showToast(message, type = 'error', duration = 5000) {
  const id = ++toastIdCounter;
  const toast = { id, message, type, duration };
  toastListeners.forEach(listener => listener(toast));
  return id;
}

export function ToastContainer() {
  const [toasts, setToasts] = useState([]);
  const timeoutIds = useRef(new Map());

  useEffect(() => {
    const listener = (toast) => {
      setToasts(prev => [...prev, toast]);
      if (toast.duration > 0) {
        const timeoutId = setTimeout(() => {
          timeoutIds.current.delete(toast.id);
          setToasts(prev => prev.filter(t => t.id !== toast.id));
        }, toast.duration);
        timeoutIds.current.set(toast.id, timeoutId);
      }
    };
    toastListeners.push(listener);
    return () => {
      toastListeners = toastListeners.filter(l => l !== listener);
      // Clear all pending timeouts on unmount
      timeoutIds.current.forEach(id => clearTimeout(id));
      timeoutIds.current.clear();
    };
  }, []);

  const dismiss = useCallback((id) => {
    // Clear auto-dismiss timeout if exists
    const timeoutId = timeoutIds.current.get(id);
    if (timeoutId) {
      clearTimeout(timeoutId);
      timeoutIds.current.delete(id);
    }
    setToasts(prev => prev.filter(t => t.id !== id));
  }, []);

  if (toasts.length === 0) return null;

  return html`
    <div class="fixed bottom-4 right-4 z-[100] flex flex-col gap-2 pointer-events-none">
      ${toasts.map(toast => html`
        <div
          key=${toast.id}
          class="pointer-events-auto flex items-start gap-3 rounded-xl border px-4 py-3 shadow-lg backdrop-blur-sm animate-fade-in-up ${
            toast.type === 'error'
              ? 'border-attention/50 bg-attention/15 text-attention'
              : toast.type === 'success'
              ? 'border-active/50 bg-active/15 text-active'
              : 'border-starting/50 bg-starting/15 text-starting'
          }"
          style=${{ maxWidth: '380px' }}
        >
          <div class="flex-1 text-sm font-medium">${toast.message}</div>
          <button
            onClick=${() => dismiss(toast.id)}
            class="shrink-0 rounded p-0.5 opacity-70 transition-opacity hover:opacity-100"
          >
            <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
            </svg>
          </button>
        </div>
      `)}
    </div>
  `;
}

/**
 * Error tracker for surfacing repeated failures.
 * Tracks errors by key and shows toast after threshold.
 */
const errorCounts = {};
const ERROR_THRESHOLD = 3;
const ERROR_WINDOW_MS = 30000; // 30 second window

export function trackError(key, message, { log = true, threshold = ERROR_THRESHOLD } = {}) {
  const now = Date.now();

  // Always log
  if (log) {
    console.error(`[${key}]`, message);
  }

  // Track error count within window
  if (!errorCounts[key]) {
    errorCounts[key] = { count: 0, firstAt: now, lastToastAt: 0 };
  }

  const tracker = errorCounts[key];

  // Reset if outside window
  if (now - tracker.firstAt > ERROR_WINDOW_MS) {
    tracker.count = 0;
    tracker.firstAt = now;
  }

  tracker.count++;

  // Surface toast after threshold, but not too frequently
  if (tracker.count >= threshold && now - tracker.lastToastAt > ERROR_WINDOW_MS) {
    showToast(`${message} (repeated ${tracker.count}x)`, 'error');
    tracker.lastToastAt = now;
    tracker.count = 0; // Reset after showing toast
  }
}

export function clearErrorCount(key) {
  delete errorCounts[key];
}
