import React, { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, type ForwardedRef } from 'react';
import { themedColor } from '../../theme';
import {
  ActivityIndicator,
  FlatList,
  RefreshControl,
  SafeAreaView,
  Text,
  View,
} from 'react-native';

import { Pencil, Trash2 } from 'lucide-react-native';

import { SuperagentScreen } from './SuperagentScreen';
import { SuperagentTopBar } from './SuperagentTopBar';
import { NoAgentsHero } from './NoAgentsHero';
import { PlaceholderPage } from './screenParts';
import { ChatConversationRow, CreateAgentRow } from './chatListParts';
import { pickCreateAgentSubtitle } from './createAgentSubtitle';
import { AgentActionsSheet, ConfirmDialog, type AgentAction } from '../settings/agentActionsParts';
import { RenameAgentModal } from '../settings/RenameAgentModal';
import { ConversationScreen, type ConversationControls } from '../conversation/ConversationScreen';
import { setPendingFirstMessage } from '../../runtime/pendingFirstMessage';
import { routeIdentityKey } from '../../runtime/routeKey';
import { useAgentBi } from '../../analytics/mixpanelContext';
import {
  useSuperagentAgents,
  useSuperagentConversationRuntime,
  useSuperagentNavigation,
  useSuperagentShellOptions,
} from '../../runtime/runtimeContext';
import { styles } from '../../styles';
import type { SuperagentAgent, SuperagentCreateAgentInput, SuperagentHomeScreenHandle, SuperagentRoute } from '../../types';

const DEFAULT_ROUTE: SuperagentRoute = { name: 'home' };

/**
 * The Superagent home/conversation view. Pure UI over the full runtime prop
 * surface — the exported `SuperagentHomeScreen` shell mounts the theme + user
 * providers and feeds this from `useSuperagentRuntime`. Not part of the public
 * package API (used directly only by the in-repo web demo harness).
 */
export function SuperagentHomeScreenView({
  handleRef,
}: {
  handleRef?: ForwardedRef<SuperagentHomeScreenHandle>;
}) {
  const {
    agents,
    isLoading,
    isRefreshingAgents,
    onRefreshAgents,
    onCreateAgent,
    onRenameAgent,
    onDeleteAgent,
  } = useSuperagentAgents();
  const {
    navigationMode = 'internal',
    initialRoute = DEFAULT_ROUTE,
    onOpenAgent,
    onAgentBack,
    onRouteChange,
  } = useSuperagentNavigation();
  const { latestMessages, messagesByAgentId } = useSuperagentConversationRuntime();
  const { isActive } = useSuperagentShellOptions();

  // The mobile home screen shows a single flat agent list under a fixed title
  // (folders aren't part of the mobile runtime surface).
  const homeTitle = 'Superagents';

  const [route, setRoute] = useState<SuperagentRoute>(initialRoute);
  const [isCreating, setIsCreating] = useState(false);
  // Bridges the host-facing ref to the active conversation's imperative controls.
  // Null while no conversation is mounted, so each handle method becomes a safe no-op.
  const conversationControlsRef = useRef<ConversationControls | null>(null);
  useImperativeHandle(handleRef, () => ({
    openConversationMenu: () => conversationControlsRef.current?.openMenu(),
    openConversationShare: () => conversationControlsRef.current?.openShare(),
    openConversationRename: () => conversationControlsRef.current?.openRename(),
  }), []);

  // Track app_id (the active agent's id) as a super-property so every event
  // carries it; null on the home list. The agent-editor page-view fires in the
  // same effect, after register(), so it never lands on a stale app_id. Keyed on
  // the agent id so it fires once per agent open (home → agent, agent → agent),
  // not on re-renders of the same route.
  const bi = useAgentBi();
  const lastViewedAgentId = useRef<string | null>(null);
  useEffect(() => {
    const agentId = route.name === 'agent' ? route.agentId : null;
    bi.register({ app_id: agentId });
    if (agentId && agentId !== lastViewedAgentId.current) {
      void bi.trackEditor('Page View');
    }
    lastViewedAgentId.current = agentId;
  }, [bi, route]);

  // Home page-view, fired each time the home list becomes visible. The tab stays
  // mounted, so mount alone doesn't mean the user saw it — gate on isActive. Also
  // gate on the list having loaded so agent_count isn't logged as 0 for returning
  // users while agents (default []) is still loading.
  const wasViewingHome = useRef(false);
  const isViewingHome = isActive === true && route.name === 'home';
  useEffect(() => {
    if (isViewingHome && !isLoading && !wasViewingHome.current) {
      wasViewingHome.current = true;
      void bi.track('Agent Home: Page View', { navigation_mode: navigationMode, agent_count: agents.length });
    } else if (!isViewingHome) {
      wasViewingHome.current = false;
    }
  }, [isViewingHome, isLoading, agents.length, bi, navigationMode]);

  // Follow externally-driven route changes (e.g. the runtime moves home after the
  // active agent is deleted, or a deep link changes the agent). Keyed by value so
  // it doesn't clobber internal navigation on unrelated re-renders.
  const externalRouteKey = routeIdentityKey(initialRoute);
  useEffect(() => {
    setRoute(initialRoute);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [externalRouteKey]);
  const latestAgent = agents[0] ?? null;

  // Resolve the conversation feed for an agent: the explicit latestMessages feed
  // covers the most-recent agent, with the per-agent map as the general source —
  // so each chat row shows a preview regardless of how the host wires data.
  const messagesForAgent = useCallback((agent: SuperagentAgent) => {
    const mapped = messagesByAgentId[agent.id];
    if (mapped?.length) return mapped;
    if (agent.id === latestAgent?.id && latestMessages.length) return latestMessages;
    return mapped ?? [];
  }, [latestAgent?.id, latestMessages, messagesByAgentId]);

  const navigate = useCallback((nextRoute: SuperagentRoute) => {
    setRoute(nextRoute);
    onRouteChange?.(nextRoute);
  }, [onRouteChange]);

  const openAgent = useCallback((agentId: string) => {
    if (navigationMode === 'internal') {
      navigate({ name: 'agent', agentId });
    }
    onOpenAgent?.(agentId);
  }, [navigate, navigationMode, onOpenAgent]);

  const createAgent = useCallback(async (input?: SuperagentCreateAgentInput) => {
    void bi.trackHome('Create Agent Click', {
      is_new_user: agents.length === 0,
      idea_key: input?.ideaKey,
      idea_category: input?.ideaCategory,
    });
    if (!onCreateAgent) {
      navigate({ name: 'create-agent' });
      return;
    }

    setIsCreating(true);
    try {
      const createdAgent = await onCreateAgent(input);
      if (createdAgent?.id) {
        void bi.trackHome('Agent Created', { agent_id: createdAgent.id });
        const content = input?.initialMessage?.trim();
        // Hand the composer prompt + connectors to the new agent's chat, which
        // auto-sends it. Kept out of the route so it can't be replayed (see
        // pendingFirstMessage).
        if (content) setPendingFirstMessage({ agentId: createdAgent.id, content, connectorIds: input?.connectorIds });
        openAgent(createdAgent.id);
      } else {
        navigate({ name: 'create-agent' });
      }
    } finally {
      setIsCreating(false);
    }
  }, [agents.length, bi, navigate, onCreateAgent, openAgent]);

  // Per-agent overflow menu (mirrors the web "all agents" card actions).
  const [menuAgent, setMenuAgent] = useState<SuperagentAgent | null>(null);
  const [renameTarget, setRenameTarget] = useState<SuperagentAgent | null>(null);
  const [isRenaming, setIsRenaming] = useState(false);
  const [renameError, setRenameError] = useState<string | null>(null);
  const [deleteTarget, setDeleteTarget] = useState<SuperagentAgent | null>(null);
  const [isDeleting, setIsDeleting] = useState(false);

  const hasAnyAgentAction = Boolean(onRenameAgent || onDeleteAgent);

  const menuActions = useMemo<AgentAction[]>(() => {
    if (!menuAgent) return [];
    const agent = menuAgent;
    const close = () => setMenuAgent(null);
    const iconColor = themedColor('#F7F7F7');
    const actions: AgentAction[] = [];

    if (onRenameAgent) {
      actions.push({
        key: 'rename',
        label: 'Rename',
        icon: <Pencil color={iconColor} size={20} strokeWidth={2} />,
        onPress: () => { close(); setRenameError(null); setRenameTarget(agent); },
      });
    }
    if (onDeleteAgent) {
      actions.push({
        key: 'delete',
        label: 'Delete',
        destructive: true,
        icon: <Trash2 color={themedColor('#FF6B6B')} size={20} strokeWidth={2} />,
        onPress: () => { void bi.trackEditor('Agent Delete Click'); close(); setDeleteTarget(agent); },
      });
    }
    return actions;
  }, [bi, menuAgent, onDeleteAgent, onRenameAgent]);

  const handleRename = useCallback(async (name: string) => {
    if (!renameTarget || !onRenameAgent) return;
    setIsRenaming(true);
    setRenameError(null);
    try {
      await onRenameAgent({ agentId: renameTarget.id, name });
      setRenameTarget(null);
    } catch (error) {
      setRenameError(error instanceof Error ? error.message : 'Failed to rename Superagent');
    } finally {
      setIsRenaming(false);
    }
  }, [onRenameAgent, renameTarget]);

  const handleDelete = useCallback(async () => {
    if (!deleteTarget || !onDeleteAgent) return;
    setIsDeleting(true);
    try {
      await onDeleteAgent({ agentId: deleteTarget.id });
      setDeleteTarget(null);
    } finally {
      setIsDeleting(false);
    }
  }, [deleteTarget, onDeleteAgent]);

  // Picked once per mount so the copy varies across app opens but stays
  // stable while the screen re-renders.
  const [createAgentSubtitle] = useState(() => pickCreateAgentSubtitle(new Date()));

  const renderConversationRow = useCallback((agent: SuperagentAgent) => (
    <ChatConversationRow
      key={agent.id}
      agent={agent}
      messages={messagesForAgent(agent)}
      onPress={() => {
        // agent_id passed explicitly — the app_id super-property is null on the home list.
        void bi.trackHome('Continue Agent Click', { agent_id: agent.id });
        openAgent(agent.id);
      }}
      onLongPress={hasAnyAgentAction ? () => setMenuAgent(agent) : undefined}
    />
  ), [bi, hasAnyAgentAction, messagesForAgent, openAgent]);

  if (route.name === 'agent') {
    const activeAgent = findAgentById(agents, route.agentId);

    return (
      <ConversationScreen
        key={route.agentId}
        agent={activeAgent ?? createUnknownAgent(route.agentId)}
        controlsRef={conversationControlsRef}
        onBack={() => {
          if (onAgentBack) {
            onAgentBack();
            return;
          }

          navigate({ name: 'home' });
        }}
      />
    );
  }

  if (route.name === 'create-agent') {
    return (
      <PlaceholderPage
        title="Create Superagent"
        body="Creation flow will live inside this package."
        onBack={() => navigate({ name: 'home' })}
      />
    );
  }

  const hasAgents = agents.length > 0;

  return (
    <SuperagentScreen style={!hasAgents ? styles.heroScreenBg : undefined}>
      {/* The shell is edge-to-edge; this screen owns its safe-area insets so the
          top bar / title / chips don't render under the notch. */}
      <SafeAreaView style={styles.homeSafeArea}>
      {/* Native DS top bar: centered logo (no hamburger / workspace button —
          those live in the sidebar, Phase 2). */}
      <SuperagentTopBar />

      {isLoading ? (
        <View style={styles.chatEmptyWrap}>
          <ActivityIndicator color={themedColor('#FF5A1F')} />
        </View>
      ) : !hasAgents ? (
        <NoAgentsHero isCreating={isCreating} onCreateAgent={createAgent} />
      ) : (
        <FlatList
          style={styles.chatListScroll}
          contentContainerStyle={styles.chatListContent}
          data={agents}
          keyExtractor={(agent) => agent.id}
          refreshControl={
            onRefreshAgents ? (
              <RefreshControl
                refreshing={!!isRefreshingAgents}
                onRefresh={() => { void onRefreshAgents(); }}
                tintColor={themedColor('#FF5A1F')}
                colors={[themedColor('#FF5A1F')]}
              />
            ) : undefined
          }
          renderItem={({ item }) => renderConversationRow(item)}
          // Title lives in the list header (not pinned above) so the pull-to-refresh
          // spinner surfaces at the very top of the screen, above the title.
          ListHeaderComponent={homeTitle ? <Text style={styles.screenTitle}>{homeTitle}</Text> : null}
          ListEmptyComponent={
            <Text style={styles.chatEmptyHint}>No agents in this folder yet.</Text>
          }
          ListFooterComponent={
            <CreateAgentRow isCreating={isCreating} subtitle={createAgentSubtitle} onPress={() => createAgent()} />
          }
        />
      )}
      </SafeAreaView>

      <AgentActionsSheet
        visible={menuAgent != null}
        title={menuAgent?.name || 'Untitled Agent'}
        actions={menuActions}
        onClose={() => setMenuAgent(null)}
      />
      <RenameAgentModal
        error={renameError}
        initialName={renameTarget?.name || 'Superagent'}
        isSaving={isRenaming}
        isVisible={renameTarget != null}
        onClose={() => { if (!isRenaming) { setRenameTarget(null); setRenameError(null); } }}
        onSave={handleRename}
      />
      <ConfirmDialog
        visible={deleteTarget != null}
        title="Delete agent?"
        message={`"${deleteTarget?.name || 'This agent'}" and its conversations will be permanently deleted. This can't be undone.`}
        confirmLabel="Delete"
        destructive
        isBusy={isDeleting}
        onCancel={() => { if (!isDeleting) setDeleteTarget(null); }}
        onConfirm={handleDelete}
      />
    </SuperagentScreen>
  );
}

function findAgentById(agents: SuperagentAgent[], agentId: string) {
  return agents.find((agent) => agent.id === agentId);
}

function createUnknownAgent(agentId: string): SuperagentAgent {
  return {
    id: agentId,
    name: 'Superagent',
  };
}
