import { IContainer, UseKey, Bindings, IApplication, PathLoader, IServiceProvider, IPathName, IController, HttpContext, IMiddleware } from '@h3ravel/shared';
import { H3Event } from 'h3';

declare class Container implements IContainer {
    private bindings;
    private singletons;
    /**
     * Check if the target has any decorators
     *
     * @param target
     * @returns
     */
    static hasAnyDecorator(target: Function): boolean;
    /**
     * Bind a transient service to the container
     */
    bind<T>(key: new (...args: any[]) => T, factory: () => T): void;
    bind<T extends UseKey>(key: T, factory: () => Bindings[T]): void;
    /**
     * Bind a singleton service to the container
     */
    singleton<T extends UseKey>(key: T | (new (..._args: any[]) => Bindings[T]), factory: () => Bindings[T]): void;
    /**
     * Resolve a service from the container
     */
    make<T extends UseKey, X = undefined>(key: T | (new (..._args: any[]) => Bindings[T])): X extends undefined ? Bindings[T] : X;
    /**
     * Automatically build a class with constructor dependency injection
     */
    private build;
    /**
     * Check if a service is registered
     */
    has(key: UseKey): boolean;
}

declare class Application extends Container implements IApplication {
    paths: PathLoader;
    private booted;
    private versions;
    private basePath;
    private providers;
    protected externalProviders: Array<new (_app: Application) => IServiceProvider>;
    constructor(basePath: string);
    /**
     * Register core bindings into the container
     */
    protected registerBaseBindings(): void;
    /**
     * Dynamically register all configured providers
     */
    registerConfiguredProviders(): Promise<void>;
    protected loadOptions(): Promise<void>;
    /**
     * Load default and optional providers dynamically
     *
     * Auto-Registration Behavior
     *
     * Minimal App: Loads only core, config, http, router by default.
     * Full-Stack App: Installs database, mail, queue, cache → they self-register via their providers.
     */
    protected getConfiguredProviders(): Promise<Array<new (_app: Application) => IServiceProvider>>;
    protected getAllProviders(): Promise<Array<new (_app: Application) => IServiceProvider>>;
    private sortProviders;
    registerProviders(providers: Array<new (_app: Application) => IServiceProvider>): void;
    /**
     * Register a provider
     */
    register(provider: IServiceProvider): Promise<void>;
    /**
     * Boot all providers after registration
     */
    boot(): Promise<void>;
    /**
     * Attempt to dynamically import an optional module
     */
    private safeImport;
    /**
     * Get the base path of the app
     *
     * @returns
     */
    getBasePath(): string;
    /**
     * Dynamically retrieves a path property from the class.
     * Any property ending with "Path" is accessible automatically.
     *
     * @param name - The base name of the path property
     * @returns
     */
    getPath(name: IPathName, pth?: string): string;
    /**
     * Programatically set the paths.
     *
     * @param name - The base name of the path property
     * @param path - The new path
     * @returns
     */
    setPath(name: IPathName, path: string): void;
    /**
     * Returns the installed version of the system core and typescript.
     *
     * @returns
     */
    getVersion(key: 'app' | 'ts'): string;
}

/**
 * Base controller class
 */
declare abstract class Controller implements IController {
    protected app: Application;
    constructor(app: Application);
    show(..._ctx: any[]): any;
    index(..._ctx: any[]): any;
    store(..._ctx: any[]): any;
    update(..._ctx: any[]): any;
    destroy(..._ctx: any[]): any;
}

declare abstract class ServiceProvider implements IServiceProvider {
    static order?: `before:${string}` | `after:${string}` | string | undefined;
    static priority: number;
    protected app: Application;
    constructor(app: Application);
    /**
     * Register bindings to the container.
     * Runs before boot().
     */
    abstract register(): void | Promise<void>;
    /**
     * Perform post-registration booting of services.
     * Runs after all providers have been registered.
     */
    boot?(): void | Promise<void>;
}

type ServiceProviderConstructor = (new (app: Application) => ServiceProvider) & IServiceProvider;

declare function Inject(...dependencies: string[]): (target: any) => void;
/**
 * Allows binding dependencies to both class and class methods
 *
 * @returns
 */
declare function Injectable(): ClassDecorator & MethodDecorator;

/**
 * Kernel class handles middleware execution and response transformations.
 * It acts as the core middleware pipeline for HTTP requests.
 */
declare class Kernel {
    protected context: (event: H3Event) => HttpContext;
    protected middleware: IMiddleware[];
    /**
     * @param context - A factory function that converts an H3Event into an HttpContext.
     * @param middleware - An array of middleware classes that will be executed in sequence.
     */
    constructor(context: (event: H3Event) => HttpContext, middleware?: IMiddleware[]);
    /**
     * Handles an incoming request and passes it through middleware before invoking the next handler.
     *
     * @param event - The raw H3 event object.
     * @param next - A callback function that represents the next layer (usually the controller or final handler).
     * @returns A promise resolving to the result of the request pipeline.
     */
    handle(event: H3Event, next: (ctx: HttpContext) => Promise<unknown>): Promise<unknown>;
    /**
     * Sequentially runs middleware in the order they were registered.
     *
     * @param context - The standardized HttpContext.
     * @param next - Callback to execute when middleware completes.
     * @returns A promise resolving to the final handler's result.
     */
    private runMiddleware;
    /**
     * Utility function to determine if a value is a plain object or array.
     *
     * @param value - The value to check.
     * @returns True if the value is a plain object or array, otherwise false.
     */
    private isPlainObject;
}

/**
 * Bootstraps core services and bindings.
 *
 * Bind essential services to the container (logger, config repository).
 * Register app-level singletons.
 * Set up exception handling.
 *
 * Auto-Registered
 */
declare class CoreServiceProvider extends ServiceProvider {
    static priority: number;
    register(): void;
}

declare class ViewServiceProvider extends ServiceProvider {
    static priority: number;
    register(): void;
}

export { Application, Container, Controller, CoreServiceProvider, Inject, Injectable, Kernel, ServiceProvider, type ServiceProviderConstructor, ViewServiceProvider };
