import { invoke } from "@tauri-apps/api/core";
import type {
  ConnectionConfig,
  ConnectResult,
  DbFlavor,
  QueryResult,
  PaginatedQueryResult,
  SchemaObject,
  ColumnDetail,
  ColumnInfo,
  ConstraintInfo,
  IndexInfo,
  TriggerInfo,
  HistoryEntry,
  SavedQuery,
  AiSettings,
  OllamaModel,
  AppSettings,
  McpStatus,
  ChatMessage,
  ChatTurnResult,
} from "@/types";

// Connections
export const getConnections = () =>
  invoke<ConnectionConfig[]>("get_connections");

export const saveConnection = (config: ConnectionConfig) =>
  invoke<void>("save_connection", { config });

export const deleteConnection = (id: string) =>
  invoke<void>("delete_connection", { id });

export const testConnection = (config: ConnectionConfig) =>
  invoke<string>("test_connection", { config });

export const connectDb = (config: ConnectionConfig) =>
  invoke<ConnectResult>("connect", { config });

export const disconnectDb = (id: string) =>
  invoke<void>("disconnect", { id });

export const switchDatabase = (config: ConnectionConfig, database: string) =>
  invoke<void>("switch_database", { config, database });

// Read-Only
export const setReadOnly = (connectionId: string, readOnly: boolean) =>
  invoke<void>("set_read_only", { connectionId, readOnly });

export const getReadOnly = (connectionId: string) =>
  invoke<boolean>("get_read_only", { connectionId });

export const getDbFlavor = (connectionId: string) =>
  invoke<DbFlavor>("get_db_flavor", { connectionId });

// Queries
export const executeQuery = (connectionId: string, sql: string) =>
  invoke<QueryResult>("execute_query", { connectionId, sql });

// Schema
export const listDatabases = (connectionId: string) =>
  invoke<string[]>("list_databases", { connectionId });

export const listSchemas = (connectionId: string) =>
  invoke<string[]>("list_schemas", { connectionId });

export const listTables = (connectionId: string, schema: string) =>
  invoke<SchemaObject[]>("list_tables", { connectionId, schema });

export const listViews = (connectionId: string, schema: string) =>
  invoke<SchemaObject[]>("list_views", { connectionId, schema });

export const listFunctions = (connectionId: string, schema: string) =>
  invoke<SchemaObject[]>("list_functions", { connectionId, schema });

export const listIndexes = (connectionId: string, schema: string) =>
  invoke<SchemaObject[]>("list_indexes", { connectionId, schema });

export const listSequences = (connectionId: string, schema: string) =>
  invoke<SchemaObject[]>("list_sequences", { connectionId, schema });

export const getTableColumns = (
  connectionId: string,
  schema: string,
  table: string
) => invoke<ColumnInfo[]>("get_table_columns", { connectionId, schema, table });

export const getColumnDetails = (
  connectionId: string,
  schema: string,
  table: string
) => invoke<ColumnDetail[]>("get_column_details", { connectionId, schema, table });

export const getTableConstraints = (
  connectionId: string,
  schema: string,
  table: string
) =>
  invoke<ConstraintInfo[]>("get_table_constraints", {
    connectionId,
    schema,
    table,
  });

export const getTableIndexes = (
  connectionId: string,
  schema: string,
  table: string
) => invoke<IndexInfo[]>("get_table_indexes", { connectionId, schema, table });

export const getTableTriggers = (
  connectionId: string,
  schema: string,
  table: string
) => invoke<TriggerInfo[]>("get_table_triggers", { connectionId, schema, table });

// Data
export const getTableData = (params: {
  connectionId: string;
  schema: string;
  table: string;
  page: number;
  pageSize: number;
  sortColumn?: string;
  sortDirection?: string;
  filter?: string;
}) => invoke<PaginatedQueryResult>("get_table_data", params);

export const updateRow = (params: {
  connectionId: string;
  schema: string;
  table: string;
  pkColumns: string[];
  pkValues: unknown[];
  column: string;
  value: unknown;
  ctid?: string;
}) => invoke<void>("update_row", params);

export const insertRow = (params: {
  connectionId: string;
  schema: string;
  table: string;
  columns: string[];
  values: unknown[];
}) => invoke<void>("insert_row", params);

export const deleteRows = (params: {
  connectionId: string;
  schema: string;
  table: string;
  pkColumns: string[];
  pkValuesList: unknown[][];
  ctids?: string[];
}) => invoke<number>("delete_rows", params);

// History
export const addHistoryEntry = (entry: HistoryEntry) =>
  invoke<void>("add_history_entry", { entry });

export const getHistory = (params?: {
  connectionId?: string;
  search?: string;
  limit?: number;
}) =>
  invoke<HistoryEntry[]>("get_history", {
    connectionId: params?.connectionId,
    search: params?.search,
    limit: params?.limit,
  });

export const clearHistory = () => invoke<void>("clear_history");

// Saved Queries
export const listSavedQueries = (params?: { search?: string }) =>
  invoke<SavedQuery[]>("list_saved_queries", { search: params?.search });

export const saveQuery = (query: SavedQuery) =>
  invoke<void>("save_query", { query });

export const deleteSavedQuery = (id: string) =>
  invoke<void>("delete_saved_query", { id });

// Completion schema
export const getCompletionSchema = (connectionId: string) =>
  invoke<Record<string, Record<string, string[]>>>(
    "get_completion_schema",
    { connectionId }
  );

// Export
export const exportCsv = (
  path: string,
  columns: string[],
  rows: unknown[][]
) => invoke<void>("export_csv", { path, columns, rows });

export const exportJson = (
  path: string,
  columns: string[],
  rows: unknown[][]
) => invoke<void>("export_json", { path, columns, rows });

// AI
export const getAiSettings = () =>
  invoke<AiSettings>("get_ai_settings");

export const saveAiSettings = (settings: AiSettings) =>
  invoke<void>("save_ai_settings", { settings });

export const listOllamaModels = (ollamaUrl: string) =>
  invoke<OllamaModel[]>("list_ollama_models", { ollamaUrl });

export const listFireworksModels = (apiKey: string) =>
  invoke<OllamaModel[]>("list_fireworks_models", { apiKey });

export const listOpenRouterModels = (apiKey: string) =>
  invoke<OllamaModel[]>("list_openrouter_models", { apiKey });

export const chatSend = (connectionId: string, messages: ChatMessage[]) =>
  invoke<ChatTurnResult>("chat_send", { connectionId, messages });

export const chatCompact = (connectionId: string, messages: ChatMessage[]) =>
  invoke<ChatTurnResult>("chat_compact", { connectionId, messages });

// Memory (per-connection markdown notes for the chat agent)
export const getMemory = (connectionId: string) =>
  invoke<string>("get_memory", { connectionId });

export const saveMemory = (connectionId: string, content: string) =>
  invoke<void>("save_memory", { connectionId, content });

// App Settings
export const getAppSettings = () =>
  invoke<AppSettings>("get_app_settings");

export const saveAppSettings = (settings: AppSettings) =>
  invoke<void>("save_app_settings", { settings });

export const getMcpStatus = () =>
  invoke<McpStatus>("get_mcp_status");
