import 'dart:math';

import 'package:flutter/material.dart';

/// ASCII 문자 분해 파티클
class AsciiParticle {
  AsciiParticle({
    required this.char,
    required this.initialX,
    required this.initialY,
    required this.vx,
    required this.vy,
    required this.delay,
  }) : x = initialX,
       y = initialY,
       opacity = 1.0;

  final String char;
  final double initialX;
  final double initialY;
  final double vx; // X 속도
  final double vy; // Y 속도
  final double delay; // 분해 시작 지연 (0.0 ~ 0.3)

  double x;
  double y;
  double opacity;

  /// 진행도에 따라 파티클 상태 업데이트
  void update(double progress) {
    // 지연 적용
    final adjustedProgress = ((progress - delay) / (1.0 - delay)).clamp(
      0.0,
      1.0,
    );

    if (adjustedProgress <= 0) {
      // 아직 분해 시작 전
      x = initialX;
      y = initialY;
      opacity = 1.0;
      return;
    }

    // 이징 적용 (가속)
    final easedProgress = Curves.easeOutQuad.transform(adjustedProgress);

    // 위치 업데이트 (초기 위치에서 이동)
    x = initialX + vx * easedProgress * 3.0;
    y = initialY + vy * easedProgress * 3.0;

    // 중력 효과
    y += easedProgress * easedProgress * 2.0;

    // 페이드 아웃 (후반부에 급격히)
    opacity = (1.0 - easedProgress * easedProgress).clamp(0.0, 1.0);
  }
}

/// ASCII 캐릭터 분해 애니메이션 위젯
///
/// 캐릭터의 각 ASCII 문자가 파티클로 분해되어 흩어지는 효과
class AsciiDisintegrateWidget extends StatefulWidget {
  const AsciiDisintegrateWidget({
    super.key,
    required this.characterLines,
    this.charWidth = 8.0,
    this.charHeight = 12.0,
    this.duration = const Duration(milliseconds: 1500),
    this.textColor,
    this.onComplete,
  });

  /// ASCII 캐릭터 문자열 (줄 단위)
  final List<String> characterLines;

  /// 문자 너비 (픽셀)
  final double charWidth;

  /// 문자 높이 (픽셀)
  final double charHeight;

  /// 애니메이션 지속 시간
  final Duration duration;

  /// 텍스트 색상 (null이면 테마 색상)
  final Color? textColor;

  /// 완료 콜백
  final VoidCallback? onComplete;

  @override
  State<AsciiDisintegrateWidget> createState() =>
      _AsciiDisintegrateWidgetState();
}

class _AsciiDisintegrateWidgetState extends State<AsciiDisintegrateWidget>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late List<AsciiParticle> _particles;
  final Random _random = Random();

  @override
  void initState() {
    super.initState();
    _initParticles();
    _controller = AnimationController(duration: widget.duration, vsync: this)
      ..addListener(() => setState(() {}))
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          widget.onComplete?.call();
        }
      })
      ..forward();
  }

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

  void _initParticles() {
    _particles = [];

    for (int y = 0; y < widget.characterLines.length; y++) {
      final line = widget.characterLines[y];
      for (int x = 0; x < line.length; x++) {
        final char = line[x];
        // 공백은 파티클로 변환하지 않음
        if (char != ' ') {
          _particles.add(
            AsciiParticle(
              char: char,
              initialX: x.toDouble(),
              initialY: y.toDouble(),
              // 랜덤 속도 (위쪽 + 좌우로 퍼짐)
              vx: (_random.nextDouble() - 0.5) * 4.0,
              vy: -_random.nextDouble() * 2.0 - 0.5, // 위쪽으로
              // 랜덤 지연 (안쪽에서 바깥쪽으로 분해)
              delay: _random.nextDouble() * 0.3,
            ),
          );
        }
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    // 파티클 상태 업데이트
    for (final particle in _particles) {
      particle.update(_controller.value);
    }

    final textColor =
        widget.textColor ?? Theme.of(context).textTheme.bodyMedium?.color;

    return CustomPaint(
      size: Size(
        widget.characterLines.isNotEmpty
            ? widget.characterLines
                      .map((l) => l.length)
                      .reduce((a, b) => a > b ? a : b) *
                  widget.charWidth
            : 0,
        widget.characterLines.length * widget.charHeight,
      ),
      painter: _DisintegratePainter(
        particles: _particles,
        charWidth: widget.charWidth,
        charHeight: widget.charHeight,
        textColor: textColor ?? Colors.white,
      ),
    );
  }
}

/// 분해 파티클 페인터
class _DisintegratePainter extends CustomPainter {
  _DisintegratePainter({
    required this.particles,
    required this.charWidth,
    required this.charHeight,
    required this.textColor,
  });

  final List<AsciiParticle> particles;
  final double charWidth;
  final double charHeight;
  final Color textColor;

  @override
  void paint(Canvas canvas, Size size) {
    for (final particle in particles) {
      if (particle.opacity <= 0) continue;

      final textPainter = TextPainter(
        text: TextSpan(
          text: particle.char,
          style: TextStyle(
            fontFamily: 'JetBrainsMono',
            fontSize: charHeight * 0.9,
            color: textColor.withValues(alpha: particle.opacity),
          ),
        ),
        textDirection: TextDirection.ltr,
      )..layout();

      final x = particle.x * charWidth;
      final y = particle.y * charHeight;

      textPainter.paint(canvas, Offset(x, y));
    }
  }

  @override
  bool shouldRepaint(covariant _DisintegratePainter oldDelegate) => true;
}
