import { BuildOptions } from 'esbuild';
import * as React from 'react';

// packages/core/types/src/functions/functionTypes.ts



// =============================================================================
// DEPLOYMENT CONFIGURATION TYPES (for functions.yaml generation)
// =============================================================================

/**
 * Memory allocation options for Cloud Functions
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
type FunctionMemory =
  | '128MB'
  | '256MB'
  | '512MB'
  | '1GB'
  | '2GB'
  | '4GB'
  | '8GB';

/**
 * Function trigger types
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
type FunctionTrigger =
  | 'callable'
  | 'http'
  | 'pubsub'
  | 'firestore'
  | 'auth'
  | 'storage'
  | 'scheduled';

/**
 * Function-level deployment metadata
 * @description Per-function configuration for Firebase deployment (like PageMeta for pages)
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
interface FunctionMeta {
  /** Custom entry point name (defaults to export name) */
  entryPoint?: string;
  /** Deployment regions (overrides app defaults) */
  region?: string[];
  /** Platform version */
  platform?: 'gcfv1' | 'gcfv2';
  /** Category label for organization */
  category?: 'auth' | 'crud' | 'analytics' | 'scheduled' | 'webhook' | string;
  /** Additional labels */
  labels?: Record<string, string>;
  /** Trigger type (defaults to 'callable') */
  trigger?: FunctionTrigger;
  /** For scheduled functions - cron expression */
  schedule?: string;
  /** Memory allocation */
  memory?: FunctionMemory;
  /** Timeout in seconds */
  timeoutSeconds?: number;
  /** Minimum instances (for cold start optimization) */
  minInstances?: number;
  /** Maximum instances */
  maxInstances?: number;
  /** Secret environment variable names (synced via sync-secrets, read via defineSecret) */
  secrets?: string[];
}

/**
 * CRUD entity configuration for auto-generation
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
interface CrudConfig {
  /** Entity collection names to generate CRUD for */
  entities: string[];
  /** Override defaults for all CRUD functions */
  defaults?: Partial<FunctionMeta>;
}

/**
 * App-level defaults for all functions
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
interface FunctionDefaults {
  /** Default deployment regions */
  region?: string[];
  /** Default platform version */
  platform?: 'gcfv1' | 'gcfv2';
  /** App label for all functions */
  labels?: Record<string, string>;
  /** Default memory allocation */
  memory?: FunctionMemory;
  /** Default timeout in seconds */
  timeoutSeconds?: number;
}

/**
 * Complete functions configuration for an app
 * @description Single config file pattern for functions.yaml generation
 *
 * @example
 * ```typescript
 * export const functionsConfig: FunctionsConfig = {
 *   defaults: {
 *     region: ['europe-west1'],
 *     platform: 'gcfv2',
 *     labels: { app: 'myapp' },
 *   },
 *   functions: {
 *     setCustomClaims: { category: 'auth' },
 *     getDashboardMetrics: { category: 'analytics', memory: '512MB' },
 *   },
 *   crud: {
 *     entities: ['car', 'customer', 'inquiry'],
 *   },
 * };
 * ```
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
interface FunctionsConfig {
  /** App-level defaults applied to all functions */
  defaults?: FunctionDefaults;
  /** Static functions configuration (non-CRUD) */
  functions?: Record<string, FunctionMeta>;
  /** CRUD auto-generation configuration */
  crud?: CrudConfig;
}

type $MergeBy<T, K> = Omit<T, keyof K> & K;

type $PreservedValue<Value, Fallback> = [Value] extends [never] ? Fallback : Value;

/**
 * This interface can be augmented by users to add types to `i18next` default TypeOptions.
 *
 * Usage:
 * ```ts
 * // i18next.d.ts
 * import 'i18next';
 * declare module 'i18next' {
 *   interface CustomTypeOptions {
 *     defaultNS: 'custom';
 *     returnNull: false;
 *     returnObjects: false;
 *     nsSeparator: ':';
 *     keySeparator: '.';
 *     compatibilityJSON: 'v4';
 *     allowObjectInHTMLChildren: false;
 *     resources: {
 *       custom: {
 *         foo: 'foo';
 *       };
 *     };
 *   }
 * }
 * ```
 */
interface CustomTypeOptions {}

type TypeOptions = $MergeBy<
  {
    /** @see {InitOptions.returnNull} */
    returnNull: false;

    /** @see {InitOptions.returnEmptyString} */
    returnEmptyString: true;

    /** @see {InitOptions.returnObjects} */
    returnObjects: false;

    /** @see {InitOptions.keySeparator} */
    keySeparator: '.';

    /** @see {InitOptions.nsSeparator} */
    nsSeparator: ':';

    /** @see {InitOptions.pluralSeparator} */
    pluralSeparator: '_';

    /** @see {InitOptions.contextSeparator} */
    contextSeparator: '_';

    /** @see {InitOptions.defaultNS} */
    defaultNS: 'translation';

    /** @see {InitOptions.fallbackNS} */
    fallbackNS: false;

    /** @see {InitOptions.compatibilityJSON} */
    compatibilityJSON: 'v4';

    /** @see {InitOptions.resources} */
    resources: object;

    /**
     * Flag that allows HTML elements to receive objects. This is only useful for React applications
     * where you pass objects to HTML elements so they can be replaced to their respective interpolation
     * values (mostly with Trans component)
     */
    allowObjectInHTMLChildren: false;

    /**
     * Flag that enables strict key checking even if a `defaultValue` has been provided.
     * This ensures all calls of `t` function don't accidentally use implicitly missing keys.
     */
    strictKeyChecks: false;

    /**
     * Prefix for interpolation
     */
    interpolationPrefix: '{{';

    /**
     * Suffix for interpolation
     */
    interpolationSuffix: '}}';

    /** @see {InterpolationOptions.unescapePrefix} */
    unescapePrefix: '-';

    /** @see {InterpolationOptions.unescapeSuffix} */
    unescapeSuffix: '';

    /**
     * Use a proxy-based selector to select a translation.
     *
     * Enables features like go-to definition, and better DX/faster autocompletion
     * for TypeScript developers.
     *
     * If you're working with an especially large set of translations and aren't
     * using context, you set `enableSelector` to `"optimize"` and i18next won't do
     * any type-level processing of your translations at all.
     *
     * With `enableSelector` set to `"optimize"`, i18next is capable of supporting
     * arbitrarily large/deep translation sets without causing any IDE slowdown
     * whatsoever.
     *
     * @default false
     */
    enableSelector: false;
  },
  CustomTypeOptions
>;

type FlatNamespace = $PreservedValue<keyof TypeOptions['resources'], string>;
type Namespace<T = FlatNamespace> = T | readonly T[];

interface ReportNamespaces {
  addUsedNamespaces(namespaces: Namespace): void;
  getUsedNamespaces(): string[];
}

declare module 'i18next' {
  // interface i18n {
  //   reportNamespaces?: ReportNamespaces;
  // }
  interface CustomInstanceExtensions {
    reportNamespaces?: ReportNamespaces;
  }
}

type ObjectOrNever = TypeOptions['allowObjectInHTMLChildren'] extends true
  ? Record<string, unknown>
  : never;

type ReactI18NextChildren = React.ReactNode | ObjectOrNever;

declare module 'react' {
  namespace JSX {
    interface IntrinsicAttributes {
      i18nIsDynamicList?: boolean;
    }
  }

  interface HTMLAttributes<T> {
    // This union is inspired by the typings for React.ReactNode. We do this to fix "This JSX tag's 'children' prop
    // expects a single child of type 'ReactI18NextChildren', but multiple children were provided":
    // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/5a1e9f91ed0143adede394adb3f540e650455f71/types/react/index.d.ts#L268
    children?: ReactI18NextChildren | Iterable<ReactI18NextChildren>;
  }
}

// packages/core/config/functions/index.d.ts
/**
 * @fileoverview Type Definitions for esbuild Configuration
 * @description TypeScript type definitions for esbuild configuration used in Firebase and Vercel function builds.
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */



/**
 * Esbuild configuration options
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
interface EsbuildOptions {
  entry?: string;
  outDir?: string;
  minify?: boolean;
  sourcemap?: boolean;
  platform?: 'firebase' | 'vercel' | 'framework';
  bundleWorkspaceDeps?: boolean;
  importFramework?: boolean;
  external?: boolean;
}

/**
 * Create esbuild configuration for functions
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
declare function createFunctionsEsbuildConfig(
  options?: EsbuildOptions
): BuildOptions;
/**
 * Create root functions esbuild configuration
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
declare function createRootFunctionsConfig(
  options?: EsbuildOptions
): BuildOptions;
/**
 * Create app functions esbuild configuration
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
declare function createAppFunctionsConfig(
  options?: EsbuildOptions
): BuildOptions;

/** Auto-detection options for YAML generation */
interface AutoDetectOptions {
  /** Path to entry file for export detection (e.g., 'src/index.ts') */
  entryFile?: string;
  /** Path to .env file for secret detection (default: '.env') */
  envPath?: string;
}

/**
 * Auto-detect exported function names from entry file
 */
declare function detectExportedFunctions(entryFile: string): string[];

/**
 * Auto-detect secret keys from .env file (non-config keys)
 */
declare function detectSecretsFromEnv(envPath?: string): string[];

/**
 * Generate functions.yaml content from config
 */
declare function generateFunctionsYaml(
  config: FunctionsConfig,
  options?: AutoDetectOptions
): string;

/**
 * Generate yaml and return metadata
 */
declare function generateFunctionsYamlWithInfo(
  config: FunctionsConfig,
  options?: AutoDetectOptions
): {
  yaml: string;
  functions: string[];
  staticFunctions: string[];
  crudFunctions: string[];
  autoDetected: string[];
  autoSecrets: string[];
};

/**
 * Filter .env secrets for Firebase deployment
 * Strips secret keys from .env and moves them to .env.local (emulator-only)
 */
declare function filterEnvSecrets(config: FunctionsConfig): {
  stripped: string[];
  kept: number;
};

/** Build options for buildFunctions */
interface BuildFunctionsOptions {
  /** Entry point file (default: 'src/index.ts') */
  entry?: string;
  /** Output directory (default: 'lib') */
  outDir?: string;
  /** Minify output (default: true in production) */
  minify?: boolean;
  /** Generate source maps (default: true) */
  sourcemap?: boolean;
  /** Print bundle analysis (default: false) */
  analyze?: boolean;
  /** Entry file for auto-detection (default: 'src/index.ts') */
  entryFile?: string;
  /** .env path for secret detection (default: '.env') */
  envPath?: string;
}

/**
 * Build Firebase Functions in one call.
 * Handles: esbuild bundling, functions.yaml generation, .env secret filtering.
 *
 * @example
 * ```js
 * import { buildFunctions } from '@donotdev/core/functions';
 * import { functionsConfig } from './functions.config.js';
 *
 * buildFunctions(functionsConfig);
 * ```
 */
declare function buildFunctions(
  functionsConfig: FunctionsConfig,
  options?: BuildFunctionsOptions
): Promise<void>;

export { buildFunctions, createAppFunctionsConfig, createFunctionsEsbuildConfig, createRootFunctionsConfig, detectExportedFunctions, detectSecretsFromEnv, filterEnvSecrets, generateFunctionsYaml, generateFunctionsYamlWithInfo };
export type { AutoDetectOptions, BuildFunctionsOptions, EsbuildOptions };
