import { BasePlugin, BasePluginConfig, IAppResponse, PluginEndpointMap, PluginPhase, RouteConfig } from "../shared/src/plugin.js";
import { PluginExecutionSettings, StreamExecuteHandler, StreamExecutionSettings } from "../shared/src/execute.js";
import { CacheManager } from "../cache/index.js";
import { ITelemetry } from "../telemetry/types.js";
import { AppManager } from "../app/index.js";
import { StreamManager } from "../stream/stream-manager.js";
import { DevFileReader } from "./dev-reader.js";
import express from "express";

//#region src/plugin/plugin.d.ts

/**
 * Base abstract class for creating AppKit plugins.
 *
 * All plugins must declare a static `manifest` property with their metadata
 * and resource requirements. The manifest defines:
 * - `required` resources: Always needed for the plugin to function
 * - `optional` resources: May be needed depending on plugin configuration
 *
 * ## Static vs Runtime Resource Requirements
 *
 * The manifest is static and doesn't know the plugin's runtime configuration.
 * For resources that become required based on config options, plugins can
 * implement a static `getResourceRequirements(config)` method.
 *
 * At runtime, this method is called with the actual config to determine
 * which "optional" resources should be treated as "required".
 *
 * @example Basic plugin with static requirements
 * ```typescript
 * import { Plugin, toPlugin, PluginManifest, ResourceType } from '@databricks/appkit';
 *
 * const myManifest: PluginManifest = {
 *   name: 'myPlugin',
 *   displayName: 'My Plugin',
 *   description: 'Does something awesome',
 *   resources: {
 *     required: [
 *       { type: ResourceType.SQL_WAREHOUSE, alias: 'warehouse', ... }
 *     ],
 *     optional: []
 *   }
 * };
 *
 * class MyPlugin extends Plugin<MyConfig> {
 *   static manifest = myManifest;
 *   name = 'myPlugin';
 * }
 * ```
 *
 * @example Plugin with config-dependent resources
 * ```typescript
 * interface MyConfig extends BasePluginConfig {
 *   enableCaching?: boolean;
 * }
 *
 * const myManifest: PluginManifest = {
 *   name: 'myPlugin',
 *   resources: {
 *     required: [
 *       { type: ResourceType.SQL_WAREHOUSE, alias: 'warehouse', ... }
 *     ],
 *     optional: [
 *       // Database is optional in the static manifest
 *       { type: ResourceType.DATABASE, alias: 'cache', description: 'Required if caching enabled', ... }
 *     ]
 *   }
 * };
 *
 * class MyPlugin extends Plugin<MyConfig> {
 *   static manifest = myManifest;
 *   name = 'myPlugin';
 *
 *   // Runtime method: converts optional resources to required based on config
 *   static getResourceRequirements(config: MyConfig) {
 *     const resources = [];
 *     if (config.enableCaching) {
 *       // When caching is enabled, Database becomes required
 *       resources.push({
 *         type: ResourceType.DATABASE,
 *         alias: 'cache',
 *         resourceKey: 'database',
 *         description: 'Cache storage for query results',
 *         permission: 'CAN_CONNECT_AND_CREATE',
 *         fields: {
 *           instance_name: { env: 'DATABRICKS_CACHE_INSTANCE' },
 *           database_name: { env: 'DATABRICKS_CACHE_DB' },
 *         },
 *         required: true  // Mark as required at runtime
 *       });
 *     }
 *     return resources;
 *   }
 * }
 * ```
 */
declare abstract class Plugin<TConfig extends BasePluginConfig = BasePluginConfig> implements BasePlugin {
  protected config: TConfig;
  protected isReady: boolean;
  protected cache: CacheManager;
  protected app: AppManager;
  protected devFileReader: DevFileReader;
  protected streamManager: StreamManager;
  protected telemetry: ITelemetry;
  /** Registered endpoints for this plugin */
  private registeredEndpoints;
  /**
   * Plugin initialization phase.
   * - 'core': Initialized first (e.g., config plugins)
   * - 'normal': Initialized second (most plugins)
   * - 'deferred': Initialized last (e.g., server plugin)
   */
  static phase: PluginPhase;
  /**
   * Plugin name identifier.
   */
  name: string;
  constructor(config: TConfig);
  injectRoutes(_: express.Router): void;
  setup(): Promise<void>;
  getEndpoints(): PluginEndpointMap;
  abortActiveOperations(): void;
  /**
   * Returns the public exports for this plugin.
   * Override this to define a custom public API.
   * By default, returns an empty object.
   */
  exports(): unknown;
  /**
   * Execute operations using the user's identity from the request.
   * Returns a proxy of this plugin where all method calls execute
   * with the user's Databricks credentials instead of the service principal.
   *
   * @param req - The Express request containing the user token in headers
   * @returns A proxied plugin instance that executes as the user
   * @throws Error if user token is not available in request headers
   */
  asUser(req: express.Request): this;
  /**
   * Creates a proxy that wraps method calls in a user context.
   * This allows all plugin methods to automatically use the user's
   * Databricks credentials.
   */
  private _createUserContextProxy;
  protected executeStream<T>(res: IAppResponse, fn: StreamExecuteHandler<T>, options: StreamExecutionSettings, userKey?: string): Promise<void>;
  protected execute<T>(fn: (signal?: AbortSignal) => Promise<T>, options: PluginExecutionSettings, userKey?: string): Promise<T | undefined>;
  protected registerEndpoint(name: string, path: string): void;
  protected route<_TResponse>(router: express.Router, config: RouteConfig): void;
  private _buildExecutionConfig;
  private _buildInterceptors;
  private _executeWithInterceptors;
  private _checkIfGenerator;
}
//#endregion
export { Plugin };
//# sourceMappingURL=plugin.d.ts.map