import type { IReactiveFileSystem, IFileSystemCapabilities } from "@firesystem/core";

/**
 * Provider interface para integração de file systems com o workspace
 * Segue o padrão de providers do VSCode
 */
export interface SourceProvider {
  /**
   * Identificador único do provider (ex: "memory", "indexeddb", "s3")
   */
  readonly scheme: string;

  /**
   * Display name amigável do provider
   */
  readonly displayName: string;

  /**
   * Cria uma nova instância do file system
   * @param config Configuração específica do provider
   */
  createFileSystem(config: any): Promise<IReactiveFileSystem>;

  /**
   * Valida se uma configuração é válida para este provider
   * @param config Configuração a ser validada
   */
  validateConfiguration?(config: any): Promise<{ valid: boolean; errors?: string[] }>;

  /**
   * Retorna as capacidades do file system
   * Útil para o workspace saber limitações antes de criar
   */
  getCapabilities(): IFileSystemCapabilities;

  /**
   * Destrói/limpa uma instância do file system
   * Importante para liberar recursos (conexões, memória, etc)
   */
  dispose?(fs: IReactiveFileSystem): Promise<void>;

  /**
   * Deleta dados permanentes do projeto (opcional)
   * Cada provider decide o que fazer baseado no tipo:
   * - IndexedDB: deleta o banco
   * - S3: não faz nada (dados remotos)
   * - Memory: não faz nada (volátil)
   * @param config Configuração do projeto para identificar os dados
   */
  deleteProjectData?(config: any): Promise<void>;

  /**
   * Informa se o provider armazena dados localmente
   * @returns true se os dados são armazenados localmente (ex: IndexedDB), false se remotos (ex: S3)
   */
  hasLocalData?(): boolean;

  /**
   * Estima o tamanho dos dados locais em bytes (se aplicável)
   * @param config Configuração do projeto
   * @returns Tamanho estimado em bytes ou null se não aplicável
   */
  estimateDataSize?(config: any): Promise<number | null>;
}

/**
 * Configuração de um projeto/source
 */
export interface ProjectSource {
  /**
   * Tipo do source, deve corresponder ao scheme de um provider registrado
   */
  type: string;

  /**
   * Configuração específica do provider
   */
  config: any;

  /**
   * Autenticação opcional
   */
  auth?: any;
}

/**
 * Interface para providers que suportam persistência
 */
export interface PersistableSourceProvider extends SourceProvider {
  /**
   * Salva o estado atual do file system
   */
  save(fs: IReactiveFileSystem, config: any): Promise<void>;

  /**
   * Carrega o estado salvo para o file system
   */
  load(fs: IReactiveFileSystem, config: any): Promise<void>;
}

/**
 * Interface para providers que suportam conversão
 */
export interface ConvertibleSourceProvider extends SourceProvider {
  /**
   * Converte o file system para outro tipo
   * @param fs File system fonte
   * @param targetScheme Scheme do provider alvo
   * @param targetConfig Configuração para o provider alvo
   */
  convertTo(
    fs: IReactiveFileSystem, 
    targetScheme: string, 
    targetConfig: any
  ): Promise<{ config: any; initialData?: any }>;
}

/**
 * Registro de providers no workspace
 */
export interface ProviderRegistry {
  /**
   * Registra um provider
   */
  registerProvider(provider: SourceProvider): void;

  /**
   * Remove um provider do registro
   */
  unregisterProvider(scheme: string): void;

  /**
   * Obtém um provider pelo scheme
   */
  getProvider(scheme: string): SourceProvider | undefined;

  /**
   * Lista todos os providers registrados
   */
  getRegisteredProviders(): SourceProvider[];
}