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

part of '../task_timeline_card.dart';

/// Private implementation type for `_TaskTimelineCardState` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _TaskTimelineCardState extends State<TaskTimelineCard> {
  /// Private state stored as `_isHovered` 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 _isHovered = false;

  /// Private state stored as `_isPushRunning` 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 _isPushRunning = false;

  /// Builds the widget subtree for this component.
  /// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
  @override
  Widget build(BuildContext context) {
    final card = widget.card;
    final colors = _CardColors.forKind(card.visualKind);
    return LayoutBuilder(
      builder: (context, constraints) {
        final metrics = _CardMetrics.fromConstraints(
          constraints,
          kind: card.visualKind,
        );
        final content = SizedBox.expand(
          child: Stack(
            children: [
              Positioned.fill(
                child: metrics.isCompact
                    ? _CompactCardText(
                        card: card,
                        color: colors.accent,
                        metrics: metrics,
                        onStatusPressed: widget.onStatusPressed,
                      )
                    : _ExpandedCardContent(
                        card: card,
                        colors: colors,
                        metrics: metrics,
                        onStatusPressed: widget.onStatusPressed,
                      ),
              ),
              Positioned(
                top: metrics.indicatorTop,
                right: 0,
                child: _TrailingControls(
                  card: card,
                  colors: colors,
                  metrics: metrics,
                  actionsVisible: card.showsQuickActions && _isHovered,
                  pushRunning: _isPushRunning,
                  onPushToNext: widget.onPushToNext == null
                      ? null
                      : () => _runPush(widget.onPushToNext!),
                  onPushToTomorrow: widget.onPushToTomorrow == null
                      ? null
                      : () => _runPush(widget.onPushToTomorrow!),
                  onPushToBacklog: widget.onPushToBacklog == null
                      ? null
                      : () => _runPush(widget.onPushToBacklog!),
                ),
              ),
            ],
          ),
        );
        return MouseRegion(
          onEnter: (_) {
            setState(() {
              _isHovered = true;
            });
          },
          onExit: (_) {
            setState(() {
              _isHovered = false;
            });
          },
          child: Material(
            color: Colors.transparent,
            child: InkWell(
              key: ValueKey(card.id),
              borderRadius: BorderRadius.circular(metrics.cardRadius),
              onTap: widget.onTap,
              child: Container(
                padding: metrics.padding,
                clipBehavior: Clip.antiAlias,
                decoration: BoxDecoration(
                  color: colors.background,
                  borderRadius: BorderRadius.circular(metrics.cardRadius),
                  border: Border.all(
                    color: colors.accent,
                    width: metrics.borderWidth,
                  ),
                  boxShadow: [
                    BoxShadow(
                      color: colors.accent.withValues(alpha: 0.12),
                      blurRadius: metrics.shadowBlur,
                      spreadRadius: metrics.shadowSpread,
                    ),
                  ],
                ),
                child: content,
              ),
            ),
          ),
        );
      },
    );
  }

  /// Runs the `_runPush` 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.
  Future<void> _runPush(
    Future<void> Function(TimelineCardModel card) callback,
  ) async {
    if (_isPushRunning) {
      logger.warn(
        () => 'Duplicate card push action ignored. cardId=${widget.card.id}',
      );
      return;
    }
    logger.debug(() => 'Card push action started. cardId=${widget.card.id}');
    setState(() {
      _isPushRunning = true;
    });
    try {
      await callback(widget.card);
      logger.debug(() => 'Card push action finished. cardId=${widget.card.id}');
    } on Object catch (error, stackTrace) {
      logger.error(
        () => 'Card push action failed. cardId=${widget.card.id}',
        error: error,
        stackTrace: stackTrace,
      );
      rethrow;
    } finally {
      if (mounted) {
        setState(() {
          _isPushRunning = false;
        });
      }
    }
  }
}
