import 'package:flutter/material.dart';
import '../../../../core/theme/app_colors.dart';

/// Status of a timeline node, determines dot style and color.
enum NodeStatus { active, completed, error, warning, idle }

/// A single node in the agent workflow timeline.
///
/// Renders: vertical line | colored dot/spinner | content
/// When [status] is [NodeStatus.active], the dot becomes an animated spinner.
class TimelineEventNode extends StatelessWidget {
  final NodeStatus status;
  final String label;
  final Widget? content;
  final bool isFirst;
  final bool isLast;
  final bool isStreaming;
  final IconData? icon;

  const TimelineEventNode({
    super.key,
    required this.status,
    required this.label,
    this.content,
    this.isFirst = false,
    this.isLast = false,
    this.isStreaming = false,
    this.icon,
  });

  Color get _dotColor => switch (status) {
    NodeStatus.active => AppColors.info,
    NodeStatus.completed => AppColors.success,
    NodeStatus.error => AppColors.error,
    NodeStatus.warning => AppColors.warning,
    NodeStatus.idle => AppColors.textMuted,
  };

  @override
  Widget build(BuildContext context) {
    // Use CustomPaint for the timeline line to avoid IntrinsicHeight which
    // causes bottom-overflow on long content.
    // Icon nodes are 16px tall, plain dots are 10px. The gap in the
    // vertical line must be large enough to avoid overlapping either.
    final dotRadius = icon != null ? 10.0 : 6.0;
    return CustomPaint(
      painter: _TimelineLinePainter(
        color: AppColors.surfaceLight,
        isFirst: isFirst,
        isLast: isLast,
        dotCenter: 14, // vertical center of the dot area
        dotRadius: dotRadius,
        lineX: 14, // horizontal center of the 28px left column
      ),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // Left column: dot only (line is drawn by CustomPaint)
          SizedBox(
            width: 28,
            child: Padding(
              padding: const EdgeInsets.only(top: 6),
              child: Center(
                child: status == NodeStatus.active
                    ? _SpinnerDot(color: _dotColor)
                    : _StaticDot(color: _dotColor, icon: icon),
              ),
            ),
          ),
          const SizedBox(width: 8),
          // Right column: label + content
          Expanded(
            child: Padding(
              padding: const EdgeInsets.only(bottom: 12),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [
                  // Label row
                  Padding(
                    padding: const EdgeInsets.only(top: 2),
                    child: Text(
                      label,
                      style: TextStyle(
                        color: status == NodeStatus.active
                            ? _dotColor
                            : AppColors.textSecondary,
                        fontSize: 13,
                        fontWeight: FontWeight.w500,
                      ),
                      maxLines: 2,
                      overflow: TextOverflow.ellipsis,
                    ),
                  ),
                  // Content
                  if (content != null) ...[
                    const SizedBox(height: 6),
                    content!,
                  ],
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

/// Paints the vertical timeline line behind the node content.
/// Avoids IntrinsicHeight by painting lines based on the actual widget size.
class _TimelineLinePainter extends CustomPainter {
  final Color color;
  final bool isFirst;
  final bool isLast;
  final double dotCenter;
  final double dotRadius;
  final double lineX;

  _TimelineLinePainter({
    required this.color,
    required this.isFirst,
    required this.isLast,
    required this.dotCenter,
    required this.dotRadius,
    required this.lineX,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = color
      ..strokeWidth = 1.5;

    // Line above the dot/icon
    if (!isFirst) {
      canvas.drawLine(Offset(lineX, 0), Offset(lineX, dotCenter - dotRadius), paint);
    }

    // Line below the dot/icon
    if (!isLast) {
      canvas.drawLine(
        Offset(lineX, dotCenter + dotRadius),
        Offset(lineX, size.height),
        paint,
      );
    }
  }

  @override
  bool shouldRepaint(_TimelineLinePainter oldDelegate) =>
      color != oldDelegate.color ||
      isFirst != oldDelegate.isFirst ||
      isLast != oldDelegate.isLast ||
      dotRadius != oldDelegate.dotRadius;
}

/// Static colored dot with optional icon for completed/error/idle states.
class _StaticDot extends StatelessWidget {
  final Color color;
  final IconData? icon;

  const _StaticDot({required this.color, this.icon});

  @override
  Widget build(BuildContext context) {
    if (icon != null) {
      return SizedBox(
        width: 16,
        height: 16,
        child: Icon(icon, size: 14, color: color),
      );
    }
    return Container(
      width: 10,
      height: 10,
      decoration: BoxDecoration(
        shape: BoxShape.circle,
        color: color,
      ),
    );
  }
}

/// Animated pulsing asterisk for active nodes (scale up/down like a star).
class _SpinnerDot extends StatefulWidget {
  final Color color;
  const _SpinnerDot({required this.color});

  @override
  State<_SpinnerDot> createState() => _SpinnerDotState();
}

class _SpinnerDotState extends State<_SpinnerDot>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 800),
    )..repeat(reverse: true);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (_, __) {
        // Pulse between 0.6x and 1.2x scale
        final scale = 0.6 + _controller.value * 0.6;
        return Transform.scale(
          scale: scale,
          child: Text(
            '*',
            style: TextStyle(
              color: widget.color.withValues(alpha: 0.6 + _controller.value * 0.4),
              fontSize: 18,
              fontWeight: FontWeight.bold,
              height: 1,
            ),
          ),
        );
      },
    );
  }
}

/// Code block container used for tool input/output.
class CodeBlock extends StatelessWidget {
  final String text;
  final Color? textColor;
  final int? maxLines;

  const CodeBlock({
    super.key,
    required this.text,
    this.textColor,
    this.maxLines,
  });

  @override
  Widget build(BuildContext context) {
    final style = TextStyle(
      fontFamily: 'monospace',
      fontSize: 12,
      color: textColor ?? AppColors.textSecondary,
      height: 1.4,
    );

    return Container(
      width: double.infinity,
      padding: const EdgeInsets.all(10),
      decoration: BoxDecoration(
        color: AppColors.background,
        borderRadius: BorderRadius.circular(6),
      ),
      child: maxLines != null
          ? Text(
              text.replaceAll('\n', ' '),
              style: style,
              maxLines: maxLines,
              overflow: TextOverflow.ellipsis,
            )
          : SelectableText(
              text,
              style: style,
            ),
    );
  }
}
