import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../../../services/analysis_providers.dart'; import '../../../shared/presentation/widgets/async_value_view.dart'; import '../../../shared/presentation/widgets/lab_section_scaffold.dart'; class ExperimentPage extends ConsumerWidget { const ExperimentPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final theme = Theme.of(context); final snapshot = ref.watch(selectedSessionSnapshotProvider); return LabSectionScaffold( eyebrow: 'Experiment', title: 'Follow the AI analyst through each validation step.', description: 'This page visualizes hypotheses, validation chains, score changes, and structured failure reasons across the experiment timeline.', children: [ AsyncValueView( value: snapshot, loadingMessage: 'Loading experiment timeline...', data: (session) { if (session == null) { return const _EmptySessionCard(); } return Column( children: [ Card( child: Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Hypotheses', style: theme.textTheme.titleLarge), const SizedBox(height: 12), ...session.hypotheses.map( (hypothesis) => Padding( padding: const EdgeInsets.only(bottom: 14), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '${hypothesis.label} | ${hypothesis.confidence.toStringAsFixed(2)}', style: theme.textTheme.titleMedium, ), const SizedBox(height: 4), Text( hypothesis.rationale, style: theme.textTheme.bodyMedium, ), const SizedBox(height: 6), Wrap( spacing: 8, runSpacing: 8, children: hypothesis.relatedSignalProfiles .map((item) => Chip(label: Text(item))) .toList(), ), ], ), ), ), ], ), ), ), const SizedBox(height: 16), ...session.experiments.map( (experiment) => Card( child: Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( experiment.title, style: theme.textTheme.titleLarge, ), const SizedBox(height: 8), Text( 'Status: ${experiment.status} | Score: ${experiment.score.total.toStringAsFixed(2)}', style: theme.textTheme.bodyMedium, ), if (experiment.hypothesisId != null) ...[ const SizedBox(height: 6), Text( 'Hypothesis: ${experiment.hypothesisId}', style: theme.textTheme.bodyMedium, ), ], const SizedBox(height: 12), ...experiment.pipelineSummary.map( (node) => Padding( padding: const EdgeInsets.only(bottom: 4), child: Text('- $node'), ), ), if (experiment.score.notes.isNotEmpty) ...[ const SizedBox(height: 12), ...experiment.score.notes.map( (note) => Text('Note: $note'), ), ], if (experiment.failureReasons.isNotEmpty) ...[ const SizedBox(height: 12), Text( 'Failure reasons: ${experiment.failureReasons.join(', ')}', style: theme.textTheme.bodyMedium, ), ], ], ), ), ), ), const SizedBox(height: 8), FilledButton( onPressed: () => context.goNamed('conclusion'), child: const Text('Review Conclusion'), ), ], ); }, ), ], ); } } class _EmptySessionCard extends StatelessWidget { const _EmptySessionCard(); @override Widget build(BuildContext context) { return const Card( child: Padding( padding: EdgeInsets.all(20), child: Text('No session selected yet.'), ), ); } }