// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only

part of '../../../export_controller.dart';

/// Registry that resolves export format names to writer factories.
final class ExportWriterRegistry {
  /// Creates a registry from [factories].
  ExportWriterRegistry({
    Map<String, ExportWriterFactory> factories =
        const <String, ExportWriterFactory>{},
  }) : _factories = Map<String, ExportWriterFactory>.fromEntries(
          factories.entries.map(
            (entry) => MapEntry(_normalizeFormat(entry.key), entry.value),
          ),
        );

  /// Private state stored as `_factories` for this implementation.
  /// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
  final Map<String, ExportWriterFactory> _factories;

  /// Default registry with JSON and CSV stub writers.
  factory ExportWriterRegistry.defaults() {
    return ExportWriterRegistry(
      factories: <String, ExportWriterFactory>{
        'json': JsonExportWriter.new,
        'csv': CsvExportWriter.new,
      },
    );
  }

  /// Available format names.
  Set<String> get formats => Set<String>.unmodifiable(_factories.keys);

  /// Register [factory] for [format].
  void register(String format, ExportWriterFactory factory) {
    final normalized = _normalizeFormat(format);
    core.logger.finer(() => 'Export writer registered. format=$normalized');
    _factories[normalized] = factory;
  }

  /// Create a writer for [format] using [sink].
  ExportWriter create(String format, StringSink sink) {
    final normalized = _normalizeFormat(format);
    final factory = _factories[normalized];
    if (factory == null) {
      core.logger.warn(() => 'Export writer lookup failed: unknown format. '
          'format=$normalized availableFormatCount=${_factories.length}');
      throw ExportException('Unknown export format: $format');
    }
    core.logger.finer(() => 'Export writer created. format=$normalized');
    return factory(sink);
  }
}
