import React, { createContext, useContext, type ReactNode } from 'react';

import type { useSuperagentRuntime } from './useSuperagentRuntime';
import type {
  SuperagentAgent,
  SuperagentCreateAgentInput,
  SuperagentMediaPicker,
  SuperagentMessage,
  SuperagentRoute,
} from '../types';

/**
 * Runtime state + handlers shared across the Superagent screen tree via React
 * context, so components read what they need through domain hooks
 * (`useSuperagentChannels`, `useSuperagentConnectors`, …) instead of receiving
 * dozens of drilled props. Mirrors the web agent-editor's store-hook consumption
 * model; we use a context-backed value rather than a module singleton so the two
 * mounted screens (home tab + pushed conversation) each keep their own isolated
 * runtime. Genuine identity/UI props (`agent`, `isVisible`, refs) stay props —
 * only shared runtime state flows through here, matching the web boundary.
 */

type RuntimeReturn = ReturnType<typeof useSuperagentRuntime>;

/**
 * The full context value: the runtime hook's return, minus the navigation/route
 * fields the shell overrides with host-aware versions, plus the shell-owned
 * extras (host navigation, media pickers, plans CTA, debug flag, insets).
 */
export type SuperagentRuntimeContextValue = Omit<
  RuntimeReturn,
  | 'onOpenAgent'
  | 'onRouteChange'
  | 'initialRoute'
  | 'currentRoute'
  | 'latestMessages'
  | 'messagesByAgentId'
  | 'onCreateAgent'
  | 'onRenameAgent'
  | 'onCloneAgent'
  | 'onDeleteAgent'
  | 'onShareAgentLink'
> & {
  // Overridden with real element types — the runtime returns empty `[]` / `{}`
  // literals, which infer as `never[]` / `{}` and can't be indexed/mapped.
  latestMessages: SuperagentMessage[];
  messagesByAgentId: Record<string, SuperagentMessage[]>;
  // The runtime impl ignores its arg; widen to the seeded-create contract callers use.
  onCreateAgent: (input?: SuperagentCreateAgentInput) => Promise<SuperagentAgent | void> | SuperagentAgent | void;
  // Optional so overflow-menu / settings actions can gate their affordance on
  // handler presence (the runtime always provides them, but consumers must not assume it).
  onRenameAgent?: RuntimeReturn['onRenameAgent'];
  onCloneAgent?: RuntimeReturn['onCloneAgent'];
  onDeleteAgent?: RuntimeReturn['onDeleteAgent'];
  onShareAgentLink?: RuntimeReturn['onShareAgentLink'];
  navigationMode?: 'internal' | 'external';
  initialRoute?: SuperagentRoute;
  onOpenAgent?: (agentId: string) => void;
  onAgentBack?: () => void;
  onRouteChange?: (route: SuperagentRoute) => void;
  onViewPlans?: () => void;
  showDebugPayloads?: boolean;
  isActive?: boolean;
  contentTopInset?: number;
  hideConversationHeader?: boolean;
  onPickFiles?: SuperagentMediaPicker;
  onPickPhotos?: SuperagentMediaPicker;
  onTakePhoto?: SuperagentMediaPicker;
};

const SuperagentRuntimeContext = createContext<SuperagentRuntimeContextValue | null>(null);

export function SuperagentRuntimeProvider({
  value,
  children,
}: {
  value: SuperagentRuntimeContextValue;
  children: ReactNode;
}) {
  return <SuperagentRuntimeContext.Provider value={value}>{children}</SuperagentRuntimeContext.Provider>;
}

/**
 * Base accessor for the whole runtime value. Throws when used outside the
 * provider (i.e. outside a `SuperagentHomeScreen`) so a missing provider surfaces
 * immediately rather than as confusing `undefined` reads. Prefer the domain hooks
 * below; reach for this only when a component genuinely spans several domains.
 */
export function useSuperagentRuntimeContext(): SuperagentRuntimeContextValue {
  const value = useContext(SuperagentRuntimeContext);
  if (!value) {
    throw new Error('Superagent runtime hooks must be used within a <SuperagentHomeScreen>.');
  }
  return value;
}

/** Agents list + agent-lifecycle actions (home list, overflow menu). */
export function useSuperagentAgents() {
  const ctx = useSuperagentRuntimeContext();
  return {
    agents: ctx.agents,
    activeAgentId: ctx.activeAgentId,
    activeAgent: ctx.activeAgent,
    isLoading: ctx.isLoading,
    isRefreshingAgents: ctx.isRefreshingAgents,
    loadError: ctx.loadError,
    onRefreshAgents: ctx.onRefreshAgents,
    onCreateAgent: ctx.onCreateAgent,
    onRenameAgent: ctx.onRenameAgent,
    onCloneAgent: ctx.onCloneAgent,
    onDeleteAgent: ctx.onDeleteAgent,
    onShareAgentLink: ctx.onShareAgentLink,
  };
}

/** App-shell navigation wiring (routing between home and agent screens). */
export function useSuperagentNavigation() {
  const ctx = useSuperagentRuntimeContext();
  return {
    navigationMode: ctx.navigationMode,
    initialRoute: ctx.initialRoute,
    onOpenAgent: ctx.onOpenAgent,
    onAgentBack: ctx.onAgentBack,
    onRouteChange: ctx.onRouteChange,
  };
}

/** Conversation-runtime dependencies (clients, current user, message seeds). */
export function useSuperagentConversationRuntime() {
  const ctx = useSuperagentRuntimeContext();
  return {
    apiClient: ctx.apiClient,
    realtimeClient: ctx.realtimeClient,
    currentUserId: ctx.currentUserId,
    currentUserAvatarUrl: ctx.currentUserAvatarUrl,
    currentUserName: ctx.currentUserName,
    latestMessages: ctx.latestMessages,
    messagesByAgentId: ctx.messagesByAgentId,
    onAgentMessageDone: ctx.onAgentMessageDone,
    copyToClipboard: ctx.copyToClipboard,
  };
}

/** OAuth connectors: catalog, connection state, and connect/disconnect actions. */
export function useSuperagentConnectors() {
  const ctx = useSuperagentRuntimeContext();
  return {
    availableConnectors: ctx.availableConnectors,
    connectedConnectors: ctx.connectedConnectors,
    connectingConnectorId: ctx.connectingConnectorId,
    isLoadingConnectors: ctx.isLoadingConnectors,
    onConnectConnector: ctx.onConnectConnector,
    onDisconnectConnector: ctx.onDisconnectConnector,
    onRemoveConnector: ctx.onRemoveConnector,
    onCancelConnectorConnection: ctx.onCancelConnectorConnection,
  };
}

/** Messaging channels (WhatsApp, Telegram, LINE, iMessage, Slack). */
export function useSuperagentChannels() {
  const ctx = useSuperagentRuntimeContext();
  return {
    channelStatus: ctx.channelStatus,
    connectingChannelId: ctx.connectingChannelId,
    disconnectingChannelId: ctx.disconnectingChannelId,
    isLoadingChannels: ctx.isLoadingChannels,
    onConnectSlack: ctx.onConnectSlack,
    onDisconnectSlack: ctx.onDisconnectSlack,
    onDisconnectTelegram: ctx.onDisconnectTelegram,
    onDisconnectIMessage: ctx.onDisconnectIMessage,
    onDisconnectWhatsApp: ctx.onDisconnectWhatsApp,
    onGenerateLineCode: ctx.onGenerateLineCode,
    onGenerateIMessageCode: ctx.onGenerateIMessageCode,
    onOpenIMessage: ctx.onOpenIMessage,
    onOpenLine: ctx.onOpenLine,
    onOpenTelegram: ctx.onOpenTelegram,
    onOpenWhatsApp: ctx.onOpenWhatsApp,
    onSetupTelegram: ctx.onSetupTelegram,
    onShareIMessageCode: ctx.onShareIMessageCode,
    onShareLineCode: ctx.onShareLineCode,
    onRefreshChannels: ctx.onRefreshChannels,
  };
}

/** Scheduled/triggered automations ("Tasks") + their credit usage. */
export function useSuperagentAutomations() {
  const ctx = useSuperagentRuntimeContext();
  return {
    automations: ctx.automations,
    automationCredits: ctx.automationCredits,
    automationLoadError: ctx.automationLoadError,
    isLoadingAutomations: ctx.isLoadingAutomations,
    onToggleAutomation: ctx.onToggleAutomation,
    onArchiveAutomation: ctx.onArchiveAutomation,
    onRestoreAutomation: ctx.onRestoreAutomation,
    onDeleteAutomation: ctx.onDeleteAutomation,
    onRunAutomationNow: ctx.onRunAutomationNow,
    onEditAutomation: ctx.onEditAutomation,
    onRefreshAutomations: ctx.onRefreshAutomations,
  };
}

/**
 * Workflows ("Tasks") for a workflows-enabled agent + their lifecycle actions.
 * An agent runs EITHER workflows OR automations — the Tasks panel picks the
 * surface via `agent.workflowsEnabled` and reads the matching domain hook.
 */
export function useSuperagentWorkflows() {
  const ctx = useSuperagentRuntimeContext();
  return {
    workflows: ctx.workflows,
    workflowLoadError: ctx.workflowLoadError,
    isLoadingWorkflows: ctx.isLoadingWorkflows,
    onToggleWorkflow: ctx.onToggleWorkflow,
    onArchiveWorkflow: ctx.onArchiveWorkflow,
    onRestoreWorkflow: ctx.onRestoreWorkflow,
    onRunWorkflowNow: ctx.onRunWorkflowNow,
    onRefreshWorkflows: ctx.onRefreshWorkflows,
  };
}

/** Sandbox files browser. */
export function useSuperagentFiles() {
  const ctx = useSuperagentRuntimeContext();
  return {
    filePaths: ctx.filePaths,
    fileLoadError: ctx.fileLoadError,
    fileLoadFailed: ctx.fileLoadFailed,
    isLoadingFiles: ctx.isLoadingFiles,
    onOpenSandboxFile: ctx.onOpenSandboxFile,
    onSaveSandboxFile: ctx.onSaveSandboxFile,
    onUploadSandboxFiles: ctx.onUploadSandboxFiles,
    onRefreshFiles: ctx.onRefreshFiles,
  };
}

/** Agent secrets (env vars) + the agent-settings load flag. */
export function useSuperagentSecrets() {
  const ctx = useSuperagentRuntimeContext();
  return {
    secrets: ctx.secrets,
    isLoadingAgentSettings: ctx.isLoadingAgentSettings,
    onSaveSecret: ctx.onSaveSecret,
    onDeleteSecret: ctx.onDeleteSecret,
    onRefreshAgentSettings: ctx.onRefreshAgentSettings,
  };
}

/** Collaborators / sharing (invite, refresh, open workspace members). */
export function useSuperagentCollaborators() {
  const ctx = useSuperagentRuntimeContext();
  return {
    collaborators: ctx.collaborators,
    isLoadingCollaborators: ctx.isLoadingCollaborators,
    onShareAgent: ctx.onShareAgent,
    onRefreshCollaborators: ctx.onRefreshCollaborators,
    onOpenWorkspaceMembers: ctx.onOpenWorkspaceMembers,
  };
}

/** Model + tool-permission mutations (chat model, automation model, guards). */
export function useSuperagentModelActions() {
  const ctx = useSuperagentRuntimeContext();
  return {
    onUpdateAgentModel: ctx.onUpdateAgentModel,
    onUpdateAgentAutomationModel: ctx.onUpdateAgentAutomationModel,
    onUpdateToolPermissions: ctx.onUpdateToolPermissions,
  };
}

/** Native media capture/pick + live voice for the composer. */
export function useSuperagentMedia() {
  const ctx = useSuperagentRuntimeContext();
  return {
    onPickFiles: ctx.onPickFiles,
    onPickPhotos: ctx.onPickPhotos,
    onTakePhoto: ctx.onTakePhoto,
    onStartLiveVoice: ctx.onStartLiveVoice,
    speechToText: ctx.speechToText,
  };
}

/** Cross-cutting shell options (plans CTA, debug payloads, content inset). */
export function useSuperagentShellOptions() {
  const ctx = useSuperagentRuntimeContext();
  return {
    onViewPlans: ctx.onViewPlans,
    showDebugPayloads: ctx.showDebugPayloads,
    isActive: ctx.isActive,
    contentTopInset: ctx.contentTopInset,
    hideConversationHeader: ctx.hideConversationHeader,
  };
}
