import type { actionId } from "./Queries"
import type { Method } from "axios"
import type { RacletteStore } from "@racletteCore"
import type EventEmitter from "@racletteCore/lib/eventEmitter"
import type $log from "@racletteCore/lib/logger"
import type { AxiosInstance } from "axios"
import type { Socket } from "socket.io-client"
import type { FetchClientInterface } from "@racletteCore/lib/httpClient"
import type {
  WidgetConf,
  WidgetDeclaration,
  PluginApi,
} from "@racletteOrchestrator"
import type { DefineComponent } from "vue"
import type { UIState, WidgetBase } from "@racletteCore/store/types"
import type { Query } from "@racletteCore/store/reducers/queries/reducers"
export type BroadcastChannelDefinition = {
  channel: string
  channelKey: string
  prefix: string
}[]
// TODO fix types for store
export type CorePluginApi = {
  $store: RacletteStore
  $api: {
    fetch: FetchClientInterface
    axios: AxiosInstance
  }
  $eventbus: EventEmitter
  $socket: Socket
  $log: typeof $log
}

export type PluginEndpointDefinition = {
  actionId?: actionId
  // override the auto generated actionId
  target: string | ((payload: any) => string)
  broadcast?: boolean
  method?: Method
  channels?: BroadcastChannelDefinition
}
export type PluginFrontendDataDefinition = {
  type: string
  operations?: Record<string, PluginEndpointDefinition>
}
export type InstallApi = {
  addDataType: Function
  addNodeDependency: Function
  addStoreEffect: Function
  dispatchStore: Function
}

export type PluginWidget = {
  details: WidgetDeclaration
  config: WidgetConf
  component: Function
}

export type PluginFrontendDefinition = {
  install: (
    $installApi: InstallApi,
    $pluginApi: PluginApi,
  ) => Promise<unknown> | unknown
  widgets: {
    [key: string]: PluginWidget
  }
  i18n: {
    [key: string]: {
      [key: string]: string
    }
  }
  data: { [key: string]: PluginFrontendDataDefinition }

  exportComponents: {
    [key: string]: DefineComponent
  }
}

type StorePayloadObject = Record<string, any>

export type PluginStoreApi = {
  getUiState(): UIState
  setUiState: (payload: Partial<UIState>) => void
  getWidgetState(widgetId: string): WidgetBase | Record<string, never>
  updateWidgetState: (payload: Partial<WidgetBase>, widgetId: string) => void
  setWidgetState: (payload: Partial<WidgetBase>, widgetId: string) => void
  getQueryState(actionId: actionId): Query | Record<string, never>
  getQueryData<T = any>(actionId: actionId): T
  get<T = any>(pathArray: string[], filter: Record<string, any>): T
}
export type PluginTypes = "core" | "npm" | "app"
export type RegisteredPlugin = {
  author: string
  pluginKey: string
  name: string
  pluginType: PluginTypes
  path: string
  widgets: { [key: string]: PluginWidget }
  options: {}
  // later on added stuff
  $api: PluginApi
  initEventbus: () => void
  initCud: (
    orchestratorResultWrapper: { write: Function; read: Function },
    instanceUid: number,
    actionIdOverride: actionId | undefined,
  ) => (
    actionIdOverride: string,
    orchestratorResultWrapper: { write: Function; read: Function },
    instanceId: number,
    pluginData: PluginFrontendDefinition["data"],
  ) => any // TODO: care about orchestratorResultWrapper and any
  initSocket: () => Function
}
