import React, { useEffect, useMemo, useRef, useState } from 'react';
import { ActivityIndicator, Text, TextInput, View } from 'react-native';
import { Search } from 'lucide-react-native';

import { ConnectedConnectorCard, ConnectorCard } from './ConnectorCards';
import { ConnectorDetailView } from './ConnectorDetailView';
import { SUPERAGENT_CONNECTOR_CATALOG } from './connectorCatalog';
import { sortConnectorsByPopularity } from './connectorCatalogUtils';
import { getConnectorScopesForMode } from './connectorPanelUtils';
import { connectorPanelStyles as cStyles } from './connectorPanelStyles';
import { editorShellStyles } from '../editor/editorShellStyles';
import { useAgentBi } from '../../analytics/mixpanelContext';
import { useSuperagentConnectors } from '../../runtime/runtimeContext';
import { themedColor } from '../../theme';
import type { SuperagentAgent, SuperagentConnector, SuperagentConnectorAccessMode } from '../../types';

export function ConnectorsPanel({
  agent,
  isVisible = true,
  onBackHandlerChange,
}: {
  agent: SuperagentAgent;
  // Whether the containing settings sheet is open. When it closes we reset the
  // in-sheet navigation so reopening always starts at the main list (and the
  // top-bar shows ✕, not a stale ←).
  isVisible?: boolean;
  // Report a back handler so the modal top-bar swaps its ✕ for a ← while
  // viewing a connector's detail (null = at the main view).
  onBackHandlerChange?: (back: (() => void) | null) => void;
}) {
  const {
    availableConnectors,
    connectedConnectors,
    connectingConnectorId,
    isLoadingConnectors: isLoading,
    onCancelConnectorConnection: onCancel,
    onConnectConnector: onConnect,
    onDisconnectConnector: onDisconnect,
    onRemoveConnector: onRemove,
  } = useSuperagentConnectors();
  const bi = useAgentBi();

  // In-sheet navigation: tapping a connector pushes its detail view within the
  // same settings modal (no nested modal-on-modal).
  const [detailConnector, setDetailConnector] = useState<SuperagentConnector | null>(null);
  const [searchQuery, setSearchQuery] = useState('');

  // Native-only: report the settled query, not per keystroke. Web has fixed filter
  // tabs (Plugins Filter) instead of a free-text box, so this is its own event.
  useEffect(() => {
    const normalizedQuery = searchQuery.trim();
    if (!normalizedQuery) return;
    const timer = setTimeout(() => {
      void bi.trackEditor('Connector Search', { query_length: normalizedQuery.length });
    }, 400);
    return () => clearTimeout(timer);
  }, [searchQuery, bi]);

  useEffect(() => {
    onBackHandlerChange?.(detailConnector ? () => setDetailConnector(null) : null);
  }, [detailConnector, onBackHandlerChange]);
  useEffect(() => () => onBackHandlerChange?.(null), [onBackHandlerChange]);

  // Reset to the main list whenever the sheet is hidden, so reopening never
  // resurfaces a stale detail screen with a broken back control.
  useEffect(() => {
    if (!isVisible) {
      setDetailConnector(null);
    }
  }, [isVisible]);

  // Once the in-flight connection for the connector we're viewing ends (success,
  // failure, or cancel), pop back to the list so it lands under "Apps connected".
  const prevConnectingId = useRef(connectingConnectorId);
  useEffect(() => {
    const previous = prevConnectingId.current;
    prevConnectingId.current = connectingConnectorId;
    if (detailConnector && previous === detailConnector.id && connectingConnectorId !== detailConnector.id) {
      setDetailConnector(null);
    }
  }, [connectingConnectorId, detailConnector]);

  const connectedIds = useMemo(
    () => new Set((connectedConnectors ?? []).map((connector) => connector.id)),
    [connectedConnectors],
  );
  // Not-yet-connected connectors, most popular first (mirrors the web ranking),
  // narrowed by the search query when present.
  const available = useMemo(() => {
    const query = searchQuery.trim().toLowerCase();
    const notConnected = (availableConnectors ?? SUPERAGENT_CONNECTOR_CATALOG).filter(
      (connector) => !connectedIds.has(connector.id),
    );
    const matched = query
      ? notConnected.filter((connector) =>
          [connector.id, connector.name, connector.subtitle, connector.description, connector.category]
            .filter(Boolean)
            .join(' ')
            .toLowerCase()
            .includes(query),
        )
      : notConnected;
    return sortConnectorsByPopularity(matched);
  }, [availableConnectors, connectedIds, searchQuery]);

  const connect = async (connector: SuperagentConnector, accessMode: SuperagentConnectorAccessMode | null) => {
    const result = await onConnect?.({
      accessMode: accessMode ?? undefined,
      agentId: agent.id,
      connectorId: connector.id,
      scopes: getConnectorScopesForMode(connector, accessMode ?? 'full_access'),
    });
    if (result) {
      void bi.trackEditor('Plugin Connect', { connector_type: connector.id, access_mode: accessMode ?? 'full_access' });
    }
    // Stay in the detail view so the spinner/Cancel remain visible; the effect
    // above pops back once the connection flow resolves.
  };

  if (isLoading) {
    return (
      <View style={editorShellStyles.loadingPanel}>
        <ActivityIndicator color={themedColor('#FF5A1F')} />
        <Text style={editorShellStyles.loadingText}>Loading connectors...</Text>
      </View>
    );
  }

  if (detailConnector) {
    return (
      <View style={editorShellStyles.settingsStack}>
        <ConnectorDetailView
          canConnect={!!onConnect}
          connector={detailConnector}
          isConnecting={connectingConnectorId === detailConnector.id}
          onCancel={() => onCancel?.({ agentId: agent.id, connectorId: detailConnector.id })}
          onConnect={connect}
        />
      </View>
    );
  }

  const connected = connectedConnectors ?? [];

  return (
    <View style={editorShellStyles.settingsStack}>
      <View style={cStyles.section}>
        <View style={cStyles.sectionHeader}>
          <Text style={cStyles.sectionTitle}>Apps connected</Text>
          {connected.length > 0 ? <Text style={cStyles.greenCount}>{connected.length}</Text> : null}
        </View>
        {connected.length > 0 ? (
          connected.map((connector) => (
            <ConnectedConnectorCard
              agentId={agent.id}
              connector={connector}
              isConnecting={connectingConnectorId === connector.id}
              key={connector.id}
              onCancel={onCancel}
              onConnect={onConnect}
              onDisconnect={onDisconnect}
              onRemove={onRemove}
            />
          ))
        ) : (
          <Text style={cStyles.emptyText}>No apps connected yet.</Text>
        )}
      </View>

      <View style={cStyles.section}>
        <View style={cStyles.sectionHeader}>
          <Text style={cStyles.sectionTitle}>All connectors</Text>
        </View>
        <View style={editorShellStyles.connectorSearchWrap}>
          <Search color={themedColor('#A1A1AA')} size={16} strokeWidth={2.4} />
          <TextInput
            autoCapitalize="none"
            autoCorrect={false}
            clearButtonMode="while-editing"
            onChangeText={setSearchQuery}
            placeholder="Search connectors"
            placeholderTextColor={themedColor('#8E8E93')}
            returnKeyType="search"
            style={editorShellStyles.connectorSearchInput}
            value={searchQuery}
          />
        </View>
        {available.length > 0 ? (
          available.map((connector) => (
            <ConnectorCard
              agentId={agent.id}
              connector={connector}
              isConnecting={connectingConnectorId === connector.id}
              key={connector.id}
              onCancel={onCancel}
              onSelect={() => setDetailConnector(connector)}
            />
          ))
        ) : (
          <Text style={cStyles.emptyText}>No matching connectors.</Text>
        )}
      </View>
    </View>
  );
}
