import type { ReasoningLevel as LLMReasoningLevel } from "../../utils/llmClient";
import type { ContextAttachmentSupport } from "./contextAttachmentTypes";
import type {
  SelectedTextSource,
  ChatAttachmentCategory,
  ChatAttachment,
  GeneratedChatImage,
  PaperContentSourceMode,
  AdvancedModelParams,
  ActiveNoteSession,
  PaperContextRef,
  QuoteCitation,
  NoteContextRef,
  OtherContextRef,
  CollectionContextRef,
  TagContextRef,
  GlobalConversationSummary,
  PaperConversationSummary,
} from "../../shared/types";

export type {
  SelectedTextSource,
  ChatAttachmentCategory,
  ChatAttachment,
  GeneratedChatImage,
  PaperContentSourceMode,
  AdvancedModelParams,
  ActiveNoteSession,
  PaperContextRef,
  QuoteCitation,
  NoteContextRef,
  OtherContextRef,
  CollectionContextRef,
  TagContextRef,
  GlobalConversationSummary,
  PaperConversationSummary,
} from "../../shared/types";

export type SelectedTextContext = {
  text: string;
  source: SelectedTextSource;
  paperContext?: PaperContextRef;
  noteContext?: NoteContextRef;
  contextItemId?: number;
  pageIndex?: number;
  pageLabel?: string;
};

export interface Message {
  role: "user" | "assistant";
  text: string;
  timestamp: number;
  runMode?: "chat" | "agent";
  agentRunId?: string;
  selectedText?: string;
  selectedTextExpanded?: boolean;
  selectedTexts?: string[];
  selectedTextSources?: SelectedTextSource[];
  selectedTextPaperContexts?: (PaperContextRef | undefined)[];
  selectedTextNoteContexts?: (NoteContextRef | undefined)[];
  selectedTextExpandedIndex?: number;
  screenshotImages?: string[];
  paperContexts?: PaperContextRef[];
  fullTextPaperContexts?: PaperContextRef[];
  citationPaperContexts?: PaperContextRef[];
  quoteCitations?: QuoteCitation[];
  pinnedPaperContexts?: PaperContextRef[];
  selectedCollectionContexts?: CollectionContextRef[];
  selectedTagContexts?: TagContextRef[];
  /** Skill IDs explicitly selected via slash command for this turn. */
  forcedSkillIds?: string[];
  collectionContextsExpanded?: boolean;
  tagContextsExpanded?: boolean;
  paperContextsExpanded?: boolean;
  attachments?: ChatAttachment[];
  modelAttachments?: ChatAttachment[];
  generatedImages?: GeneratedChatImage[];
  attachmentsExpanded?: boolean;
  attachmentActiveIndex?: number;
  screenshotExpanded?: boolean;
  screenshotActiveIndex?: number;
  modelName?: string;
  modelEntryId?: string;
  modelProviderLabel?: string;
  streaming?: boolean;
  pendingFinalText?: string;
  waitingAnimationStartedAt?: number;
  pendingAgentTraceEvents?: import("../../agent/types").AgentRunEventRecord[];
  reasoningSummary?: string;
  reasoningDetails?: string;
  reasoningOpen?: boolean;
  webchatRunState?: "done" | "incomplete" | "error";
  webchatCompletionReason?:
    | "settled"
    | "forced_cancel"
    | "timeout"
    | "error"
    | null;
  webchatChatUrl?: string;
  webchatChatId?: string;
  compactMarker?: boolean;
  runtimeMarkerText?: string;
  modelSwitchMarkerText?: string;
}

export type ChatRuntimeMode = "chat" | "agent";
export type PaperContextSendMode = "retrieval" | "full-next" | "full-sticky";

export type ReasoningProviderKind =
  | "openai"
  | "gemini"
  | "deepseek"
  | "kimi"
  | "mimo"
  | "qwen"
  | "grok"
  | "anthropic"
  | "unsupported";
export type ReasoningLevelSelection = "none" | LLMReasoningLevel;
export type ReasoningOption = {
  level: LLMReasoningLevel;
  enabled: boolean;
  label?: string;
};
export type ActionDropdownSpec = {
  slotId: string;
  slotClassName: string;
  buttonId: string;
  buttonClassName: string;
  buttonText: string;
  menuId: string;
  menuClassName: string;
  disabled?: boolean;
};
export type CustomShortcut = {
  id: string;
  label: string;
  prompt: string;
};
export type ResolvedContextSource = {
  contextItem: Zotero.Item | null;
  paperContext?: PaperContextRef | null;
  support?: ContextAttachmentSupport | null;
  statusText: string;
  sourceKind?:
    | "none"
    | "note"
    | "active-reader"
    | "selected-child"
    | "direct-attachment"
    | "first-child"
    | "best-attachment";
  ownerItem?: Zotero.Item | null;
  rawItem?: Zotero.Item | null;
  ownerItemId?: number;
  contextItemId?: number;
  supportKind?: "pdf" | "text";
  contentSourceMode?: PaperContentSourceMode;
  requiresAsyncResolution?: boolean;
  isAsyncFinal?: boolean;
};

export type ContextSourceLifecycleState = {
  rawItem: Zotero.Item | null;
  ownerItem: Zotero.Item | null;
  contextItem: Zotero.Item | null;
  rawItemId: number;
  ownerItemId: number;
  contextItemId: number;
  sourceKind: NonNullable<ResolvedContextSource["sourceKind"]>;
  supportKind?: "pdf" | "text";
  contentSourceMode?: PaperContentSourceMode;
  requiresAsyncResolution: boolean;
  isAsyncFinal: boolean;
};

export type PdfContext = {
  title: string;
  chunks: string[];
  chunkMeta: PdfChunkMeta[];
  chunkStats: ChunkStat[];
  docFreq: Record<string, number>;
  avgChunkLength: number;
  fullLength: number;
  embeddings?: number[][];
  embeddingCacheKey?: string;
  embeddingPromise?: Promise<number[][] | null>;
  embeddingPromiseKey?: string;
  /** Last embedding attempt that failed; suppresses retry storms for the same config. */
  embeddingFailureKey?: string;
  sourceType?:
    | "mineru"
    | "zotero-worker"
    | "zotero-fulltext-cache"
    | "attachment-markdown"
    | "attachment-html"
    | "attachment-txt"
    | "attachment-docx";
};

export type PdfChunkKind =
  | "abstract"
  | "introduction"
  | "methods"
  | "results"
  | "discussion"
  | "conclusion"
  | "references"
  | "figure-caption"
  | "table-caption"
  | "appendix"
  | "body"
  | "unknown";

export type PdfChunkMeta = {
  chunkIndex: number;
  text: string;
  normalizedText: string;
  sectionLabel?: string;
  chunkKind: PdfChunkKind;
  anchorText?: string;
  leadingNoiseRemoved?: boolean;
};

export type ContextAssemblyMode = "full" | "retrieval";
export type ContextAssemblyStrategy =
  | "paper-first-full"
  | "paper-cache-full"
  | "paper-manual-full"
  | "paper-explicit-retrieval"
  | "paper-followup-retrieval"
  | "general-full"
  | "general-retrieval";

export type ContextBudgetPlan = {
  modelLimitTokens: number;
  limitTokens: number;
  softLimitTokens: number;
  baseInputTokens: number;
  outputReserveTokens: number;
  reasoningReserveTokens: number;
  contextBudgetTokens: number;
};

export type PaperContextCandidate = {
  paperKey: string;
  itemId: number;
  contextItemId: number;
  title: string;
  citationKey?: string;
  firstCreator?: string;
  year?: string;
  chunkIndex: number;
  chunkText: string;
  sectionLabel?: string;
  chunkKind?: PdfChunkKind;
  anchorText?: string;
  leadingNoiseRemoved?: boolean;
  estimatedTokens: number;
  bm25Score: number;
  embeddingScore: number;
  hybridScore: number;
  evidenceScore: number;
  matchedQueryVariant?: string;
  matchedQueryVariants?: string[];
};

export type MultiContextPlan = {
  mode: ContextAssemblyMode;
  strategy: ContextAssemblyStrategy;
  contextText: string;
  contextCache?: import("../../contextCache/manager").ContextCachePlan;
  contextBudget: ContextBudgetPlan;
  usedContextTokens: number;
  selectedPaperCount: number;
  selectedChunkCount: number;
  citationPaperContexts?: PaperContextRef[];
  quoteCitations?: QuoteCitation[];
  assistantInstruction?: string;
};

export type GlobalPortalItem = {
  __llmGlobalPortalItem: true;
  id: number;
  libraryID: number;
  parentID?: number;
  attachmentContentType?: string;
  isAttachment: () => boolean;
  getAttachments: () => number[];
  getField: (field: string) => string;
  isRegularItem: () => boolean;
};

export type PaperPortalItem = {
  __llmPaperPortalItem: true;
  __llmPaperPortalBaseItemID: number;
  __llmPaperPortalSessionVersion: number;
  id: number;
  libraryID: number;
  parentID?: number;
  attachmentContentType?: string;
  isAttachment: () => boolean;
  getAttachments: () => number[];
  getField: (field: string) => string;
  isRegularItem: () => boolean;
};

export type ClaudeGlobalPortalItem = {
  __llmClaudeGlobalPortalItem: true;
  __llmClaudeConversationKind: "global";
  id: number;
  libraryID: number;
  parentID?: number;
  attachmentContentType?: string;
  isAttachment: () => boolean;
  getAttachments: () => number[];
  getField: (field: string) => string;
  isRegularItem: () => boolean;
};

export type ClaudePaperPortalItem = {
  __llmClaudePaperPortalItem: true;
  __llmClaudeConversationKind: "paper";
  __llmClaudePaperPortalBaseItemID: number;
  id: number;
  libraryID: number;
  parentID?: number;
  attachmentContentType?: string;
  isAttachment: () => boolean;
  getAttachments: () => number[];
  getField: (field: string) => string;
  isRegularItem: () => boolean;
};

export type CodexGlobalPortalItem = {
  __llmCodexGlobalPortalItem: true;
  __llmCodexConversationKind: "global";
  id: number;
  libraryID: number;
  parentID?: number;
  attachmentContentType?: string;
  isAttachment: () => boolean;
  getAttachments: () => number[];
  getField: (field: string) => string;
  isRegularItem: () => boolean;
};

export type CodexPaperPortalItem = {
  __llmCodexPaperPortalItem: true;
  __llmCodexConversationKind: "paper";
  __llmCodexPaperPortalBaseItemID: number;
  id: number;
  libraryID: number;
  parentID?: number;
  attachmentContentType?: string;
  isAttachment: () => boolean;
  getAttachments: () => number[];
  getField: (field: string) => string;
  isRegularItem: () => boolean;
};

export type ChunkStat = {
  index: number;
  length: number;
  tf: Record<string, number>;
  uniqueTerms: string[];
};

export type ZoteroTabsState = {
  selectedID?: string | number;
  selectedType?: string;
  _tabs?: Array<{ id?: string | number; type?: string; data?: any }>;
};

// ── Send flow options ─────────────────────────────────────────────────────

import type { ReasoningConfig as LLMReasoningConfig } from "../../utils/llmClient";

export type SendQuestionOptions = {
  body: Element;
  item: Zotero.Item;
  /** Resolved panel/source context selected by compose UI. */
  contextSource?: ResolvedContextSource | null;
  question: string;
  images?: string[];
  model?: string;
  apiBase?: string;
  apiKey?: string;
  authMode?:
    | "api_key"
    | "codex_auth"
    | "codex_app_server"
    | "copilot_auth"
    | "webchat";
  providerProtocol?: import("../../utils/providerProtocol").ProviderProtocol;
  modelEntryId?: string;
  modelProviderLabel?: string;
  reasoning?: LLMReasoningConfig;
  advanced?: AdvancedModelParams;
  displayQuestion?: string;
  selectedTexts?: string[];
  selectedTextSources?: SelectedTextSource[];
  selectedTextPaperContexts?: (PaperContextRef | undefined)[];
  selectedTextNoteContexts?: (NoteContextRef | undefined)[];
  paperContexts?: PaperContextRef[];
  fullTextPaperContexts?: PaperContextRef[];
  selectedCollectionContexts?: CollectionContextRef[];
  selectedTagContexts?: TagContextRef[];
  /** Attachments shown in chat history. */
  attachments?: ChatAttachment[];
  /** Provider-resolved attachments sent to the model. Defaults to `attachments`. */
  modelAttachments?: ChatAttachment[];
  runtimeMode?: ChatRuntimeMode;
  agentRunId?: string;
  skipAgentDispatch?: boolean;
  pdfModePaperKeys?: Set<string>;
  /** Skill IDs force-activated via slash menu selection. */
  forcedSkillIds?: string[];
  /** System messages injected by provider-side PDF upload (Qwen fileid://, Kimi extracted text). */
  pdfUploadSystemMessages?: string[];
  /** [webchat] When true, attach the paper PDF to the ChatGPT query. */
  webchatSendPdf?: boolean;
  /** [webchat] When true, send the prompt into a fresh ChatGPT conversation. */
  webchatForceNewChat?: boolean;
  skipAutoCompact?: boolean;
};

export type EditRetryOptions = {
  body: Element;
  item: Zotero.Item;
  /** Resolved panel/source context selected by compose UI. */
  contextSource?: ResolvedContextSource | null;
  displayQuestion: string;
  selectedTexts?: string[];
  selectedTextSources?: SelectedTextSource[];
  selectedTextPaperContexts?: (PaperContextRef | undefined)[];
  selectedTextNoteContexts?: (NoteContextRef | undefined)[];
  screenshotImages?: string[];
  paperContexts?: PaperContextRef[];
  fullTextPaperContexts?: PaperContextRef[];
  selectedCollectionContexts?: CollectionContextRef[];
  selectedTagContexts?: TagContextRef[];
  /** Attachments shown in chat history. */
  attachments?: ChatAttachment[];
  /** Provider-resolved attachments sent to the retry request. Defaults to `attachments`. */
  modelAttachments?: ChatAttachment[];
  pdfUploadSystemMessages?: string[];
  targetRuntimeMode?: ChatRuntimeMode;
  expected?: {
    conversationKey: number;
    userTimestamp: number;
    assistantTimestamp: number;
  };
  model?: string;
  apiBase?: string;
  apiKey?: string;
  authMode?:
    | "api_key"
    | "codex_auth"
    | "codex_app_server"
    | "copilot_auth"
    | "webchat";
  providerProtocol?: import("../../utils/providerProtocol").ProviderProtocol;
  modelEntryId?: string;
  modelProviderLabel?: string;
  reasoning?: LLMReasoningConfig;
  advanced?: AdvancedModelParams;
};
