/**
 * Raclette Configuration with ESLint properties
 */
export type RacletteAppMode = "workbench" | "product-view" | string
export type RacletteConfig = {
  name: string
  root: string
  services: {
    frontend?: ServiceFrontendConfig
    backend?: ServiceBackendConfig
    mongodb?: {
      enabled: boolean
      port: number
      name?: string
      volume?: string
      databaseName?: string
      volumes?: VolumeDefinition[] // Add custom volumes property
    }
    cache?: {
      enabled: boolean
      port: number
      name?: string
      volume?: string
      db?: number
      volumes?: VolumeDefinition[] // Add custom volumes property
    
    }
    workbench?: {
      enabled: boolean
      debugPort?: number
      withLogs?: boolean
      frontendPort: number
      backendPort: number
    }
    [key: string]: any
  }
  plugins: Array<string | [string, any]>
  modules: Array<string | [string, any]>
  env: {
    development?: EnvironmentVariables
    production?: EnvironmentVariables
    [key: string]: EnvironmentVariables | undefined
  }
  global: {
    requireAuthentication: boolean
    appMode?: RacletteAppMode
  }
  frontend: {
    additonalPluginPaths?: string[]
    framework: "vue" | "react"
    pleaseLetUsAdvertiseOurselfs?: boolean
    advertiseYourself?: string
    preventNotifications?: boolean
    i18n?: {
      locales?: string[]
      priorities?: Record<string, number>
    }
    vue?: {
      plugins: string[]
    }
    react?: {
      plugins: string[]
    }
    custom?: {
      [key: string]: any
    }
  }
  backend: {
    additonalPluginPaths?: string[]
    sockets?: SocketConfig
    custom?: {
      [key: string]: any
    }
    cache?: CacheConfig
  }
  workbench?: WorkbenchConfig
  typescript?: {
    compilerOptions?: {
      // Allow for any compiler option to be overridden
      [key: string]: any
    }
  }
  eslint?: {
    rules?: Record<string, any>
    plugins?: string[]
    extends?: string[]
    ignores?: string[]
    // Whether to use recommended rules
    useRecommended?: boolean
    // For environment-specific configurations
    env?: Record<string, any>
  }
  // Multi-App Workspace feature - configurable source directories
  sourceDirectories?: Array<{
    name: string
    path: string // Supports env variables like process.env.SOME_PATH || "../fallback"
    priority: number
    servicePathMap?: {
      [service: string]: string
    }
    folderMappings?: {
      [targetPath: string]: string
    }
  }>
  // Generic package merging configuration
  packageMerging?: {
    frontend?: PackageSourceConfig[]
    backend?: PackageSourceConfig[]
    [service: string]: PackageSourceConfig[] | undefined
  }
  // Configurable lock file paths
  lockFiles?: {
    frontend?: string
    backend?: string
    [service: string]: string | undefined
  }
}

export type WorkbenchConfig = {
  frontend: {
    i18n?: {
      locales?: string[]
    }
  }
}

export type ServiceFrontendConfig = {
  enabled: boolean
  port: number
  name?: string
  nodeModulesVolume?: string
  installPackages?: string[]
  volumes?: VolumeDefinition[] // Add custom volumes property
}

export type ServiceBackendConfig = {
  enabled: boolean
  port: number
  name?: string
  nodeModulesVolume?: string
  enableDebug?: boolean
  installPackages?: string[]
  volumes?: VolumeDefinition[] // Add custom volumes property
}

export type EnvironmentVariables = {
  RACLETTE_CORE_ABSOLUTE_PATH?: string
  RACLETTE_DEBUG_MODE?: boolean
  RACLETTE_SOCKET_URL?: string
  RACLETTE_SERVER_BASE_URL?: string
  RACLETTE_INERHIT_NPMRC?: boolean
  RACLETTE_DISABLE_PLUGIN_LOGS?: boolean
  // overrides for service config
  RACLETTE_SERVER_CONTAINERNAME?: string
  RACLETTE_SERVER_PORT?: number
  RACLETTE_SERVER_TOKEN_SECRET?: string
  RACLETTE_CLIENT_CONTAINERNAME?: string
  RACLETTE_CLIENT_PORT?: number
  RACLETTE_MONGODB_HOST?: string
  RACLETTE_MONGODB_CONTAINERNAME?: string
  RACLETTE_MONGODB_PORT?: number
  RACLETTE_MONGODB_VOLUME?: string
  RACLETTE_MONGODB_CONFIG_VOLUME?: string
  RACLETTE_CACHE_URL?: string
  RACLETTE_CACHE_CONTAINERNAME?: string
  RACLETTE_CACHE_PORT?: number
  RACLETTE_CACHE_VOLUME?: string

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  [key: string]: any // Allow additional vars
}

/**
 * Volume Definition for Docker Compose
 */
export type VolumeDefinition = {
  // Source can be a named volume, host path, or volume specification
  source: string
  // Target is the path inside the container
  target: string
  // Optional volume type (bind, volume, tmpfs)
  type?: "bind" | "volume" | "tmpfs"
  // Optional read-only flag
  readonly?: boolean
  // Skip this volume if source path doesn't exist
  mustExist?: boolean
  // Optional volume driver-specific options
  volumeOptions?: {
    // Populate on service creation when volume doesn't exist
    nocopy?: boolean
    // Any other driver-specific options
    [key: string]: any
  }
  // Optional bind-specific options
  bindOptions?: {
    // Propagation mode for bind mounts
    propagation?:
      | "private"
      | "rprivate"
      | "shared"
      | "rshared"
      | "slave"
      | "rslave"
    // Create host path if it doesn't exist
    createHostPath?: boolean
    // Any other bind-specific options
    [key: string]: any
  }
  // Optional tmpfs-specific options
  tmpfsOptions?: {
    // Size of the tmpfs mount in bytes
    size?: number
    // File mode of the tmpfs in octal
    mode?: number
  }
}
/**
 * Cache Configuration
 */
export type CacheConfig = {
  persistence?: "none" | "rdb" | "aof" | "rdb+aof"
  RDB_OPTIONS?: string
}
/**
 * Socket Configuration
 */
export type SocketConfig = {
  /** Configure what data is automatically sent when a frontend joins */
  autoSend: {
    /** Send compositions data on join */
    compositions: boolean
    /** Send interaction links data on join */
    interactionLinks: boolean
    /** Send project configuration on join */
    projectConfig: boolean
    /** Additional custom data types to send (must be in the DB and registered via stream) */
    additionalDatatypes?: {
      [key: string]: boolean | undefined
    }
    customData?: {
      /** Key is the property name in the response, value is the static data */
      [key: string]: any
    }
  }

  /** Socket security configuration */
  security: {
    /** Whether authentication is required for socket connections */
    requireAuth: boolean
    /** Token validation method */
    tokenValidation: "jwt"
    /** Custom validation handler path */
    customValidator?: string
  }

  /** Advanced socket options */
  options: {
    /** Socket.io adapter configuration */
    adapter: "memory" | "cache" | "mongodb"
    /** Connection timeout in milliseconds */
    connectionTimeout: number
    /** Ping interval in milliseconds */
    pingInterval: number
    /** Ping timeout in milliseconds */
    pingTimeout: number
  }
}

/**
 * Raclette Module Definition
 */
export type RacletteModule = {
  name: string
  services?: Record<string, any>
  extendConfig?: (config: RacletteConfig, options: any) => RacletteConfig
  backendExtensions?: {
    plugins?: string[]
    routes?: string[]
  }
  frontendExtensions?: {
    components?: string[]
    plugins?: string[]
  }
  hooks?: Record<string, (...args: any[]) => Promise<void>>
}

export type PluginMetadata = {
  name: string
  author: string
  version: string
  description?: string
  repository?: string
  license?: string
  hooks?: {
    beforeMount?: (app: any) => Promise<void>
    mounted?: (app: any) => Promise<void>
    beforeUnmount?: (app: any) => Promise<void>
  }
  pluginKey?: string
  dependencies?: string[]
  options?: Record<string, any>
  frontendDir?: string // default: "./frontend"
  backendDir?: string // default: "./backend"
}

export type PackageSourceConfig = {
  // Path to the packages.json file (supports env variables)
  file: string
  // Key within the file to extract (e.g., "frontend", "workbench.frontend")
  key: string
}

// Type definitions for better type safety
export const Services = ["frontend", "backend"] as const
export type ServicesType = typeof Services
export type FrontendServerTarget = ServicesType[number]
export type Service = FrontendServerTarget

export const Workbenches = ["workbench.frontend", "workbench.backend"] as const
export type WorkbenchesType = typeof Workbenches
export type WorkbenchTarget = WorkbenchesType[number]

export const PackageTargets = [ ...Services, ...Workbenches] as const;
export type PackageTargetsType = typeof PackageTargets;
export type PackageTarget = PackageTargetsType[number];

export const Environments = ["development", "production"] as const
export type EnvironmentsType = typeof Services
export type Environment = EnvironmentsType[number]
