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

part of '../json_csv_writers.dart';

/// CSV export writer for scheduler tasks.
final class CsvExportWriter implements ExportWriter {
  /// Creates a CSV writer that writes to the provided string sink.
  CsvExportWriter(this._sink);

  /// Private state stored as `_sink` 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 StringSink _sink;

  /// Private state stored as `_started` for this implementation.
  /// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
  bool _started = false;

  /// Private state stored as `_ended` for this implementation.
  /// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
  bool _ended = false;

  /// Runs the `begin` operation and completes after its asynchronous work finishes.
  /// Callers should await the returned future so repository writes, UI refreshes, and failure handling happen in a predictable order.
  @override
  Future<void> begin(ExportContext context) async {
    _assertNotEnded();
    _started = true;
    _sink.writeln(
      'id,title,projectId,type,status,durationMinutes,scheduledStartUtc,'
      'scheduledEndUtc',
    );
  }

  /// Runs the `writeTask` operation and completes after its asynchronous work finishes.
  /// Callers should await the returned future so repository writes, UI refreshes, and failure handling happen in a predictable order.
  @override
  Future<void> writeTask(core.Task task) async {
    if (!_started) {
      throw const ExportException('Writer has not started.');
    }
    _assertNotEnded();
    _sink.writeln(<String>[
      task.id,
      task.title,
      task.projectId,
      core.PersistenceEnumMapping.encodeTaskType(task.type),
      core.PersistenceEnumMapping.encodeTaskStatus(task.status),
      task.durationMinutes?.toString() ?? '',
      task.scheduledStart == null
          ? ''
          : core.PersistenceDateTimeConvention.toStoredString(
              task.scheduledStart!,
            ),
      task.scheduledEnd == null
          ? ''
          : core.PersistenceDateTimeConvention.toStoredString(
              task.scheduledEnd!,
            ),
    ].map(_csvCell).join(','));
  }

  /// Runs the `end` operation and completes after its asynchronous work finishes.
  /// Callers should await the returned future so repository writes, UI refreshes, and failure handling happen in a predictable order.
  @override
  Future<void> end() async {
    if (!_started) {
      throw const ExportException('Writer has not started.');
    }
    _assertNotEnded();
    _ended = true;
  }

  /// Runs the `_assertNotEnded` helper used inside this library.
  /// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
  void _assertNotEnded() {
    if (_ended) {
      throw const ExportException('Writer has already ended.');
    }
  }
}
