import type { ComponentType } from 'react';
import type { Container } from '@tinkoff/dippy';
import { Scope, createToken } from '@tinkoff/dippy';
import type { Route } from '@tinkoff/router';
import type { Command, PageAction } from '@tramvai/core';
import type { ActionsRegistry, INITIAL_APP_STATE_TOKEN, Cache } from '@tramvai/tokens-common';
import type { LazyComponentWrapper } from '@tramvai/react';
import type { StoreClass } from '@tramvai/state';
import type { ChunkExtractor } from '@loadable/server';
import type {
  ChildAppLoader,
  ChildAppDiManager,
  ChildAppPreloadManager,
  ChildAppCommandLineRunner,
  ChildAppRequestConfig,
  WrapperProps,
  RootStateSubscription,
  ChildAppStateManager,
  ChildAppFinalConfig,
  ChildAppRenderManager,
  ChildAppResolutionConfig,
  ResolutionConfig,
  HostProvidedContracts,
  ChildRequiredContracts,
  ChildAppContractManager,
  ChildProvidedContracts,
  HostRequiredContracts,
  ChildContractsFallback,
  HostContractsFallback,
  ChildAppErrorBoundaryHandler,
  ChildAppPreloadManagerPlugin,
  ChildAppLoaderPlugin,
  ChildAppConfigResolutionPlugin,
  ChildAppRenderPlugin,
} from './types';
export * from './types';
const multiOptions = { multi: true } as const;
export const commandLineListTokens = {
  
  customerStart: createToken<Command>('child-app customer_start', multiOptions), 
  resolveUserDeps: createToken<Command>('child-app resolve_user_deps', multiOptions), 
  resolvePageDeps: createToken<Command>('child-app resolve_page_deps', multiOptions), 
  
  clear: createToken<Command>('child-app clear', multiOptions), 
  
  spaTransition: createToken<Command>('child-app spa_transition', multiOptions),
  
  afterSpaTransition: createToken<Command>('child-app after_spa_transition', multiOptions),
};
export const CHILD_APP_RESOLUTION_CONFIGS_TOKEN = createToken<
  | ChildAppResolutionConfig
  | ChildAppResolutionConfig[]
  | (() =>
      | ChildAppResolutionConfig
      | ChildAppResolutionConfig[]
      | Promise<ChildAppResolutionConfig>
      | Promise<ChildAppResolutionConfig[]>)
>('child-app resolve configs', multiOptions);
export const CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN = createToken<{
  resolve(config: ChildAppRequestConfig): ResolutionConfig | undefined;
  init(): Promise<void>;
}>('child-app resolution config manager');
export const CHILD_APP_RESOLVE_CONFIG_TOKEN = createToken<
  (config: ChildAppRequestConfig) => ChildAppFinalConfig | undefined
>('child-app resolve external config');
export const CHILD_APP_RESOLVE_BASE_URL_TOKEN = createToken<string | undefined>(
  'child-app resolve external base url'
);
export const CHILD_APP_PRELOAD_MANAGER_TOKEN = createToken<ChildAppPreloadManager>(
  'child-app preload manager'
);
export const CHILD_APP_INTERNAL_CONFIG_TOKEN = createToken<ChildAppFinalConfig>(
  'child-app current config'
);
export const CHILD_APP_INTERNAL_ACTION_TOKEN = createToken<PageAction | PageAction[]>(
  'child-app action',
  multiOptions
);
export const CHILD_APP_ACTIONS_REGISTRY_TOKEN = createToken<ActionsRegistry>(
  'child-app actions registry'
);
export const CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN = createToken<RootStateSubscription>(
  'child-app root state subscription',
  multiOptions
);
export const CHILD_APP_INTERNAL_ROOT_STATE_ALLOWED_STORE_TOKEN = createToken<StoreClass | string>(
  'child-app root state allowed store',
  multiOptions
);
export const CHILD_APP_INTERNAL_ROOT_DI_BORROW_TOKEN = createToken<any>(
  'child-app root di borrow',
  multiOptions
);
export const IS_CHILD_APP_DI_TOKEN = createToken<boolean>('child-app isChildApp Di');
export const IS_CHILD_APP_CONTRACTS_COMPATIBLE_TOKEN = createToken<boolean>(
  'child-app contracts compatible'
);
export const CHILD_APP_SINGLETON_DI_MANAGER_TOKEN = createToken<ChildAppDiManager>(
  'child-app singleton di manager'
);
export const CHILD_APP_DI_MANAGER_TOKEN = createToken<ChildAppDiManager>('child-app di manager');
export const CHILD_APP_RENDER_MANAGER_TOKEN = createToken<ChildAppRenderManager>(
  'child-app render manager'
);
export const CHILD_APP_STATE_MANAGER_TOKEN =
  createToken<ChildAppStateManager>('child-app state manager');
export const CHILD_APP_LOADER_TOKEN = createToken<ChildAppLoader>('child-app loader');
export const CHILD_APP_LOADER_CACHE_TOKEN = createToken<Cache>('child-app loader cache');
export const CHILD_APP_LOADER_CACHE_CLEANUP_CONFIG_TOKEN = createToken<{
  cleanupIntervalMs?: number;
}>('child-app loader cache cleanup config');
export const CHILD_APP_LOADER_CACHE_OPTIONS_TOKEN = createToken<{
  max?: number;
  ttl?: number;
}>('child-app loader cache options');
export const CHILD_APP_COMMAND_LINE_RUNNER_TOKEN = createToken<ChildAppCommandLineRunner>(
  'child-app command runner'
);
export const CHILD_APP_COMMON_INITIAL_STATE_TOKEN = createToken<
  Record<string, typeof INITIAL_APP_STATE_TOKEN>
>('child-app initialAppState');
export const CHILD_APP_INTERNAL_RENDER_TOKEN =
  createToken<ComponentType<WrapperProps<any>>>('child-app render');
export const CHILD_APP_INTERNAL_CHUNK_EXTRACTOR = createToken<ChunkExtractor>(
  'child-app chunk extractor'
);
export const CHILD_APP_PAGE_SERVICE_TOKEN =
  createToken<ChildAppPageService>('child-app page service');
export const CHILD_APP_PAGE_COMPONENTS_TOKEN = createToken<Record<string, ChildAppPageComponent>>(
  'child-app page components',
  { multi: true }
);
export const CHILD_APP_RENDER_CHILDREN_TOKEN = createToken<ComponentType<{ di: Container }>>(
  'child-app render children'
);
export const CHILD_APP_PRELOAD_SOURCE_LIST_TOKEN = createToken<
  (options: { route?: Route }) => ChildAppRequestConfig[] | Promise<ChildAppRequestConfig[]>
>('child-app preload source list', { multi: true });
export const CHILD_APP_PRELOAD_MANAGER_PLUGIN = createToken<ChildAppPreloadManagerPlugin>(
  'child-app preload plugin',
  { multi: true }
);
export interface ChildAppPageService {
  resolveComponent(route?: Route): Promise<void>;
  getComponentName(route?: Route): string | void;
  getComponent(route?: Route): ChildAppPageComponent | void;
  getActions(route?: Route): PageAction[];
}
export type ChildAppPageComponent = ComponentType<{}> & {
  actions?: PageAction[];
};
export type ChildAppPageComponentDecl =
  | ChildAppPageComponent
  | LazyComponentWrapper<ChildAppPageComponent>;
export type RootDiAccessMode =
  | { mode: 'blacklist'; list: string[] }
  | { mode: 'whitelist'; list: string[] };
export const CHILD_APP_ROOT_DI_ACCESS_MODE_TOKEN = createToken<RootDiAccessMode>(
  'child-app root di access mode',
  { scope: Scope.SINGLETON }
);
export const CHILD_APP_CONTRACT_MANAGER = createToken<ChildAppContractManager>(
  'child-app contract manager',
  { scope: Scope.SINGLETON }
);
export const CHILD_PROVIDED_CONTRACTS = createToken<ChildProvidedContracts>(
  'child-app child provided contracts',
  { multi: true, scope: Scope.SINGLETON }
);
export const HOST_PROVIDED_CONTRACTS = createToken<HostProvidedContracts>(
  'child-app host provided contracts',
  { multi: true, scope: Scope.SINGLETON }
);
export const CHILD_REQUIRED_CONTRACTS = createToken<ChildRequiredContracts>(
  'child-app child required contracts',
  { multi: true, scope: Scope.SINGLETON }
);
export const HOST_REQUIRED_CONTRACTS = createToken<HostRequiredContracts>(
  'child-app host required contracts',
  { multi: true, scope: Scope.SINGLETON }
);
export const CHILD_CONTRACTS_FALLBACK = createToken<ChildContractsFallback>(
  'child-app child contracts fallback',
  {
    multi: true,
  }
);
export const HOST_CONTRACTS_FALLBACK = createToken<HostContractsFallback>(
  'child-app host contracts fallback',
  {
    multi: true,
  }
);
export const CHILD_APP_ERROR_BOUNDARY_TOKEN = createToken<ChildAppErrorBoundaryHandler>(
  'child-app reactErrorBoundaryHandlers',
  {
    multi: true,
  }
);
export const CHILD_APP_RENDER_PLUGIN = createToken<ChildAppRenderPlugin>(
  'child-app render plugin',
  {
    multi: true,
  }
);
export const CHILD_APP_CONFIG_RESOLUTION_PLUGIN = createToken<ChildAppConfigResolutionPlugin>(
  'child-app config resultion plugin',
  { multi: true }
);
export const CHILD_PRELOAD_MANAGER_PLUGIN = createToken<ChildAppPreloadManagerPlugin>(
  'child-app preload manager plugin',
  {
    multi: true,
  }
);
export const CHILD_APP_LOADER_PLUGIN = createToken<ChildAppLoaderPlugin>(
  'child-app loader plugin',
  { multi: true }
);