'use client';

import { useCallback, useEffect, useRef, useState } from 'react';

interface RunningRow {
  id: string;
  workflowName: string;
  status: string;
  currentNode: string | null;
  progress: { done: number; total: number };
  createdAt: string;
}

interface UpcomingRow {
  id: string;
  name: string;
  body_kind: string;
  body_ref: string;
  next_run_at: string | null;
  schedule_kind: string;
  schedule_summary: string;
}

interface RecentRow {
  id: string;
  workflowName: string;
  status: string;
  completedAt: string | null;
  durationMs: number | null;
}

interface Summary {
  running: RunningRow[];
  upcoming: UpcomingRow[];
  recent: RecentRow[];
  generated_at: string;
}

const POLL_OPEN_MS = 5000;   // active polling while open
const POLL_BADGE_MS = 30000; // background polling while closed (just for counts)

function timeAgo(iso: string | null): string {
  if (!iso) return '';
  const s = Math.round((Date.now() - Date.parse(iso)) / 1000);
  if (s < 60) return `${s}s ago`;
  if (s < 3600) return `${Math.round(s / 60)}m ago`;
  if (s < 86400) return `${Math.round(s / 3600)}h ago`;
  return `${Math.round(s / 86400)}d ago`;
}

function timeUntil(iso: string | null): string {
  if (!iso) return '';
  const s = Math.round((Date.parse(iso) - Date.now()) / 1000);
  if (s < 0) return 'overdue';
  if (s < 60) return `in ${s}s`;
  if (s < 3600) return `in ${Math.round(s / 60)}m`;
  if (s < 86400) return `in ${Math.round(s / 3600)}h`;
  return `in ${Math.round(s / 86400)}d`;
}

function fmtDuration(ms: number | null): string {
  if (ms == null) return '';
  if (ms < 1000) return `${ms}ms`;
  if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;
  return `${Math.round(ms / 60_000)}m`;
}

function statusGlyph(s: string): string {
  if (s === 'done') return '✓';
  if (s === 'failed') return '✗';
  if (s === 'cancelled') return '⊘';
  if (s === 'running') return '▶';
  return s;
}

function statusColor(s: string): string {
  if (s === 'done') return 'text-green-500';
  if (s === 'failed') return 'text-red-400';
  if (s === 'cancelled') return 'text-gray-400';
  if (s === 'running') return 'text-blue-400';
  return 'text-[var(--text-secondary)]';
}

/**
 * Activity pill — top-right glanceable status for running pipelines +
 * upcoming schedules. Click to expand a 3-section dropdown. Polls every
 * 5s while open, 30s in background for badge counts.
 */
export default function ActivityPanel() {
  const [summary, setSummary] = useState<Summary | null>(null);
  const [open, setOpen] = useState(false);
  const panelRef = useRef<HTMLDivElement | null>(null);

  const refetch = useCallback(async () => {
    try {
      const r = await fetch('/api/activity/summary');
      if (!r.ok) return;
      const j: Summary = await r.json();
      setSummary(j);
    } catch { /* network blip — silent */ }
  }, []);

  // Initial fetch + adaptive polling cadence
  useEffect(() => {
    refetch();
    const ms = open ? POLL_OPEN_MS : POLL_BADGE_MS;
    const id = setInterval(refetch, ms);
    return () => clearInterval(id);
  }, [open, refetch]);

  // Click-outside dismisses
  useEffect(() => {
    if (!open) return;
    const onClick = (e: MouseEvent) => {
      if (panelRef.current && !panelRef.current.contains(e.target as Node)) {
        setOpen(false);
      }
    };
    window.addEventListener('mousedown', onClick);
    return () => window.removeEventListener('mousedown', onClick);
  }, [open]);

  const runningCount = summary?.running.length ?? 0;
  const upcomingCount = summary?.upcoming.length ?? 0;
  const recentFailed = (summary?.recent ?? []).filter((r) => r.status === 'failed').length;
  const hasAny = runningCount + upcomingCount + recentFailed > 0;

  // Pill border tint picks the most urgent state:
  // failed (red) > running (blue) > else dim.
  const borderTint = recentFailed > 0
    ? 'border-red-500/50'
    : runningCount > 0
      ? 'border-blue-500/50'
      : 'border-[var(--border)]';

  return (
    <div className="relative" ref={panelRef}>
      <button
        onClick={() => setOpen((o) => !o)}
        className={`text-[10px] px-2 py-0.5 rounded border ${borderTint} flex items-center gap-2.5
          text-[var(--text-secondary)] hover:text-[var(--text-primary)]`}
        title="Activity — running pipelines · upcoming schedules · recent failures"
      >
        {!hasAny ? (
          <span className="text-[var(--text-secondary)]">✓</span>
        ) : (
          <>
            {runningCount > 0 && (
              <span className="inline-flex items-baseline text-blue-400" title={`${runningCount} running`}>
                <span className="text-[7px] mr-0.5">●</span>
                <span className="font-semibold tabular-nums">{runningCount}</span>
              </span>
            )}
            {upcomingCount > 0 && (
              <span className="inline-flex items-baseline text-[var(--text-secondary)]" title={`${upcomingCount} upcoming`}>
                <span className="text-[8px] mr-0.5">◷</span>
                <span className="font-semibold tabular-nums">{upcomingCount}</span>
              </span>
            )}
            {recentFailed > 0 && (
              <span className="inline-flex items-baseline text-red-400" title={`${recentFailed} recently failed`}>
                <span className="text-[8px] mr-0.5">✕</span>
                <span className="font-semibold tabular-nums">{recentFailed}</span>
              </span>
            )}
          </>
        )}
      </button>

      {open && (
        <div
          className="absolute right-0 mt-1 w-[440px] max-h-[70vh] overflow-y-auto bg-[var(--bg-secondary)] border border-[var(--border)] rounded-lg shadow-xl z-50"
          onClick={(e) => e.stopPropagation()}
        >
          {summary === null ? (
            <div className="p-6 text-center text-xs text-[var(--text-secondary)]">Loading…</div>
          ) : (
            <div className="p-3 space-y-4">
              {/* Running */}
              <Section title="Running" count={runningCount}>
                {runningCount === 0 ? (
                  <Empty>Nothing running.</Empty>
                ) : (
                  summary.running.map((r) => (
                    <div key={r.id} className="flex items-start gap-2 text-xs py-1">
                      <span className={`${statusColor(r.status)} mt-0.5`}>{statusGlyph(r.status)}</span>
                      <div className="flex-1 min-w-0">
                        <div className="flex items-center gap-2">
                          <span className="text-[var(--text-primary)] font-medium truncate">{r.workflowName}</span>
                          <span className="text-[10px] text-[var(--text-secondary)]">
                            {r.progress.done}/{r.progress.total}
                          </span>
                          <span className="text-[10px] text-gray-500">{timeAgo(r.createdAt)}</span>
                        </div>
                        {r.currentNode && (
                          <div className="text-[10px] text-[var(--text-secondary)] mt-0.5">
                            current: {r.currentNode}
                          </div>
                        )}
                      </div>
                      <button
                        onClick={() => {
                          setOpen(false);
                          window.dispatchEvent(new CustomEvent('forge:navigate', { detail: { view: 'pipelines', pipelineId: r.id } }));
                        }}
                        className="text-[10px] px-1.5 py-0.5 rounded border border-[var(--border)] text-[var(--text-secondary)] hover:text-[var(--text-primary)]"
                      >
                        view
                      </button>
                    </div>
                  ))
                )}
              </Section>

              {/* Upcoming */}
              <Section title="Next up" count={upcomingCount}>
                {upcomingCount === 0 ? (
                  <Empty>No enabled schedules.</Empty>
                ) : (
                  summary.upcoming.map((u) => (
                    <div key={u.id} className="flex items-start gap-2 text-xs py-1">
                      <span className="text-[var(--text-secondary)] mt-0.5">⏰</span>
                      <div className="flex-1 min-w-0">
                        <div className="flex items-center gap-2">
                          <span className="text-[var(--text-primary)] font-medium truncate">{u.name}</span>
                          <span className="text-[10px] text-blue-400">{timeUntil(u.next_run_at)}</span>
                        </div>
                        <div className="text-[10px] text-[var(--text-secondary)] mt-0.5 truncate">
                          {u.body_kind}: {u.body_ref} · {u.schedule_summary}
                        </div>
                      </div>
                    </div>
                  ))
                )}
              </Section>

              {/* Recent */}
              <Section title="Recent" count={summary.recent.length}>
                {summary.recent.length === 0 ? (
                  <Empty>No recent runs.</Empty>
                ) : (
                  summary.recent.map((r) => (
                    <div key={r.id} className="flex items-start gap-2 text-xs py-1">
                      <span className={`${statusColor(r.status)} mt-0.5`}>{statusGlyph(r.status)}</span>
                      <div className="flex-1 min-w-0">
                        <div className="flex items-center gap-2">
                          <span className="text-[var(--text-primary)] truncate">{r.workflowName}</span>
                          <span className="text-[10px] text-[var(--text-secondary)]">
                            {fmtDuration(r.durationMs)} · {timeAgo(r.completedAt)}
                          </span>
                        </div>
                      </div>
                      <button
                        onClick={() => {
                          setOpen(false);
                          window.dispatchEvent(new CustomEvent('forge:navigate', { detail: { view: 'pipelines', pipelineId: r.id } }));
                        }}
                        className="text-[10px] px-1.5 py-0.5 rounded border border-[var(--border)] text-[var(--text-secondary)] hover:text-[var(--text-primary)]"
                      >
                        view
                      </button>
                    </div>
                  ))
                )}
              </Section>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

function Section({ title, count, children }: { title: string; count: number; children: React.ReactNode }) {
  return (
    <div>
      <h3 className="text-[10px] font-semibold text-[var(--text-secondary)] uppercase mb-1 flex items-center gap-2">
        {title}
        <span className="text-gray-500 font-normal">({count})</span>
      </h3>
      <div className="space-y-0.5">{children}</div>
    </div>
  );
}

function Empty({ children }: { children: React.ReactNode }) {
  return <div className="text-[10px] text-gray-500 italic py-0.5">{children}</div>;
}
