import type React from 'react';
import type { Layer, ManagedRuntime } from 'effect';
import type { MergeLeft } from 'effect/Types';
import type { Booleans, Call, Objects, Tuples } from 'hotscript';
import type { IsStringLiteral, Simplify, Tagged } from 'type-fest';
import type { createUse } from '@/hooks/useRuntimeApi/hooks/use';
import type { createFn } from '@/hooks/useRuntimeApi/hooks/useFn';
import type { createRun } from '@/hooks/useRuntimeApi/hooks/useRun';
import type { createPush } from 'hooks/useRuntimeApi/hooks/usePush';
import type { PropService } from 'utils/effect';
export type ScopeId = Tagged<string, 'ScopeId'>;
export type InstId = Tagged<string, 'InstId'>;
export type DeclId = Tagged<string, 'DeclId'>;
export type DeclarationId = Tagged<string, 'DeclarationId'>;
export type ComponentId = Tagged<string, 'ComponentId'>;
export type RegisterId = Tagged<string, 'RegisterId'>;
export type RuntimeKey = symbol;
export type RuntimeId = Tagged<string, 'RuntimeId'>;
export type ProviderId = Tagged<string, 'ProviderId'>;
export type InstanceId = Tagged<string, 'InstanceId'>;
export type ComponentMeta = {
    name: string;
};
export declare const ID_PROP = "_id";
export declare const DRYRUN_ID_PROP = "_dryRunId";
export declare const PROVIDERS_PROP = "_providers";
export declare const COMPONENT_PROP = "_component";
export declare const PROPS_PROP = "_props";
export declare const UPSTREAM_PROP = "_upstream";
export declare const ERROR_PROP = "_error";
export type RuntimeApi<R> = {
    instance: RuntimeInstance<R>['runtime'];
    use: ReturnType<typeof createUse<R>>;
    useFn: ReturnType<typeof createFn<R>>;
    usePush: ReturnType<typeof createPush<R>>;
    useRun: ReturnType<typeof createRun<R>>;
};
export type RuntimeApiFactory<R> = {
    create: (module: RuntimeContext<R, never, PropService>, instances: Map<RuntimeKey, RuntimeInstance<any>>) => RuntimeApi<R>;
    createInert: (stub: unknown) => RuntimeApi<R>;
};
export type RuntimeConfig = {
    debug: boolean;
    postUnmountTTL: number;
    env: 'prod' | 'dev';
    replace: boolean;
    cleanupPolicy: 'onUnmount' | 'immediate';
};
export type RuntimeContext<R, E = never, A = never> = {
    key: RuntimeKey;
    name: string;
    layer: Layer.Layer<R, E, A>;
};
export type RuntimePayload<R, P extends Record<string, unknown>> = {
    providerId: string;
    index: number;
    context: RuntimeContext<R, never, PropService>;
    config: Partial<RuntimeConfig>;
    props: P;
};
export type RuntimeInstance<R, P = object> = {
    id: InstanceId;
    runtime: ManagedRuntime.ManagedRuntime<R, never>;
    config: RuntimeConfig;
    propProxy: Subscribable<NoInfer<P>> & P;
};
export type IdProp = {
    readonly id: string;
};
export type Extensible<T extends Record<PropertyKey, unknown>> = T & Record<PropertyKey, unknown>;
export type SubscribeFn<T> = (value: T) => void;
export type UnsubscribeFn = () => void;
export type Subscribable<T> = {
    subscribe: (key: keyof T | PropertyKey, fn: SubscribeFn<T[keyof T]>) => UnsubscribeFn;
    value: T;
};
export type IsPrimitiveString<T> = [T] extends [string] ? IsStringLiteral<T> extends true ? false : true : false;
export type SafeKeys<T extends PropertyKey> = IsStringLiteral<T> extends true ? T : never;
export type ResultProps<CProps, ExtraProps extends Record<PropertyKey, unknown>> = Readonly<Partial<IdProp & Pick<ExtraProps, keyof CProps>> & Omit<CProps, SafeKeys<keyof ExtraProps>>>;
export type ExtensibleProps<CProps> = Extensible<Partial<IdProp & CProps>>;
export type UpstreamProviderApi<P> = {
    inject: <R>(module: RuntimeContext<R, never, PropService>) => RuntimeApi<R>;
    props: P;
};
export type UpstreamProviderFn<CProps, TResult = unknown> = (api: UpstreamProviderApi<MergeLeft<IdProp, CProps>>) => TResult;
export type ProviderApi<R, P = object> = {
    configure: (config?: Partial<RuntimeConfig>) => RuntimeApi<R>;
    runtime: RuntimeApi<R>;
    inject: <R>(module: RuntimeContext<R, never, PropService>) => RuntimeApi<R>;
    props: P;
};
export type ProviderFn<R, CProps, TResult = unknown> = (api: ProviderApi<R, MergeLeft<IdProp, CProps>>) => TResult;
export type PropsFn<CProps, TResult = unknown> = (props: MergeLeft<IdProp, CProps>) => TResult;
export type ProviderEntryType = 'runtime' | 'upstream' | 'props';
export type ProviderEntry<R, C extends React.FC<any>, P = any> = {
    id: ProviderId;
    type: 'runtime';
    module: RuntimeContext<R, never, PropService>;
    fn?: ProviderFn<R, C, P> | ProviderFn<R, C, undefined> | undefined;
} | {
    id: ProviderId;
    type: 'upstream';
    module?: RuntimeContext<R, never, PropService> | undefined;
    fn: ProviderFn<R, C, P> | ProviderFn<R, C>;
} | {
    id: ProviderId;
    type: 'props';
    fn: PropsFn<C, P>;
};
export type ResolvedProviderEntry<R, C extends React.FC<any>, P> = ProviderEntry<R, C, P> & {
    level: number;
    index: number;
};
export type ExtractStaticComponent<T> = T extends {
    [COMPONENT_PROP]: infer C;
} ? C extends (props: infer P) => any ? React.FC<Simplify<P>> : never : T;
export type ExtractStaticProviders<T> = T extends {
    [PROVIDERS_PROP]: infer R;
} ? R extends unknown[] ? R : never : [];
export type ExtractStaticProps<T> = T extends {
    [PROPS_PROP]: infer P;
} ? P : Record<never, never>;
export type ExtractProps<C extends React.FC<any>> = React.ComponentProps<C> & ExtractStaticProps<C>;
export type ExtractStaticUpstream<T> = T extends {
    [UPSTREAM_PROP]: infer U;
} ? U extends unknown[] ? U : never : [];
export type ExtractStaticError<T> = T extends {
    [ERROR_PROP]: infer U;
} ? U extends unknown[] ? U : never : [];
export type UnwrapRuntime<T> = T extends {
    module: infer R;
} ? R : T;
type ExtractReference<T> = UnwrapRuntime<T> extends {
    reference: () => infer R;
} ? R : never;
declare const UpstreamSymbol: unique symbol;
type UpstreamBrand = {
    readonly [UpstreamSymbol]: never;
};
export type Up<T> = T & UpstreamBrand;
export type KeepUpstream<T> = Call<Tuples.Filter<Booleans.Extends<{
    [UpstreamSymbol]: true;
}>>, T>;
type DownstreamBrand = {
    readonly [UpstreamSymbol]: false;
};
export type Down<T> = T & DownstreamBrand;
export type FilterReference<T> = Call<Tuples.Map<Objects.Get<'type'>>, T>;
type ExtractProviders<T> = T extends {
    [PROVIDERS_PROP]?: infer R;
} ? R : never;
type Includes<T extends readonly unknown[], V> = T extends [
    infer Head,
    ...infer Rest
] ? [V] extends [Head] ? true : Includes<Rest, V> : false;
type PushUnique<T extends readonly unknown[], V> = Includes<T, V> extends true ? T : [...T, V];
type Reverse<T> = Call<Tuples.Reverse, T>;
type Unique<T extends any[], Acc extends any[] = []> = T extends [
    infer Head,
    ...infer Tail
] ? Head extends Acc[number] ? Unique<Tail, Acc> : Unique<Tail, [...Acc, Head]> : Acc;
export type CollectProviders<Component, Seen extends unknown[] = [], Acc extends unknown[] = []> = ExtractProviders<Component> extends readonly [infer Head, ...infer Tail] ? ExtractReference<Head> extends infer Ref ? Ref extends object ? Ref extends Seen[number] ? CollectProviders<{
    [PROVIDERS_PROP]?: Tail;
}, Seen, PushUnique<Acc, Head>> : CollectProviders<{
    [PROVIDERS_PROP]?: Tail;
}, [
    ...Seen,
    Ref
], PushUnique<[
    ...Acc,
    ...CollectProviders<Ref, [...Seen, Ref], Acc>
], Head>> : CollectProviders<{
    [PROVIDERS_PROP]?: Tail;
}, Seen, PushUnique<Acc, Head>> : Acc : Acc;
export type TraverseDeps<T> = Reverse<Unique<CollectProviders<T>>>;
export {};
