import React, { useCallback, useImperativeHandle, useMemo, useState, type Ref } from 'react';
import { KeyboardAvoidingView, Platform } from 'react-native';
import { SafeAreaView, type Edge } from 'react-native-safe-area-context';

import { AgentFeatureMenu } from '../settings/AgentFeatureMenu';
import { ConversationChat } from './ConversationChat';
import { ConversationFeatureNavigationProvider } from '../../featureNavigationContext';
import { ConversationHeader } from './conversationParts';
import { conversationStyles } from './conversationStyles';
import { EditorDrawer } from '../editor/EditorDrawer';
import { featureRefreshKeys } from '../settings/featureMenu';
import { useAgentBi } from '../../analytics/mixpanelContext';
import { getSelectableModelOptions, resolveModelOption } from '../settings/modelOptions';
import { ModelPickerModal, useModelPicker } from '../settings/modelPicker';
import { RenameAgentModal } from '../settings/RenameAgentModal';
import { takePendingFirstMessage } from '../../runtime/pendingFirstMessage';
import { useFeatureFlags, useSuperagentModelAccess } from '../../user/userContext';
import {
  useSuperagentAgents,
  useSuperagentAutomations,
  useSuperagentChannels,
  useSuperagentCollaborators,
  useSuperagentConversationRuntime,
  useSuperagentFiles,
  useSuperagentModelActions,
  useSuperagentSecrets,
  useSuperagentShellOptions,
  useSuperagentWorkflows,
} from '../../runtime/runtimeContext';
import type { SuperagentAgent, SuperagentEditorTab } from '../../types';
import { useSuperagentConversation } from './useSuperagentConversation';

// When the host hides the in-package header (`hideHeader`) it owns the conversation
// chrome itself: on iOS that's a draw-behind translucent glass nav bar, and the host
// folds the full top inset (status bar + nav bar) into `contentTopInset`. Dropping the
// top safe-area edge here lets the scroll content flow up under that glass bar instead
// of being capped by an opaque status-bar strip that makes the bar read as flat.
const HIDDEN_HEADER_SAFE_AREA_EDGES: Edge[] = ['left', 'right', 'bottom'];

/**
 * Imperative actions the host can trigger when the in-package header is hidden
 * (`hideHeader`). Surfaced to the host through the SuperagentHomeScreen ref.
 */
export type ConversationControls = {
  openMenu: () => void;
  openShare: () => void;
  openRename: () => void;
};

export function ConversationScreen({
  agent,
  controlsRef,
  onBack,
}: {
  agent: SuperagentAgent;
  controlsRef?: Ref<ConversationControls>;
  onBack: () => void;
}) {
  // The prompt typed on the home composer, for a just-created agent: claimed once
  // per mount so it is auto-sent exactly once and can never come back afterwards.
  const [firstMessage] = useState(() => takePendingFirstMessage(agent.id));
  // Runtime state/handlers come from context, not props — this screen owns only
  // its local UI state (open menu/modals, model picker) and forwards genuine
  // identity/UI props (agent, isVisible, onClose) to its children.
  const { apiClient, realtimeClient, currentUserId, latestMessages, messagesByAgentId, onAgentMessageDone } =
    useSuperagentConversationRuntime();
  const { hideConversationHeader, onViewPlans } = useSuperagentShellOptions();
  const { onUpdateAgentModel } = useSuperagentModelActions();
  const { onRenameAgent } = useSuperagentAgents();
  const { onRefreshAutomations } = useSuperagentAutomations();
  const { onRefreshWorkflows } = useSuperagentWorkflows();
  const { onRefreshFiles } = useSuperagentFiles();
  const { onRefreshChannels } = useSuperagentChannels();
  const { onRefreshAgentSettings } = useSuperagentSecrets();
  const { onRefreshCollaborators } = useSuperagentCollaborators();
  const bi = useAgentBi();
  const hideHeader = hideConversationHeader ?? false;
  const fallbackMessages = messagesByAgentId[agent.id] ?? latestMessages;
  // The header "more" menu lists each secondary feature; tapping one opens that
  // feature's own modal. `activeFeature` is the editor tab the modal shows (null
  // when closed); the menu's own visibility is `isMenuOpen`.
  const [isMenuOpen, setIsMenuOpen] = useState(false);
  const [activeFeature, setActiveFeature] = useState<SuperagentEditorTab | null>(null);
  const [isRenameModalOpen, setIsRenameModalOpen] = useState(false);
  const [isRenaming, setIsRenaming] = useState(false);
  const [renameError, setRenameError] = useState<string | null>(null);
  // Open a feature modal and refresh its data on open (the per-feature refresh
  // the tabbed drawer used to fire on tab switch).
  const openFeature = useCallback((tab: SuperagentEditorTab) => {
    setIsMenuOpen(false);
    void bi.trackEditor('Feature Opened', { feature: tab });
    // Opening the sharing drawer is the native "invite" entry point; is_owner isn't
    // reliably known here (no role on the agent), so it's omitted.
    if (tab === 'sharing') void bi.trackEditor('Collaboration Invite Click');
    for (const key of featureRefreshKeys(tab)) {
      // The Tasks tab shows workflows OR automations depending on the agent;
      // refresh the matching domain so a workflow just created in this chat is
      // reflected on open (native has no realtime workflow invalidation).
      if (key === 'automations') {
        if (agent.workflowsEnabled) onRefreshWorkflows?.(agent.id);
        else onRefreshAutomations?.(agent.id);
      }
      else if (key === 'files') onRefreshFiles?.(agent.id);
      else if (key === 'channels') onRefreshChannels?.(agent.id);
      else if (key === 'agentSettings') onRefreshAgentSettings?.(agent.id);
      else if (key === 'collaborators') onRefreshCollaborators?.(agent.id);
    }
    setActiveFeature(tab);
  }, [agent.id, agent.workflowsEnabled, bi, onRefreshAgentSettings, onRefreshAutomations, onRefreshWorkflows, onRefreshChannels, onRefreshCollaborators, onRefreshFiles]);
  // The composer's model pill opens a dedicated chat-model picker sheet (not the
  // whole General modal), reusing the shared picker hook.
  const { getFlagVariant, hasFlag } = useFeatureFlags();
  const { canSelectBestModel } = useSuperagentModelAccess();
  const modelOptions = useMemo(
    () => getSelectableModelOptions(hasFlag, getFlagVariant),
    [hasFlag, getFlagVariant],
  );
  const chatSelected = useMemo(() => resolveModelOption(agent.model), [agent.model]);
  const chatModelPicker = useModelPicker({
    agentId: agent.id,
    selected: chatSelected,
    options: modelOptions,
    onSelect: onUpdateAgentModel,
    canSelectBestModel,
    onViewPlans,
  });
  // Expose the header actions imperatively so a host-supplied (e.g. native) nav bar can
  // drive them when `hideHeader` is set. share/rename only act when the host wired the
  // corresponding handler, mirroring the in-package header's button-visibility gating.
  useImperativeHandle(controlsRef, () => ({
    openMenu: () => setIsMenuOpen(true),
    openShare: () => openFeature('sharing'),
    openRename: () => setIsRenameModalOpen(true),
  }), [openFeature]);
  const refreshAutomations = useCallback(() => {
    return onRefreshAutomations?.(agent.id);
  }, [agent.id, onRefreshAutomations]);
  const conversation = useSuperagentConversation({
    agentId: agent.id,
    apiClient,
    currentUserId,
    fallbackMessages,
    fallbackSending: false,
    onAgentMessageDone,
    onConversationSettled: refreshAutomations,
    realtimeClient,
    // A seeded prompt becomes the first turn, so skip the welcome intro before it.
    skipIntro: firstMessage != null,
  });
  const saveAgentName = async (name: string) => {
    if (!onRenameAgent) {
      return;
    }

    setIsRenaming(true);
    setRenameError(null);
    try {
      await onRenameAgent({ agentId: agent.id, name });
      setIsRenameModalOpen(false);
    } catch (error) {
      setRenameError(error instanceof Error ? error.message : 'Failed to rename Superagent');
    } finally {
      setIsRenaming(false);
    }
  };

  return (
    <SafeAreaView
      edges={hideHeader ? HIDDEN_HEADER_SAFE_AREA_EDGES : undefined}
      style={conversationStyles.safeArea}
    >
      <KeyboardAvoidingView
        behavior={Platform.OS === 'ios' ? 'padding' : undefined}
        style={conversationStyles.keyboard}
      >
        {hideHeader ? null : (
          <ConversationHeader
            activeTab="chat"
            agent={agent}
            onBack={onBack}
            onOpenMenu={() => setIsMenuOpen(true)}
            onOpenShare={() => openFeature('sharing')}
            onRenameRequest={() => setIsRenameModalOpen(true)}
          />
        )}
        <ConversationFeatureNavigationProvider onOpenFeature={openFeature}>
          <ConversationChat
            agent={agent}
            apiClient={apiClient}
            initialMessage={firstMessage?.content}
            connectorIds={firstMessage?.connectorIds}
            conversation={conversation}
            onOpenModelSettings={chatModelPicker.open}
          />
        </ConversationFeatureNavigationProvider>
        <AgentFeatureMenu
          onClose={() => setIsMenuOpen(false)}
          onSelectFeature={openFeature}
          visible={isMenuOpen}
        />
        <EditorDrawer
          activeTab={activeFeature ?? 'connectors'}
          agent={agent}
          isVisible={activeFeature !== null}
          onClose={() => setActiveFeature(null)}
        />

        <RenameAgentModal
          error={renameError}
          initialName={agent.name || 'Superagent'}
          isSaving={isRenaming}
          isVisible={isRenameModalOpen}
          onClose={() => {
            if (!isRenaming) {
              setIsRenameModalOpen(false);
              setRenameError(null);
            }
          }}
          onSave={saveAgentName}
        />
        <ModelPickerModal
          isVisible={chatModelPicker.isOpen}
          options={modelOptions}
          selectedModelId={chatSelected.id}
          canSelectBestModel={canSelectBestModel}
          onClose={chatModelPicker.close}
          onSelect={chatModelPicker.selectModel}
          onViewPlans={onViewPlans}
        />
      </KeyboardAvoidingView>
    </SafeAreaView>
  );
}
