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

/// Renders the right-anchored Backlog task detail drawer.
library;

import 'package:flutter/material.dart';
import 'package:scheduler_core/scheduler_core.dart';

import '../../theme/backlog_board_visual_tokens.dart';
import '../../theme/focus_flow_tokens.dart';
import '../timeline/difficulty_bars.dart';
import '../timeline/reward_icon.dart';

/// Right-side detail drawer for the currently selected Backlog task.
class BacklogTaskDrawer extends StatelessWidget {
  /// Creates a Backlog task detail drawer.
  const BacklogTaskDrawer({
    required this.selectedTaskId,
    required this.detail,
    required this.loading,
    required this.errorMessage,
    required this.actionMessage,
    required this.onClose,
    required this.onSchedule,
    required this.onBreakUp,
    required this.onPushToSomeday,
    required this.onRemove,
    required this.onProjectPressed,
    required this.onAddTagPressed,
    required this.onViewDayPressed,
    super.key,
  });

  /// Selected task id while the drawer is open.
  final String? selectedTaskId;

  /// Loaded task detail, if available.
  final BacklogTaskDetailReadModel? detail;

  /// Whether the drawer should show a loading body.
  final bool loading;

  /// Drawer-local error message for a failed detail read.
  final String? errorMessage;

  /// Drawer-local action message, such as a missing-duration prompt.
  final String? actionMessage;

  /// Callback that closes the drawer and clears selection.
  final VoidCallback onClose;

  /// Callback for the primary Schedule action.
  final VoidCallback onSchedule;

  /// Callback for the Break Up action.
  final VoidCallback onBreakUp;

  /// Callback for the Push to Someday action.
  final VoidCallback onPushToSomeday;

  /// Callback for the Remove action.
  final VoidCallback onRemove;

  /// Callback for the project selector placeholder.
  final VoidCallback onProjectPressed;

  /// Callback for the tag add placeholder.
  final VoidCallback onAddTagPressed;

  /// Callback for the suggested-slot View day placeholder.
  final VoidCallback onViewDayPressed;

  /// 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 loadedDetail = detail;
    return DecoratedBox(
      decoration: BoxDecoration(
        color: const Color(0xFF10121B),
        borderRadius: BorderRadius.circular(8),
        border: Border.all(color: FocusFlowTokens.subtleBorder),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withValues(alpha: 0.38),
            blurRadius: 36,
            offset: const Offset(-10, 0),
          ),
        ],
      ),
      child: Padding(
        padding: const EdgeInsets.fromLTRB(18, 16, 18, 18),
        child: loadedDetail == null
            ? _DrawerStatusContent(
                selectedTaskId: selectedTaskId,
                loading: loading,
                errorMessage: errorMessage,
                onClose: onClose,
              )
            : _DrawerDetailContent(
                detail: loadedDetail,
                onClose: onClose,
                onSchedule: onSchedule,
                onBreakUp: onBreakUp,
                onPushToSomeday: onPushToSomeday,
                onRemove: onRemove,
                onProjectPressed: onProjectPressed,
                onAddTagPressed: onAddTagPressed,
                onViewDayPressed: onViewDayPressed,
                actionMessage: actionMessage,
              ),
      ),
    );
  }
}

/// Status body shown before detail is available or after a detail error.
class _DrawerStatusContent extends StatelessWidget {
  /// Creates a drawer status content body.
  const _DrawerStatusContent({
    required this.selectedTaskId,
    required this.loading,
    required this.errorMessage,
    required this.onClose,
  });

  /// Selected task id used in loading copy.
  final String? selectedTaskId;

  /// Whether the detail read is still in progress.
  final bool loading;

  /// Error message for failed reads.
  final String? errorMessage;

  /// Callback that closes the drawer.
  final VoidCallback onClose;

  /// 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) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        _DrawerTopRow(
          title: loading ? 'Loading task' : 'Could not load task details',
          onClose: onClose,
        ),
        Expanded(
          child: Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                if (loading)
                  const SizedBox.square(
                    dimension: 30,
                    child: CircularProgressIndicator(strokeWidth: 2.4),
                  )
                else
                  const Icon(
                    Icons.info_outline,
                    color: FocusFlowTokens.warningYellow,
                    size: 30,
                  ),
                const SizedBox(height: 14),
                Text(
                  loading
                      ? 'Preparing ${selectedTaskId ?? 'task'} details.'
                      : errorMessage ?? 'The selected task is unavailable.',
                  textAlign: TextAlign.center,
                  style: const TextStyle(
                    color: FocusFlowTokens.textMuted,
                    height: 1.35,
                  ),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
}

/// Fully loaded drawer content for one Backlog task.
class _DrawerDetailContent extends StatelessWidget {
  /// Creates loaded drawer content.
  const _DrawerDetailContent({
    required this.detail,
    required this.onClose,
    required this.onSchedule,
    required this.onBreakUp,
    required this.onPushToSomeday,
    required this.onRemove,
    required this.onProjectPressed,
    required this.onAddTagPressed,
    required this.onViewDayPressed,
    required this.actionMessage,
  });

  /// Detail read model supplied by the scheduler application layer.
  final BacklogTaskDetailReadModel detail;

  /// Callback that closes the drawer.
  final VoidCallback onClose;

  /// Callback for Schedule.
  final VoidCallback onSchedule;

  /// Callback for Break Up.
  final VoidCallback onBreakUp;

  /// Callback for Push to Someday.
  final VoidCallback onPushToSomeday;

  /// Callback for Remove.
  final VoidCallback onRemove;

  /// Callback for the project selector placeholder.
  final VoidCallback onProjectPressed;

  /// Callback for the tag add placeholder.
  final VoidCallback onAddTagPressed;

  /// Callback for View day.
  final VoidCallback onViewDayPressed;

  /// Drawer-local action message.
  final String? actionMessage;

  /// 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) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        _DrawerHeader(detail: detail, onClose: onClose),
        const SizedBox(height: 16),
        Expanded(
          child: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                _NotesSection(notes: detail.notes),
                const SizedBox(height: 16),
                _ProjectAndTagsSection(
                  item: detail.item,
                  tags: detail.tags,
                  onProjectPressed: onProjectPressed,
                  onAddTagPressed: onAddTagPressed,
                ),
                const SizedBox(height: 16),
                _MetricTiles(item: detail.item),
                const SizedBox(height: 16),
                _SuggestedSlotsSection(
                  slots: detail.suggestedSlots,
                  unavailableReason: detail.suggestedSlotUnavailableReason,
                  onViewDayPressed: onViewDayPressed,
                ),
              ],
            ),
          ),
        ),
        const SizedBox(height: 18),
        if (actionMessage != null) ...[
          _DrawerActionMessage(message: actionMessage!),
          const SizedBox(height: 10),
        ],
        _DrawerActions(
          onSchedule: onSchedule,
          onBreakUp: onBreakUp,
          onPushToSomeday: onPushToSomeday,
          onRemove: onRemove,
        ),
      ],
    );
  }
}

/// Drawer-local action message panel.
class _DrawerActionMessage extends StatelessWidget {
  /// Creates an action message panel.
  const _DrawerActionMessage({required this.message});

  /// Message body.
  final String message;

  /// 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) {
    return DecoratedBox(
      decoration: BoxDecoration(
        color: FocusFlowTokens.warningYellow.withValues(alpha: 0.1),
        borderRadius: BorderRadius.circular(8),
        border: Border.all(
          color: FocusFlowTokens.warningYellow.withValues(alpha: 0.42),
        ),
      ),
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
        child: Row(
          children: [
            const Icon(
              Icons.info_outline,
              color: FocusFlowTokens.warningYellow,
              size: 18,
            ),
            const SizedBox(width: 9),
            Expanded(
              child: Text(
                message,
                style: const TextStyle(
                  color: FocusFlowTokens.textPrimary,
                  fontSize: 12.5,
                  height: 1.3,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

/// Shared title row with a close button.
class _DrawerTopRow extends StatelessWidget {
  /// Creates a drawer top row.
  const _DrawerTopRow({required this.title, required this.onClose});

  /// Row title.
  final String title;

  /// Close callback.
  final VoidCallback onClose;

  /// 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) {
    return Row(
      children: [
        Expanded(
          child: Text(
            title,
            maxLines: 2,
            overflow: TextOverflow.ellipsis,
            style: const TextStyle(
              color: FocusFlowTokens.textPrimary,
              fontSize: 20,
              fontWeight: FontWeight.w800,
            ),
          ),
        ),
        IconButton(
          key: const ValueKey('backlog-drawer-close-button'),
          tooltip: 'Close task details',
          onPressed: onClose,
          icon: const Icon(Icons.close),
          color: FocusFlowTokens.textMuted,
        ),
      ],
    );
  }
}

/// Header with bucket icon, title, subtitle, and age metadata.
class _DrawerHeader extends StatelessWidget {
  /// Creates a drawer header.
  const _DrawerHeader({required this.detail, required this.onClose});

  /// Detail model to render.
  final BacklogTaskDetailReadModel detail;

  /// Close callback.
  final VoidCallback onClose;

  /// 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 item = detail.item;
    final accent = BacklogBoardVisualTokens.bucketAccent(item.bucket);
    final subtitle = item.subtitle ?? item.bucketReason;
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Container(
              width: 36,
              height: 36,
              decoration: BoxDecoration(
                color: accent.withValues(alpha: 0.12),
                borderRadius: BorderRadius.circular(18),
                border: Border.all(color: accent),
              ),
              child: Icon(
                BacklogBoardVisualTokens.bucketIcon(item.bucket),
                color: accent,
                size: 22,
              ),
            ),
            const SizedBox(width: 12),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Expanded(
                        child: Text(
                          item.title,
                          maxLines: 3,
                          overflow: TextOverflow.ellipsis,
                          style: const TextStyle(
                            color: FocusFlowTokens.textPrimary,
                            fontSize: 21,
                            fontWeight: FontWeight.w800,
                            height: 1.12,
                          ),
                        ),
                      ),
                      const SizedBox(width: 8),
                      const Padding(
                        padding: EdgeInsets.only(top: 2),
                        child: RewardIcon(
                          size: 18,
                          color: FocusFlowTokens.accentMagenta,
                        ),
                      ),
                    ],
                  ),
                  if (subtitle.isNotEmpty) ...[
                    const SizedBox(height: 10),
                    Text(
                      subtitle,
                      maxLines: 3,
                      overflow: TextOverflow.ellipsis,
                      style: const TextStyle(
                        color: FocusFlowTokens.textMuted,
                        height: 1.32,
                      ),
                    ),
                  ],
                  const SizedBox(height: 10),
                  Text(
                    detail.addedLabel,
                    style: const TextStyle(
                      color: FocusFlowTokens.textFaint,
                      fontSize: 12,
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(width: 4),
            IconButton(
              key: const ValueKey('backlog-drawer-close-button'),
              tooltip: 'Close task details',
              onPressed: onClose,
              icon: const Icon(Icons.close),
              color: FocusFlowTokens.textMuted,
            ),
          ],
        ),
      ],
    );
  }
}

/// Notes section for the drawer.
class _NotesSection extends StatelessWidget {
  /// Creates a notes section.
  const _NotesSection({required this.notes});

  /// Optional notes body.
  final String? notes;

  /// 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 body = notes?.trim();
    return _SectionPanel(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const _SectionLabel(label: 'Notes'),
          const SizedBox(height: 10),
          Text(
            body == null || body.isEmpty ? 'No notes yet.' : body,
            style: TextStyle(
              color: body == null || body.isEmpty
                  ? FocusFlowTokens.textFaint
                  : FocusFlowTokens.textMuted,
              height: 1.42,
            ),
          ),
        ],
      ),
    );
  }
}

/// Project and tags row.
class _ProjectAndTagsSection extends StatelessWidget {
  /// Creates a project and tags section.
  const _ProjectAndTagsSection({
    required this.item,
    required this.tags,
    required this.onProjectPressed,
    required this.onAddTagPressed,
  });

  /// Selected task item data.
  final BacklogBoardItemReadModel item;

  /// Detail tag labels.
  final List<String> tags;

  /// Project selector callback.
  final VoidCallback onProjectPressed;

  /// Add-tag callback.
  final VoidCallback onAddTagPressed;

  /// 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) {
    return LayoutBuilder(
      builder: (context, constraints) {
        if (constraints.maxWidth < 360) {
          return Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              _ProjectTile(item: item, onPressed: onProjectPressed),
              const SizedBox(height: 10),
              _TagsTile(tags: tags, onAddTagPressed: onAddTagPressed),
            ],
          );
        }
        return Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Expanded(
              child: _ProjectTile(item: item, onPressed: onProjectPressed),
            ),
            const SizedBox(width: 10),
            Expanded(
              child: _TagsTile(tags: tags, onAddTagPressed: onAddTagPressed),
            ),
          ],
        );
      },
    );
  }
}

/// Project selector tile.
class _ProjectTile extends StatelessWidget {
  /// Creates a project tile.
  const _ProjectTile({required this.item, required this.onPressed});

  /// Selected task item data.
  final BacklogBoardItemReadModel item;

  /// Placeholder selector callback.
  final VoidCallback onPressed;

  /// 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) {
    return _SectionPanel(
      onTap: onPressed,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const _SectionLabel(label: 'Project'),
          const SizedBox(height: 13),
          Row(
            children: [
              _ColorDot(
                color: BacklogBoardVisualTokens.projectColor(
                  item.projectColorToken,
                ),
              ),
              const SizedBox(width: 8),
              Expanded(
                child: Text(
                  item.projectName,
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                  style: const TextStyle(
                    color: FocusFlowTokens.textPrimary,
                    fontWeight: FontWeight.w700,
                  ),
                ),
              ),
              const Icon(
                Icons.keyboard_arrow_down,
                color: FocusFlowTokens.textMuted,
              ),
            ],
          ),
        ],
      ),
    );
  }
}

/// Tags tile with read-only chips and add placeholder.
class _TagsTile extends StatelessWidget {
  /// Creates a tags tile.
  const _TagsTile({required this.tags, required this.onAddTagPressed});

  /// Detail tag labels.
  final List<String> tags;

  /// Add-tag callback.
  final VoidCallback onAddTagPressed;

  /// 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) {
    return _SectionPanel(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const _SectionLabel(label: 'Tags'),
          const SizedBox(height: 10),
          Wrap(
            spacing: 7,
            runSpacing: 7,
            crossAxisAlignment: WrapCrossAlignment.center,
            children: [
              if (tags.isEmpty)
                const Text(
                  'No tags',
                  style: TextStyle(
                    color: FocusFlowTokens.textFaint,
                    fontSize: 12,
                  ),
                )
              else
                for (final tag in tags) _TagChip(label: tag),
              _SmallIconButton(
                key: const ValueKey('backlog-drawer-add-tag-button'),
                tooltip: 'Add tag',
                icon: Icons.add,
                onPressed: onAddTagPressed,
              ),
            ],
          ),
        ],
      ),
    );
  }
}

/// Metric tile row for duration, reward, and difficulty.
class _MetricTiles extends StatelessWidget {
  /// Creates metric tiles.
  const _MetricTiles({required this.item});

  /// Selected task item data.
  final BacklogBoardItemReadModel item;

  /// 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) {
    return LayoutBuilder(
      builder: (context, constraints) {
        final tileWidth = (constraints.maxWidth - 16) / 3;
        return Wrap(
          spacing: 8,
          runSpacing: 8,
          children: [
            SizedBox(
              width: tileWidth,
              child: _MetricTile(
                title: 'Duration',
                leading: const Icon(
                  Icons.schedule,
                  color: FocusFlowTokens.textMuted,
                  size: 18,
                ),
                value: _durationLabel(item.durationMinutes),
                caption: item.durationMinutes == null
                    ? 'Add estimate'
                    : 'Estimated',
              ),
            ),
            SizedBox(
              width: tileWidth,
              child: _MetricTile(
                title: 'Reward',
                leading: const RewardIcon(
                  size: 17,
                  color: FocusFlowTokens.accentMagenta,
                ),
                value: _rewardValue(item.reward),
                caption: _rewardLabel(item.reward),
              ),
            ),
            SizedBox(
              width: tileWidth,
              child: _MetricTile(
                title: 'Difficulty',
                leading: DifficultyBars.forLevel(
                  difficulty: item.difficulty,
                  color: BacklogBoardVisualTokens.bucketAccent(item.bucket),
                  size: const Size(20, 16),
                ),
                value: _difficultyValue(item.difficulty),
                caption: _difficultyLabel(item.difficulty),
              ),
            ),
          ],
        );
      },
    );
  }
}

/// One compact drawer metric tile.
class _MetricTile extends StatelessWidget {
  /// Creates a metric tile.
  const _MetricTile({
    required this.title,
    required this.leading,
    required this.value,
    required this.caption,
  });

  /// Tile title.
  final String title;

  /// Leading icon widget.
  final Widget leading;

  /// Primary value.
  final String value;

  /// Secondary caption.
  final String caption;

  /// 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) {
    return _SectionPanel(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Text(
            title,
            maxLines: 1,
            overflow: TextOverflow.ellipsis,
            style: const TextStyle(
              color: FocusFlowTokens.textMuted,
              fontSize: 12,
              fontWeight: FontWeight.w700,
            ),
          ),
          const SizedBox(height: 10),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              leading,
              const SizedBox(width: 7),
              Flexible(
                child: Text(
                  value,
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                  style: const TextStyle(
                    color: FocusFlowTokens.textPrimary,
                    fontWeight: FontWeight.w800,
                  ),
                ),
              ),
            ],
          ),
          const SizedBox(height: 8),
          Text(
            caption,
            maxLines: 1,
            overflow: TextOverflow.ellipsis,
            style: const TextStyle(
              color: FocusFlowTokens.textMuted,
              fontSize: 12,
            ),
          ),
        ],
      ),
    );
  }
}

/// Suggested slots section.
class _SuggestedSlotsSection extends StatelessWidget {
  /// Creates a suggested slots section.
  const _SuggestedSlotsSection({
    required this.slots,
    required this.unavailableReason,
    required this.onViewDayPressed,
  });

  /// Suggested slot read models.
  final List<SuggestedSlotReadModel> slots;

  /// Optional reason why suggestions are unavailable.
  final String? unavailableReason;

  /// View-day callback.
  final VoidCallback onViewDayPressed;

  /// 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) {
    return _SectionPanel(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Row(
            children: [
              const Expanded(child: _SectionLabel(label: 'Suggested slots')),
              TextButton(
                key: const ValueKey('backlog-drawer-view-day-button'),
                onPressed: onViewDayPressed,
                child: const Text('View day'),
              ),
            ],
          ),
          const SizedBox(height: 10),
          if (slots.isEmpty)
            Text(
              unavailableReason ?? 'No suggested slots yet.',
              style: const TextStyle(
                color: FocusFlowTokens.textFaint,
                height: 1.35,
              ),
            )
          else
            for (final slot in slots) ...[
              _SuggestedSlotRow(slot: slot),
              if (slot != slots.last) const SizedBox(height: 8),
            ],
        ],
      ),
    );
  }
}

/// One suggested schedule slot row.
class _SuggestedSlotRow extends StatelessWidget {
  /// Creates a suggested slot row.
  const _SuggestedSlotRow({required this.slot});

  /// Suggested slot data.
  final SuggestedSlotReadModel slot;

  /// 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 severity = _fitSeverityColor(slot.fitSeverityToken);
    return DecoratedBox(
      decoration: BoxDecoration(
        color: FocusFlowTokens.panelBackground,
        borderRadius: BorderRadius.circular(8),
        border: Border.all(
          color: slot.isPrimary
              ? FocusFlowTokens.accentMagenta
              : severity.withValues(alpha: 0.55),
        ),
      ),
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 9),
        child: Row(
          children: [
            const Icon(
              Icons.calendar_today_outlined,
              color: FocusFlowTokens.textMuted,
              size: 17,
            ),
            const SizedBox(width: 10),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    slot.localDateLabel,
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                    style: TextStyle(
                      color: slot.isPrimary
                          ? BacklogBoardVisualTokens.doNextAccent
                          : FocusFlowTokens.textMuted,
                      fontSize: 12,
                      fontWeight: FontWeight.w800,
                    ),
                  ),
                  const SizedBox(height: 4),
                  Text(
                    '${slot.startText} - ${slot.endText} | ${slot.durationMinutes} min',
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                    style: const TextStyle(
                      color: FocusFlowTokens.textPrimary,
                      fontSize: 12,
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(width: 8),
            _FitBadge(label: slot.fitLabel, color: severity),
            const SizedBox(width: 4),
            const Icon(
              Icons.chevron_right,
              color: FocusFlowTokens.textMuted,
              size: 20,
            ),
          ],
        ),
      ),
    );
  }
}

/// Drawer action area.
class _DrawerActions extends StatelessWidget {
  /// Creates the drawer action button group.
  const _DrawerActions({
    required this.onSchedule,
    required this.onBreakUp,
    required this.onPushToSomeday,
    required this.onRemove,
  });

  /// Schedule callback.
  final VoidCallback onSchedule;

  /// Break-up callback.
  final VoidCallback onBreakUp;

  /// Push-to-someday callback.
  final VoidCallback onPushToSomeday;

  /// Remove callback.
  final VoidCallback onRemove;

  /// 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) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        Row(
          children: [
            Expanded(
              child: FilledButton.icon(
                key: const ValueKey('backlog-drawer-schedule-button'),
                onPressed: onSchedule,
                icon: const Icon(Icons.check),
                label: const Text('Schedule'),
                style: FilledButton.styleFrom(
                  backgroundColor: FocusFlowTokens.accentMagenta,
                  foregroundColor: FocusFlowTokens.textPrimary,
                  padding: const EdgeInsets.symmetric(vertical: 14),
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(8),
                  ),
                ),
              ),
            ),
            const SizedBox(width: 12),
            Expanded(
              child: OutlinedButton.icon(
                key: const ValueKey('backlog-drawer-break-up-button'),
                onPressed: onBreakUp,
                icon: const Icon(Icons.splitscreen),
                label: const Text('Break Up'),
                style: OutlinedButton.styleFrom(
                  padding: const EdgeInsets.symmetric(vertical: 14),
                  side: const BorderSide(color: FocusFlowTokens.subtleBorder),
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(8),
                  ),
                ),
              ),
            ),
          ],
        ),
        const SizedBox(height: 10),
        OutlinedButton.icon(
          key: const ValueKey('backlog-drawer-push-someday-button'),
          onPressed: onPushToSomeday,
          icon: const Icon(Icons.arrow_forward),
          label: const Text('Push to Someday'),
          style: OutlinedButton.styleFrom(
            padding: const EdgeInsets.symmetric(vertical: 14),
            side: const BorderSide(color: FocusFlowTokens.subtleBorder),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(8),
            ),
          ),
        ),
        const SizedBox(height: 10),
        OutlinedButton.icon(
          key: const ValueKey('backlog-drawer-remove-button'),
          onPressed: onRemove,
          icon: const Icon(Icons.delete_outline),
          label: const Text('Remove'),
          style: OutlinedButton.styleFrom(
            padding: const EdgeInsets.symmetric(vertical: 14),
            side: const BorderSide(color: FocusFlowTokens.subtleBorder),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(8),
            ),
          ),
        ),
      ],
    );
  }
}

/// Shared bordered section panel.
class _SectionPanel extends StatelessWidget {
  /// Creates a bordered section panel.
  const _SectionPanel({required this.child, this.onTap});

  /// Panel contents.
  final Widget child;

  /// Optional tap callback.
  final VoidCallback? onTap;

  /// 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 content = DecoratedBox(
      decoration: BoxDecoration(
        color: FocusFlowTokens.panelBackground,
        borderRadius: BorderRadius.circular(8),
        border: Border.all(
          color: FocusFlowTokens.subtleBorder.withValues(alpha: 0.82),
        ),
      ),
      child: Padding(padding: const EdgeInsets.all(14), child: child),
    );
    final callback = onTap;
    if (callback == null) {
      return content;
    }
    return Material(
      color: Colors.transparent,
      child: InkWell(
        onTap: callback,
        borderRadius: BorderRadius.circular(8),
        child: content,
      ),
    );
  }
}

/// Small section label.
class _SectionLabel extends StatelessWidget {
  /// Creates a section label.
  const _SectionLabel({required this.label});

  /// Label text.
  final String label;

  /// 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) {
    return Text(
      label,
      maxLines: 1,
      overflow: TextOverflow.ellipsis,
      style: const TextStyle(
        color: FocusFlowTokens.textPrimary,
        fontWeight: FontWeight.w800,
      ),
    );
  }
}

/// Small colored dot.
class _ColorDot extends StatelessWidget {
  /// Creates a color dot.
  const _ColorDot({required this.color});

  /// Dot color.
  final Color color;

  /// 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) {
    return Container(
      width: 10,
      height: 10,
      decoration: BoxDecoration(color: color, shape: BoxShape.circle),
    );
  }
}

/// Read-only tag chip.
class _TagChip extends StatelessWidget {
  /// Creates a tag chip.
  const _TagChip({required this.label});

  /// Tag label.
  final String label;

  /// 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) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 5),
      decoration: BoxDecoration(
        color: BacklogBoardVisualTokens.tagChipBackground(label),
        borderRadius: BorderRadius.circular(7),
        border: Border.all(
          color: BacklogBoardVisualTokens.tagChipForeground(
            label,
          ).withValues(alpha: 0.42),
        ),
      ),
      child: Text(
        label,
        style: TextStyle(
          color: BacklogBoardVisualTokens.tagChipForeground(label),
          fontSize: 12,
          fontWeight: FontWeight.w700,
        ),
      ),
    );
  }
}

/// Compact icon button used inside chips and rows.
class _SmallIconButton extends StatelessWidget {
  /// Creates a small icon button.
  const _SmallIconButton({
    required this.tooltip,
    required this.icon,
    required this.onPressed,
    super.key,
  });

  /// Tooltip text.
  final String tooltip;

  /// Icon data.
  final IconData icon;

  /// Press callback.
  final VoidCallback onPressed;

  /// 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) {
    return SizedBox.square(
      dimension: 30,
      child: IconButton(
        tooltip: tooltip,
        onPressed: onPressed,
        icon: Icon(icon),
        iconSize: 17,
        color: FocusFlowTokens.textMuted,
        visualDensity: VisualDensity.compact,
        padding: EdgeInsets.zero,
      ),
    );
  }
}

/// Fit badge for a suggested slot.
class _FitBadge extends StatelessWidget {
  /// Creates a fit badge.
  const _FitBadge({required this.label, required this.color});

  /// Badge label.
  final String label;

  /// Badge color.
  final Color color;

  /// 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) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 5),
      decoration: BoxDecoration(
        color: color.withValues(alpha: 0.12),
        borderRadius: BorderRadius.circular(7),
        border: Border.all(color: color.withValues(alpha: 0.72)),
      ),
      child: Text(
        label,
        style: TextStyle(
          color: color,
          fontSize: 11,
          fontWeight: FontWeight.w800,
        ),
      ),
    );
  }
}

/// Formats [minutes] for drawer display.
String _durationLabel(int? minutes) {
  return minutes == null ? 'Not set' : '$minutes min';
}

/// Formats [reward] as a numeric rating.
String _rewardValue(RewardLevel reward) {
  final count = BacklogBoardVisualTokens.rewardCount(reward);
  return count == 0 ? 'Not set' : '$count/5';
}

/// Formats [reward] as a plain-language label.
String _rewardLabel(RewardLevel reward) {
  return switch (reward) {
    RewardLevel.notSet => 'Not set',
    RewardLevel.veryLow => 'Tiny',
    RewardLevel.low => 'Useful',
    RewardLevel.medium => 'Satisfying',
    RewardLevel.high => 'Strong',
    RewardLevel.veryHigh => 'High reward',
  };
}

/// Formats [difficulty] as a numeric rating.
String _difficultyValue(DifficultyLevel difficulty) {
  final count = DifficultyBars.fillCountForLevel(difficulty);
  return count == 0 ? 'Not set' : '$count/5';
}

/// Formats [difficulty] as a plain-language label.
String _difficultyLabel(DifficultyLevel difficulty) {
  return switch (difficulty) {
    DifficultyLevel.notSet => 'Not set',
    DifficultyLevel.veryEasy => 'Very easy',
    DifficultyLevel.easy => 'Easy',
    DifficultyLevel.medium => 'Medium',
    DifficultyLevel.hard => 'Hard',
    DifficultyLevel.veryHard => 'Very hard',
  };
}

/// Resolves [token] to a fit-badge color.
Color _fitSeverityColor(String token) {
  return switch (token) {
    'fit-great' => BacklogBoardVisualTokens.doNextAccent,
    'fit-okay' => FocusFlowTokens.warningYellow,
    _ => FocusFlowTokens.textMuted,
  };
}
