import type { EventLogEntry } from "./app-events.ts";
import type { CompactionStatus, FallbackStatus } from "./app-tool-stream.ts";
import type {
  CronModelSuggestionsState,
  CronState,
  CronJobsScheduleKindFilter,
  CronJobsLastStatusFilter,
} from "./controllers/cron.ts";
import type { DevicePairingList } from "./controllers/devices.ts";
import type { ExecApprovalRequest } from "./controllers/exec-approval.ts";
import type { ExecApprovalsFile, ExecApprovalsSnapshot } from "./controllers/exec-approvals.ts";
import type { SkillMessage } from "./controllers/skills.ts";
import type { GatewayBrowserClient, GatewayHelloOk } from "./gateway.ts";
import type { Tab } from "./navigation.ts";
import type { UiSettings } from "./storage.ts";
import type { ThemeTransitionContext } from "./theme-transition.ts";
import type { ThemeMode } from "./theme.ts";
import type {
  AgentsListResult,
  AgentsFilesListResult,
  AgentIdentityResult,
  ChannelsStatusSnapshot,
  TeamsListResult,
  ConfigSnapshot,
  ConfigUiHints,
  HealthSnapshot,
  LogEntry,
  LogLevel,
  NostrProfile,
  PresenceEntry,
  SessionsUsageResult,
  CostUsageSummary,
  SessionUsageTimeSeries,
  SessionsListResult,
  SkillStatusReport,
  ToolsCatalogResult,
  StatusSummary,
} from "./types.ts";
import type { ChatAttachment, ChatQueueItem, CronFormState } from "./ui-types.ts";

export type BackgroundJobToast = {
  jobId: string;
  jobName: string;
  status: "running" | "complete" | "error";
  startedAt: number;
  completedAt: number | null;
  errorMsg?: string;
};
import type { NostrProfileFormState } from "./views/channels.nostr-profile-form.ts";
import type { SessionLogEntry } from "./views/usage.ts";

export type AppViewState = {
  settings: UiSettings;
  password: string;
  tab: Tab;
  onboarding: boolean;
  basePath: string;
  connected: boolean;
  theme: ThemeMode;
  themeResolved: "light" | "dark";
  hello: GatewayHelloOk | null;
  lastError: string | null;
  lastErrorCode: string | null;
  eventLog: EventLogEntry[];
  assistantName: string;
  assistantAvatar: string | null;
  assistantAgentId: string | null;
  sessionKey: string;
  chatLoading: boolean;
  chatSending: boolean;
  chatMessage: string;
  chatAttachments: ChatAttachment[];
  chatMessages: unknown[];
  chatToolMessages: unknown[];
  chatStream: string | null;
  chatStreamStartedAt: number | null;
  chatRunId: string | null;
  chatAuthMode: "oauth" | "api" | "fallback" | "unknown" | null;
  compactionStatus: CompactionStatus | null;
  fallbackStatus: FallbackStatus | null;
  chatAvatarUrl: string | null;
  backgroundJobToasts: BackgroundJobToast[];
  chatThinkingLevel: string | null;
  chatQueue: ChatQueueItem[];
  chatManualRefreshInFlight: boolean;
  nodesLoading: boolean;
  nodes: Array<Record<string, unknown>>;
  chatNewMessagesBelow: boolean;
  navDrawerOpen: boolean;
  sidebarOpen: boolean;
  sidebarContent: string | null;
  sidebarError: string | null;
  splitRatio: number;
  scrollToBottom: (opts?: { smooth?: boolean }) => void;
  devicesLoading: boolean;
  devicesError: string | null;
  devicesList: DevicePairingList | null;
  execApprovalsLoading: boolean;
  execApprovalsSaving: boolean;
  execApprovalsDirty: boolean;
  execApprovalsSnapshot: ExecApprovalsSnapshot | null;
  execApprovalsForm: ExecApprovalsFile | null;
  execApprovalsSelectedAgent: string | null;
  execApprovalsTarget: "gateway" | "node";
  execApprovalsTargetNodeId: string | null;
  execApprovalQueue: ExecApprovalRequest[];
  execApprovalBusy: boolean;
  execApprovalError: string | null;
  pendingGatewayUrl: string | null;
  configLoading: boolean;
  configRaw: string;
  configRawOriginal: string;
  configValid: boolean | null;
  configIssues: unknown[];
  configSaving: boolean;
  configApplying: boolean;
  updateRunning: boolean;
  updateInProgress: boolean;
  applySessionKey: string;
  configSnapshot: ConfigSnapshot | null;
  configSchema: unknown;
  configSchemaVersion: string | null;
  configSchemaLoading: boolean;
  configUiHints: ConfigUiHints;
  configForm: Record<string, unknown> | null;
  configFormOriginal: Record<string, unknown> | null;
  configFormMode: "form" | "raw";
  configSearchQuery: string;
  configActiveSection: string | null;
  configActiveSubsection: string | null;
  channelsLoading: boolean;
  channelsSnapshot: ChannelsStatusSnapshot | null;
  channelsError: string | null;
  channelsLastSuccess: number | null;
  whatsappLoginMessage: string | null;
  whatsappLoginQrDataUrl: string | null;
  whatsappLoginConnected: boolean | null;
  whatsappBusy: boolean;
  nostrProfileFormState: NostrProfileFormState | null;
  nostrProfileAccountId: string | null;
  configFormDirty: boolean;
  presenceLoading: boolean;
  presenceEntries: PresenceEntry[];
  presenceError: string | null;
  presenceStatus: string | null;
  agentsLoading: boolean;
  agentsList: AgentsListResult | null;
  agentsError: string | null;
  agentsSelectedId: string | null;
  agentsAvailableModels: Array<{
    id: string;
    name?: string;
    provider: string;
    contextWindow?: number;
  }>;
  toolsCatalogLoading: boolean;
  toolsCatalogError: string | null;
  toolsCatalogResult: ToolsCatalogResult | null;
  agentsPanel: "overview" | "files" | "tools" | "skills" | "channels" | "cron";
  agentToolsSubTab: "core" | "pipedream" | "zapier";
  agentFilesLoading: boolean;
  agentFilesError: string | null;
  agentFilesList: AgentsFilesListResult | null;
  agentFileContents: Record<string, string>;
  agentFileDrafts: Record<string, string>;
  agentFileActive: string | null;
  agentFileSaving: boolean;
  agentIdentityLoading: boolean;
  agentIdentityError: string | null;
  agentIdentityById: Record<string, AgentIdentityResult>;
  agentAvatarTheme: string;
  agentAvatarInstructions: string;
  agentAvatarBusy: boolean;
  agentAvatarStatus: string | null;
  agentAvatarError: string | null;
  agentAvatarPreviewUrl: string | null;
  agentSkillsLoading: boolean;
  agentSkillsError: string | null;
  agentSkillsReport: SkillStatusReport | null;
  agentSkillsAgentId: string | null;
  teamsLoading: boolean;
  teamsError: string | null;
  teamsResult: TeamsListResult | null;
  teamsSelectedId: string | null;
  teamsEditName: string;
  teamsEditDescription: string;
  teamsEditParentId: string | null;
  teamsEditAgentIds: string[];
  teamsDirty: boolean;
  teamsSaving: boolean;
  teamsDeleteInProgress: boolean;
  teamsDeleteError: string | null;
  teamsCollapsedIds: string[];
  sessionsLoading: boolean;
  sessionsResult: SessionsListResult | null;
  sessionsError: string | null;
  sessionsFilterActive: string;
  sessionsFilterLimit: string;
  sessionsIncludeGlobal: boolean;
  sessionsIncludeUnknown: boolean;
  sessionsAgentFilter: string;
  sessionsHideCron: boolean;
  // Background Sessions Panel
  bgSessionsPanelOpen: boolean;
  bgSessionsList: Array<{
    key: string;
    sessionId: string;
    label: string;
    updatedAt: number;
    running: boolean;
  }> | null;
  bgSessionsLoading: boolean;
  bgSessionsSelectedKey: string | null;
  bgSessionsHistory: Array<{
    role: string;
    text: string;
    timestamp?: number;
    toolName?: string;
  }> | null;
  bgSessionsHistoryLoading: boolean;
  bgSessionsInput: string;
  bgSessionsSending: boolean;

  // Team Chat Drawer
  teamChatOpen: boolean;
  teamChatProject: unknown;
  teamChatSessions: unknown[];
  teamChatActivity: unknown[];
  teamChatLoading: boolean;
  teamChatInput: string;
  teamChatTasksCollapsed: boolean;

  recentArchivedSessions: Array<{
    sessionId: string;
    sessionKey: string;
    displayName?: string;
    firstMessage?: string;
    updatedAt: number;
  }> | null;
  archivedSessionsLoading: boolean;
  archivedSessionsResult: import("./controllers/sessions.ts").ArchivedSessionsResult | null;
  archivedSessionsError: string | null;
  archivedSessionsSearch: string;
  liveSessionsPage: number;
  liveSessionsPageSize: number;
  archivedSessionsPage: number;
  archivedSessionsPageSize: number;
  // Session history modal
  sessionHistoryOpen: boolean;
  sessionHistoryKey: string;
  sessionHistoryAgentFilter: string;
  sessionHistorySearch: string;
  sessionHistoryRoleFilter: string;
  sessionHistoryLoading: boolean;
  sessionHistoryError: string | null;
  sessionHistoryResult: import("./views/sessions-history-modal.ts").SessionHistoryResult | null;
  usageLoading: boolean;
  usageResult: SessionsUsageResult | null;
  usageCostSummary: CostUsageSummary | null;
  usageError: string | null;
  usageStartDate: string;
  usageEndDate: string;
  usageSelectedSessions: string[];
  usageSelectedDays: string[];
  usageSelectedHours: number[];
  usageChartMode: "tokens" | "cost";
  usageDailyChartMode: "total" | "by-type";
  usageTimeSeriesMode: "cumulative" | "per-turn";
  usageTimeSeriesBreakdownMode: "total" | "by-type";
  usageTimeSeries: SessionUsageTimeSeries | null;
  usageTimeSeriesLoading: boolean;
  usageTimeSeriesCursorStart: number | null;
  usageTimeSeriesCursorEnd: number | null;
  usageSessionLogs: SessionLogEntry[] | null;
  usageSessionLogsLoading: boolean;
  usageSessionLogsExpanded: boolean;
  usageQuery: string;
  usageQueryDraft: string;
  usageQueryDebounceTimer: number | null;
  usageSessionSort: "tokens" | "cost" | "recent" | "messages" | "errors";
  usageSessionSortDir: "asc" | "desc";
  usageRecentSessions: string[];
  usageTimeZone: "local" | "utc";
  usageContextExpanded: boolean;
  usageHeaderPinned: boolean;
  usageSessionsTab: "all" | "recent";
  usageVisibleColumns: string[];
  usageLogFilterRoles: import("./views/usage.js").SessionLogRole[];
  usageLogFilterTools: string[];
  usageLogFilterHasTools: boolean;
  usageLogFilterQuery: string;
  cronLoading: boolean;
  cronJobsLoadingMore: boolean;
  cronJobs: CronJob[];
  cronJobsTotal: number;
  cronJobsHasMore: boolean;
  cronJobsNextOffset: number | null;
  cronJobsLimit: number;
  cronJobsQuery: string;
  cronJobsEnabledFilter: CronJobsEnabledFilter;
  cronJobsScheduleKindFilter: CronJobsScheduleKindFilter;
  cronJobsLastStatusFilter: CronJobsLastStatusFilter;
  cronJobsSortBy: CronJobsSortBy;
  cronJobsSortDir: CronSortDir;
  cronStatus: CronStatus | null;
  cronError: string | null;
  cronForm: CronFormState;
  cronFieldErrors: CronFieldErrors;
  cronEditingJobId: string | null;
  cronRunsJobId: string | null;
  cronRunsLoadingMore: boolean;
  cronRuns: CronRunLogEntry[];
  cronRunsTotal: number;
  cronRunsHasMore: boolean;
  cronRunsNextOffset: number | null;
  cronRunsLimit: number;
  cronRunsScope: CronRunScope;
  cronRunsStatuses: CronRunsStatusValue[];
  cronRunsDeliveryStatuses: CronDeliveryStatus[];
  cronRunsStatusFilter: CronRunsStatusFilter;
  cronRunsQuery: string;
  cronRunsSortDir: CronSortDir;
  cronModelSuggestions: string[];
  cronBusy: boolean;
  skillsLoading: boolean;
  skillsReport: SkillStatusReport | null;
  skillsError: string | null;
  skillsFilter: string;
  skillEdits: Record<string, string>;
  skillMessages: Record<string, SkillMessage>;
  skillsBusyKey: string | null;
  // Memory Page (SurrealDB Knowledge Graph)
  memoryLoading?: boolean;
  memoryHealth?: {
    surrealdb_binary: {
      installed: boolean;
      path: string | null;
      version: string | null;
    };
    surrealdb_server: {
      running: boolean;
      port: number;
      error?: string;
    };
    schema: {
      initialized: boolean;
      error?: string;
    };
    python_deps: {
      ok: boolean;
      dependencies: Record<string, boolean>;
    };
    data_dir: {
      path: string;
      exists: boolean;
    };
  } | null;
  memoryStats?: {
    facts: number;
    entities: number;
    relationships: number;
    archived: number;
    avg_confidence: number;
    by_source: Array<{ source: string; count: number }>;
    error?: string;
  } | null;
  memoryError?: string | null;
  memoryMaintenanceLog?: string | null;
  memoryInstallLog?: string | null;
  memoryBusyAction?: string | null;
  // Pipedream Page
  pipedreamLoading?: boolean;
  pipedreamConfigured?: boolean;
  pipedreamCredentials?: {
    clientId: string;
    clientSecret: string;
    projectId: string;
    environment: "development" | "production";
  };
  pipedreamShowCredentialsForm?: boolean;
  pipedreamConnectedApps?: Array<{
    slug: string;
    name: string;
    icon: string;
    connected: boolean;
    toolCount?: number;
    accountName?: string;
  }>;
  pipedreamError?: string | null;
  pipedreamSuccess?: string | null;
  pipedreamTestingApp?: string | null;
  pipedreamConnectingApp?: string | null;
  pipedreamRefreshingApp?: string | null;
  pipedreamExternalUserId?: string;
  // Pipedream App Browser
  pipedreamShowAppBrowser?: boolean;
  pipedreamAppBrowserSearch?: string;
  pipedreamAllApps?: Array<{
    slug: string;
    name: string;
    icon: string;
    connected: boolean;
  }>;
  pipedreamLoadingApps?: boolean;
  pipedreamManualSlug?: string;
  // Zapier Page
  zapierLoading?: boolean;
  zapierConfigured?: boolean;
  zapierMcpUrl?: string;
  zapierShowForm?: boolean;
  zapierToolCount?: number;
  zapierError?: string | null;
  zapierSuccess?: string | null;
  zapierTesting?: boolean;
  zapierTools?: Array<{ name: string; description?: string }>;
  zapierExpandedGroups?: Set<string>;
  // Agents Page
  agentsPageLoading?: boolean;
  agentsPageError?: string | null;
  agentsPageList?: Array<{
    id: string;
    name?: string;
    default?: boolean;
    workspace?: string;
    model?: string | { primary?: string; fallbacks?: string[] };
    identity?: {
      name?: string;
      emoji?: string;
      avatar?: string;
      theme?: string;
    };
    heartbeat?: { every?: string };
    sessionCount?: number;
    lastActive?: string;
  }>;
  agentsPageDefaultId?: string | null;
  agentsPageEditing?: {
    id: string;
    name?: string;
    default?: boolean;
    workspace?: string;
    model?: string | { primary?: string; fallbacks?: string[] };
    identity?: {
      name?: string;
      emoji?: string;
      avatar?: string;
      theme?: string;
    };
    heartbeat?: { every?: string };
  } | null;
  agentsPageIsCreating?: boolean;
  agentsPageBusyId?: string | null;
  agentsPageMessage?: { kind: "success" | "error"; text: string } | null;
  agentsPageWorkspacePattern?: string | null;
  agentsPageDefaultModel?: string | null;
  agentsPageAvailableModels?: Array<{
    id: string;
    name?: string;
    provider: string;
    contextWindow?: number;
  }>;
  // API Keys
  apikeysLoading?: boolean;
  apikeysError?: string | null;
  apikeysKeys?: Array<{
    slot: {
      id: string;
      name: string;
      provider: string;
      description: string;
      configPath: string[];
      envVar?: string;
      features: string[];
      docsUrl?: string;
      placeholder?: string;
    };
    configured: boolean;
    maskedValue?: string;
    source?: "config" | "env";
  }>;
  apikeysEdits?: Record<string, string>;
  apikeysBusyKey?: string | null;
  apikeysMessage?: { kind: "success" | "error"; text: string } | null;
  // Mode Page (Agent Loop Mode)
  modeLoading?: boolean;
  modeCurrentMode?: "core" | "enhanced";
  modeConfig?: {
    enabled: boolean;
    orchestratorProvider?: string;
    orchestratorModel?: string;
    planning: {
      enabled: boolean;
      reflectionAfterTools: boolean;
      maxPlanSteps: number;
    };
    execution: {
      parallelTools: boolean;
      maxConcurrentTools: number;
      confidenceGates: boolean;
      confidenceThreshold: number;
    };
    context: {
      proactiveManagement: boolean;
      summarizeAfterIterations: number;
      contextThreshold: number;
    };
    errorRecovery: {
      enabled: boolean;
      maxAttempts: number;
      learnFromErrors: boolean;
    };
    stateMachine: {
      enabled: boolean;
      logging: boolean;
      metrics: boolean;
    };
  } | null;
  modeSaving?: boolean;
  modeError?: string | null;
  modeSuccess?: string | null;
  modeAvailableModels?: Array<{
    id: string;
    name?: string;
    provider: string;
    contextWindow?: number;
  }>;
  debugLoading: boolean;
  debugStatus: StatusSummary | null;
  debugHealth: HealthSnapshot | null;
  debugModels: unknown[];
  debugHeartbeat: unknown;
  debugCallMethod: string;
  debugCallParams: string;
  debugCallResult: string | null;
  debugCallError: string | null;
  logsLoading: boolean;
  logsError: string | null;
  logsFile: string | null;
  logsEntries: LogEntry[];
  logsFilterText: string;
  logsLevelFilters: Record<LogLevel, boolean>;
  logsAutoFollow: boolean;
  logsTruncated: boolean;
  logsCursor: number | null;
  logsLastFetchAt: number | null;
  logsLimit: number;
  logsMaxBytes: number;
  logsAtBottom: boolean;
  updateAvailable: import("./types.js").UpdateAvailable | null;
  upstreamDivergence: {
    behind: number;
    ahead: number;
    upstreamRef: string;
    localRef: string;
    error?: string;
  } | null;
  updateModalState: "closed" | "confirm" | "checking" | "result";
  client: GatewayBrowserClient | null;
  refreshSessionsAfterChat: Set<string>;
  resetSessionAfterChat: Set<string>;
  connect: () => void;
  setTab: (tab: Tab) => void;
  setTheme: (theme: ThemeMode, context?: ThemeTransitionContext) => void;
  applySettings: (next: UiSettings) => void;
  loadOverview: () => Promise<void>;
  loadAssistantIdentity: () => Promise<void>;
  loadCron: () => Promise<void>;
  handleWhatsAppStart: (force: boolean) => Promise<void>;
  handleWhatsAppWait: () => Promise<void>;
  handleWhatsAppLogout: () => Promise<void>;
  handleChannelConfigSave: () => Promise<void>;
  handleChannelConfigReload: () => Promise<void>;
  handleNostrProfileEdit: (accountId: string, profile: NostrProfile | null) => void;
  handleNostrProfileCancel: () => void;
  handleNostrProfileFieldChange: (field: keyof NostrProfile, value: string) => void;
  handleNostrProfileSave: () => Promise<void>;
  handleNostrProfileImport: () => Promise<void>;
  handleNostrProfileToggleAdvanced: () => void;
  handleExecApprovalDecision: (decision: "allow-once" | "allow-always" | "deny") => Promise<void>;
  handleGatewayUrlConfirm: () => void;
  handleGatewayUrlCancel: () => void;
  handleConfigLoad: () => Promise<void>;
  handleConfigSave: () => Promise<void>;
  handleConfigApply: () => Promise<void>;
  handleConfigFormUpdate: (path: string, value: unknown) => void;
  handleConfigFormModeChange: (mode: "form" | "raw") => void;
  handleConfigRawChange: (raw: string) => void;
  handleInstallSkill: (key: string) => Promise<void>;
  handleUpdateSkill: (key: string) => Promise<void>;
  handleToggleSkillEnabled: (key: string, enabled: boolean) => Promise<void>;
  handleUpdateSkillEdit: (key: string, value: string) => void;
  handleSaveSkillApiKey: (key: string, apiKey: string) => Promise<void>;
  handleCronToggle: (jobId: string, enabled: boolean) => Promise<void>;
  handleCronRun: (jobId: string) => Promise<void>;
  handleCronRemove: (jobId: string) => Promise<void>;
  handleCronAdd: () => Promise<void>;
  handleCronRunsLoad: (jobId: string) => Promise<void>;
  handleCronFormUpdate: (path: string, value: unknown) => void;
  handleSessionsLoad: () => Promise<void>;
  handleSessionsPatch: (key: string, patch: unknown) => Promise<void>;
  handleLoadNodes: () => Promise<void>;
  handleLoadPresence: () => Promise<void>;
  handleLoadSkills: () => Promise<void>;
  handleLoadDebug: () => Promise<void>;
  handleLoadLogs: () => Promise<void>;
  handleDebugCall: () => Promise<void>;
  handleRunUpdate: () => Promise<void>;
  setPassword: (next: string) => void;
  setSessionKey: (next: string) => void;
  setChatMessage: (next: string) => void;
  handleSendChat: (messageOverride?: string, opts?: { restoreDraft?: boolean }) => Promise<void>;
  handleAbortChat: () => Promise<void>;
  removeQueuedMessage: (id: string) => void;
  handleChatScroll: (event: Event) => void;
  resetToolStream: () => void;
  resetChatScroll: () => void;
  exportLogs: (lines: string[], label: string) => void;
  handleLogsScroll: (event: Event) => void;
  handleOpenSidebar: (content: string) => void;
  handleCloseSidebar: () => void;
  handleSplitRatioChange: (ratio: number) => void;
};
