/* global React, Button, Icon, EmptyState, LoadingSpinner, Select, useApiResource, formatDateTime, shortId, displayModelName */
const {
  useEffect: useEffectMcpInst,
  useMemo: useMemoMcpInst,
  useState: useStateMcpInst,
} = React;

const MCP_INSTRUMENTATION_TABS = [
  { key: 'intent', label: 'Intent', icon: 'target' },
  { key: 'blocker', label: 'Blockers', icon: 'alert' },
  { key: 'frustration', label: 'Friction', icon: 'zap' },
];

function McpInstrumentationPage({ navigate, queryString = '' }) {
  const query = useMemoMcpInst(() => new URLSearchParams(queryString), [queryString]);
  const activeKind = normalizeMcpInstrumentationKind(query.get('kind'));
  const page = Math.max(0, Number.parseInt(query.get('page') || '0', 10) || 0);
  const q = query.get('q') || '';
  const filters = {
    client: query.get('client') || 'all',
    harness: query.get('harness') || 'all',
    model: query.get('model') || 'all',
    mcp: query.get('mcp') || 'all',
    workflow: query.get('workflow') || 'all',
  };
  const [searchDraft, setSearchDraft] = useStateMcpInst(q);
  const limit = 50;
  const apiPath = `/api/mcp-instrumentation/events?${buildMcpInstrumentationApiQuery({
    kind: activeKind,
    q,
    filters,
    limit,
    offset: page * limit,
  })}`;
  const events = useApiResource(apiPath, [activeKind, q, page, filters.client, filters.harness, filters.model, filters.mcp, filters.workflow]);
  const rows = events.data?.rows || [];
  const total = events.data?.total || 0;
  const filterOptions = events.data?.filterOptions || {};
  const hasNext = (page + 1) * limit < total;
  const loadingInitial = events.loading && !events.data;
  const refreshing = events.loading && Boolean(events.data);
  const filtersDirty = q
    || Object.values(filters).some((value) => value && value !== 'all');

  useEffectMcpInst(() => {
    if (!query.has('limit') && !query.has('offset')) return;
    navigate(`/mcp-instrumentation?${buildMcpInstrumentationRouteQuery({ kind: activeKind, q, page, filters })}`);
  }, [activeKind, filters.client, filters.harness, filters.model, filters.mcp, filters.workflow, navigate, page, q, query]);

  useEffectMcpInst(() => {
    setSearchDraft(q);
  }, [q]);

  function setKind(kind) {
    navigate(`/mcp-instrumentation?${buildMcpInstrumentationRouteQuery({ kind, q, filters })}`);
  }

  function submitSearch(event) {
    event?.preventDefault?.();
    navigate(`/mcp-instrumentation?${buildMcpInstrumentationRouteQuery({ kind: activeKind, q: searchDraft, filters })}`);
  }

  function setFilter(key, value) {
    navigate(`/mcp-instrumentation?${buildMcpInstrumentationRouteQuery({
      kind: activeKind,
      q,
      filters: { ...filters, [key]: value },
    })}`);
  }

  function setPage(nextPage) {
    navigate(`/mcp-instrumentation?${buildMcpInstrumentationRouteQuery({ kind: activeKind, q, page: nextPage, filters })}`);
  }

  return (
    <div className="page-inner mcp-instrumentation-page">
      <div className="ui-page-head">
        <div>
          <h1 className="ui-page-title">MCP Instrumentation</h1>
          <p className="ui-page-subtitle">Reflection events captured from the instrumented Armature MCP endpoint.</p>
        </div>
        <div className="ui-page-actions">
          <Button
            size="sm"
            variant="ghost"
            loading={refreshing}
            loadingLabel="Refreshing"
            onClick={() => events.reload()}>
            <Icon name="refresh" size={13} />Refresh
          </Button>
        </div>
      </div>

      <div className="mcp-inst-toolbar">
        <div className="mcp-inst-tabs" role="tablist" aria-label="Event kind">
          {MCP_INSTRUMENTATION_TABS.map((tab) => (
            <button
              key={tab.key}
              type="button"
              role="tab"
              aria-selected={activeKind === tab.key}
              className={`mcp-inst-tab ${activeKind === tab.key ? 'active' : ''}`}
              onClick={() => setKind(tab.key)}>
              <Icon name={tab.icon} size={13} />
              <span>{tab.label}</span>
            </button>
          ))}
        </div>
        <form className="mcp-inst-search" onSubmit={submitSearch}>
          <Icon name="search" size={14} />
          <input
            value={searchDraft}
            onChange={(event) => setSearchDraft(event.target.value)}
            placeholder={activeKind === 'intent' ? 'Search summaries' : activeKind === 'blocker' ? 'Search reasons or attempts' : 'Search friction'}
            aria-label="Search MCP instrumentation events" />
          <Button size="sm" variant="secondary" type="submit">Search</Button>
        </form>
      </div>

      <div className="mcp-inst-filters">
        <Select
          label="Client"
          value={filters.client}
          options={mcpInstrumentationOptions(filterOptions.clients, 'All clients')}
          searchable
          portal
          onChange={(value) => setFilter('client', value)} />
        <Select
          label="Harness"
          value={filters.harness}
          options={mcpInstrumentationOptions(filterOptions.harnesses, 'All harnesses', formatMcpInstrumentationHarnessOption)}
          searchable
          portal
          onChange={(value) => setFilter('harness', value)} />
        <Select
          label="Model"
          value={filters.model}
          options={mcpInstrumentationOptions(filterOptions.models, 'All models', (row) => displayModelName(row.label))}
          searchable
          portal
          onChange={(value) => setFilter('model', value)} />
        <Select
          label="MCP"
          value={filters.mcp}
          options={mcpInstrumentationOptions(filterOptions.mcps, 'All MCPs')}
          searchable
          portal
          onChange={(value) => setFilter('mcp', value)} />
        <Select
          label="Workflow"
          value={filters.workflow}
          options={mcpInstrumentationOptions(filterOptions.workflows, 'All workflows')}
          searchable
          portal
          onChange={(value) => setFilter('workflow', value)} />
        {filtersDirty && (
          <Button
            size="sm"
            variant="ghost"
            onClick={() => {
              setSearchDraft('');
              navigate(`/mcp-instrumentation?${buildMcpInstrumentationRouteQuery({ kind: activeKind })}`);
            }}>
            <Icon name="x" size={11} />Clear
          </Button>
        )}
      </div>

      <div className="runs-table-wrap mcp-inst-table-wrap">
        <table className="runs-table mcp-inst-table">
          <thead>
            <tr>
              <th>Received</th>
              <th>Client</th>
              <th>{activeKind === 'intent' ? 'Summary' : activeKind === 'blocker' ? 'Reason' : 'Description'}</th>
              <th>Workflow / MCP / Model</th>
            </tr>
          </thead>
          <tbody>
            {loadingInitial ? (
              <McpInstrumentationLoadingRows />
            ) : rows.length === 0 ? (
              <tr>
                <td colSpan={4}>
                  <EmptyState
                    icon="search"
                    title="No events found"
                    body={q ? 'Try a different search.' : 'No instrumentation events have been captured for this tab yet.'} />
                </td>
              </tr>
            ) : rows.map((row) => (
              <McpInstrumentationEventRow
                key={row.id}
                row={row}
                activeKind={activeKind}
                navigate={navigate} />
            ))}
          </tbody>
        </table>
      </div>

      <div className="mcp-inst-pagination">
        <Button size="sm" variant="ghost" disabled={page === 0} onClick={() => setPage(page - 1)}>
          <Icon name="chevronLeft" size={13} />Previous
        </Button>
        <span className="text-xs muted">Page {page + 1}</span>
        <Button size="sm" variant="ghost" disabled={!hasNext} onClick={() => setPage(page + 1)}>
          Next<Icon name="chevronRight" size={13} />
        </Button>
      </div>
    </div>
  );
}

function McpInstrumentationEventRow({ row, activeKind, navigate }) {
  const payloadText = activeKind === 'intent'
    ? row.payload?.summary
    : activeKind === 'blocker'
      ? row.payload?.reason
      : row.payload?.description;
  const attempted = row.payload?.attempted;
  const clientName = row.clientInfo?.title || row.clientInfo?.name || 'Unknown client';
  const clientVersion = row.clientInfo?.version || '';
  const workflowRun = row.workflowRun;
  return (
    <tr className="runs-row mcp-inst-row">
      <td className="mcp-inst-time">
        <div>{formatDateTime(row.receivedAt)}</div>
        <div className="mono muted">{shortId(row.agentRunId)}</div>
      </td>
      <td>
        <McpInstrumentationClientCell name={clientName} version={clientVersion} />
      </td>
      <td className="mcp-inst-payload">
        {activeKind === 'frustration' && (
          <div className="mcp-inst-chip-row">
            <span className="ui-pill">{row.payload?.kind || 'friction'}</span>
            {row.payload?.relatedTool && <span className="ui-pill ui-pill-brand">{row.payload.relatedTool}</span>}
          </div>
        )}
        <div>{payloadText || '-'}</div>
        {Array.isArray(attempted) && attempted.length > 0 && (
          <ul className="mcp-inst-attempted">
            {attempted.map((item, index) => <li key={`${row.id}-attempt-${index}`}>{item}</li>)}
          </ul>
        )}
      </td>
      <td className="mcp-inst-run-cell">
        {workflowRun ? (
          <>
            <button
              type="button"
              className="link-btn mcp-inst-run-link"
              onClick={() => navigate(`/runs/${workflowRun.id}`)}>
              <span>{workflowRun.name || shortId(workflowRun.id)}</span>
            </button>
            <div className="mcp-inst-run-harness">
              <McpInstrumentationHarnessCell
                sdkKey={workflowRun.testerSdkKey}
                sdkName={workflowRun.testerSdkDisplayName}
                modelName={workflowRun.testerModelName} />
            </div>
            <div className="mcp-inst-run-meta">
              <span><span className="mcp-inst-run-label">MCP</span>{workflowRun.mcpServerName || 'Not recorded'}</span>
              <span><span className="mcp-inst-run-label">Run</span><span className="mono">{shortId(workflowRun.id)}</span></span>
            </div>
          </>
        ) : (
          <span className="muted">Not attributed</span>
        )}
      </td>
    </tr>
  );
}

const MCP_INST_HARNESS_LOGOS = {
  codex: { src: '/frontend/assets/logos/codex.png', label: 'Codex' },
  claude: { src: '/frontend/assets/logos/claude-code.png', label: 'Claude Code' },
  anthropic_api: { src: '/frontend/assets/logos/anthropic.svg.png', label: 'Claude' },
  openai_api: { src: '/frontend/assets/logos/chatgpt.png', label: 'ChatGPT' },
  gemini: { src: '/frontend/assets/logos/gemini.png', label: 'Gemini CLI' },
  cursor: { src: '/frontend/assets/logos/cursor.png', label: 'Cursor' },
  openclaw: { src: '/frontend/assets/logos/openclaw.svg', label: 'Openclaw' },
  opencode: { src: '/frontend/assets/logos/opencode.svg', label: 'OpenCode' },
};

function McpInstrumentationClientCell({ name, version }) {
  const logo = mcpInstrumentationClientLogo(name);
  return (
    <span className="mcp-inst-client-cell">
      <span className="harness-cell-glyph" aria-hidden>
        {logo
          ? <img src={logo.src} alt="" className="harness-cell-logo" width="14" height="14" />
          : <Icon name="cpu" size={12} />}
      </span>
      <span className="mcp-inst-client-copy">
        <span className="mcp-inst-client">{logo?.label || name}</span>
        {version && <span className="text-xs muted">{version}</span>}
      </span>
    </span>
  );
}

function McpInstrumentationHarnessCell({ sdkKey, sdkName, modelName = '' }) {
  const logo = sdkKey ? MCP_INST_HARNESS_LOGOS[sdkKey] : null;
  const harnessLabel = logo?.label || sdkName || sdkKey || 'Harness';
  return (
    <span className="harness-cell mcp-inst-harness-cell">
      <span className="harness-cell-glyph" aria-hidden>
        {logo
          ? <img src={logo.src} alt="" className="harness-cell-logo" width="14" height="14" />
          : <Icon name="cpu" size={12} />}
      </span>
      <span className="harness-cell-name">{harnessLabel}</span>
      {modelName && <span className="harness-cell-model mono">{displayModelName(modelName)}</span>}
    </span>
  );
}

function mcpInstrumentationClientLogo(name) {
  const value = String(name || '').toLowerCase();
  if (value.includes('codex') || value.includes('openai')) return MCP_INST_HARNESS_LOGOS.codex;
  if (value.includes('claude') || value.includes('anthropic')) return MCP_INST_HARNESS_LOGOS.claude;
  if (value.includes('cursor')) return MCP_INST_HARNESS_LOGOS.cursor;
  if (value.includes('gemini') || value.includes('google')) return MCP_INST_HARNESS_LOGOS.gemini;
  if (value.includes('openclaw')) return MCP_INST_HARNESS_LOGOS.openclaw;
  if (value.includes('opencode')) return MCP_INST_HARNESS_LOGOS.opencode;
  return null;
}

function McpInstrumentationLoadingRows() {
  return (
    <tr className="runs-row">
      <td colSpan={4}>
        <div className="inline-loading">
          <LoadingSpinner size="sm" label="Loading instrumentation events" decorative />
          Loading events...
        </div>
      </td>
    </tr>
  );
}

function normalizeMcpInstrumentationKind(value) {
  return ['intent', 'blocker', 'frustration'].includes(value) ? value : 'intent';
}

function buildMcpInstrumentationRouteQuery({ kind, q = '', page = 0, filters = {} }) {
  const params = new URLSearchParams();
  params.set('kind', normalizeMcpInstrumentationKind(kind));
  if (q) params.set('q', q);
  for (const key of ['client', 'harness', 'model', 'mcp', 'workflow']) {
    if (filters[key] && filters[key] !== 'all') params.set(key, filters[key]);
  }
  if (page) params.set('page', String(page));
  return params.toString();
}

function buildMcpInstrumentationApiQuery({ kind, q = '', filters = {}, limit = 50, offset = 0 }) {
  const params = new URLSearchParams(buildMcpInstrumentationRouteQuery({ kind, q, filters }));
  params.set('limit', String(limit));
  params.set('offset', String(offset));
  return params.toString();
}

function mcpInstrumentationOptions(rows = [], allLabel, labelFormatter = (row) => row.label) {
  return [
    { value: 'all', label: allLabel },
    ...(Array.isArray(rows) ? rows : []).map((row) => ({
      value: row.value,
      label: labelFormatter(row) || row.label,
    })),
  ];
}

function formatMcpInstrumentationHarnessOption(row) {
  return MCP_INST_HARNESS_LOGOS[row.value]?.label || row.label;
}
