import z from 'zod';
import BaseLLM from '../../models/base/llm.js';
import BaseEmbedding from '../../models/base/embedding.js';
import SessionManager from '../../session.js';
import { ChatTurnMessage, Chunk } from '../../types.js';

export type SearchSources = 'web' | 'discussions' | 'academic';

/** Answer mode — вертикаль ответа (travel, finance, academic и т.д.) */
export type AnswerMode = 'standard' | 'focus' | 'academic' | 'writing' | 'travel' | 'finance';

/** locale по geo (например ru, en) — язык ответа */
export type SearchAgentConfig = {
  sources: SearchSources[];
  fileIds: string[];
  llm: BaseLLM<any>;
  embedding: BaseEmbedding<any> | null;
  mode: 'speed' | 'balanced' | 'quality';
  systemInstructions: string;
  locale?: string;
  /** Memory context from memory-svc (Pro) — user preferences, facts */
  memoryContext?: string;
  /** Answer mode — vertical focus (travel, finance, academic) */
  answerMode?: AnswerMode;
  /** Response preferences from user settings */
  responsePrefs?: { format?: string; length?: string; tone?: string };
  /** Step-by-step Learning — объяснять пошагово, показывать ход мысли */
  learningMode?: boolean;
  /** Model Council (Max): 3 LLMs for parallel writer + synthesis */
  councilLlms?: [BaseLLM<any>, BaseLLM<any>, BaseLLM<any>];
  /** Library client для сохранения messages (вместо SQLite) */
  libraryClient?: { upsertMessage: (threadId: string, msgId: string, query: string, opts?: object) => Promise<void>; updateMessage: (threadId: string, msgId: string, opts: object) => Promise<void>; enabled: boolean };
};

export type SearchAgentInput = {
  chatHistory: ChatTurnMessage[];
  followUp: string;
  config: SearchAgentConfig;
  chatId: string;
  messageId: string;
};

export type WidgetInput = {
  chatHistory: ChatTurnMessage[];
  followUp: string;
  classification: ClassifierOutput;
  llm: BaseLLM<any>;
};

export type Widget = {
  type: string;
  shouldExecute: (classification: ClassifierOutput) => boolean;
  execute: (input: WidgetInput) => Promise<WidgetOutput | void>;
};

export type WidgetOutput = {
  type: string;
  llmContext: string;
  data: any;
};

export type ClassifierInput = {
  llm: BaseLLM<any>;
  enabledSources: SearchSources[];
  query: string;
  chatHistory: ChatTurnMessage[];
  locale?: string;
};

export type ClassifierOutput = {
  classification: {
    skipSearch: boolean;
    personalSearch: boolean;
    academicSearch: boolean;
    discussionSearch: boolean;
    showWeatherWidget: boolean;
    showStockWidget: boolean;
    showCalculationWidget: boolean;
  };
  standaloneFollowUp: string;
};

export type AdditionalConfig = {
  llm: BaseLLM<any>;
  embedding: BaseEmbedding<any> | null;
  session: SessionManager;
};

export type ResearcherInput = {
  chatHistory: ChatTurnMessage[];
  followUp: string;
  classification: ClassifierOutput;
  config: SearchAgentConfig;
};

export type ResearcherOutput = {
  findings: ActionOutput[];
  searchFindings: Chunk[];
};

export type SearchActionOutput = {
  type: 'search_results';
  results: Chunk[];
};

export type DoneActionOutput = {
  type: 'done';
};

export type ReasoningResearchAction = {
  type: 'reasoning';
  reasoning: string;
};

export type ActionOutput =
  | SearchActionOutput
  | DoneActionOutput
  | ReasoningResearchAction;

export interface ResearchAction<
  TSchema extends z.ZodObject<any> = z.ZodObject<any>,
> {
  name: string;
  schema: z.ZodObject<any>;
  getToolDescription: (config: { mode: SearchAgentConfig['mode'] }) => string;
  getDescription: (config: { mode: SearchAgentConfig['mode'] }) => string;
  enabled: (config: {
    classification: ClassifierOutput;
    fileIds: string[];
    mode: SearchAgentConfig['mode'];
    sources: SearchSources[];
    hasEmbedding?: boolean;
  }) => boolean;
  execute: (
    params: z.infer<TSchema>,
    additionalConfig: AdditionalConfig & {
      researchBlockId: string;
      fileIds: string[];
    },
  ) => Promise<ActionOutput>;
}
