import 'dart:async';

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

import '../../theming/app_theme.dart';
import '../../theming/light_app_theme.dart';

class PostLoginSplash extends StatefulWidget {
  const PostLoginSplash({super.key, required this.onComplete});

  static const String _darkAsset = 'assets/logo/logo-anim-white.json';
  static const String _lightAsset = 'assets/logo/logo-anim-red.json';

  static LottieComposition? _darkComposition;
  static LottieComposition? _lightComposition;

  static Future<void> precache() async {
    try {
      _darkComposition ??= await AssetLottie(_darkAsset).load();
      _lightComposition ??= await AssetLottie(_lightAsset).load();
    } catch (e) {
      // Precache is a best-effort warm-up; the splash falls back to loading the
      // composition on demand. Log so a broken asset is at least diagnosable.
      debugPrint('PostLoginSplash.precache failed: $e');
    }
  }

  final VoidCallback onComplete;

  @override
  State<PostLoginSplash> createState() => _PostLoginSplashState();
}

class _PostLoginSplashState extends State<PostLoginSplash>
    with TickerProviderStateMixin {
  static const Duration _holdAfterLogo = Duration(milliseconds: 450);

  late final AnimationController _intro;
  late final AnimationController _outro;
  late final AnimationController _logo;
  late final Animation<double> _introCurve;
  late final Animation<double> _outroCurve;
  Timer? _safety;
  Timer? _hold;

  LottieComposition? _composition;
  bool _started = false;
  bool _outroStarted = false;
  bool _completed = false;

  @override
  void initState() {
    super.initState();
    _intro = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 900),
    );
    _outro = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 850),
    );
    _introCurve = CurvedAnimation(parent: _intro, curve: Curves.easeInOut);
    _outroCurve = CurvedAnimation(parent: _outro, curve: Curves.easeInOutCubic);
    _logo = AnimationController(vsync: this);
    _logo.addStatusListener((status) {
      if (status == AnimationStatus.completed) _scheduleOutro();
    });
    _safety = Timer(const Duration(seconds: 6), _startOutro);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    if (_started || _outroStarted) return;
    final isDark = AppTheme.isDarkMode(context);
    final cached = isDark
        ? PostLoginSplash._darkComposition
        : PostLoginSplash._lightComposition;
    if (cached != null) {
      _begin(cached);
      return;
    }
    final asset = isDark
        ? PostLoginSplash._darkAsset
        : PostLoginSplash._lightAsset;
    AssetLottie(asset)
        .load()
        .then((c) {
          if (mounted) _begin(c);
        })
        .catchError((_) {});
  }

  void _begin(LottieComposition composition) {
    if (_started || _outroStarted || !mounted) return;
    _started = true;
    _logo.duration = composition.duration * 0.9;
    setState(() => _composition = composition);
    _intro.forward(from: 0);
    _logo.forward(from: 0);
  }

  void _scheduleOutro() {
    if (_outroStarted || _hold != null) return;
    _hold = Timer(_holdAfterLogo, _startOutro);
  }

  void _startOutro() {
    if (_outroStarted) return;
    _outroStarted = true;
    _safety?.cancel();
    _hold?.cancel();
    _outro.forward().whenComplete(() {
      if (_completed || !mounted) return;
      _completed = true;
      widget.onComplete();
    });
  }

  @override
  void dispose() {
    _safety?.cancel();
    _hold?.cancel();
    _intro.dispose();
    _outro.dispose();
    _logo.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final surface = Theme.of(context).scaffoldBackgroundColor;
    return AbsorbPointer(
      child: AnimatedBuilder(
        animation: Listenable.merge([_introCurve, _outroCurve]),
        builder: (context, _) {
          final intro = _introCurve.value;
          final outro = _outroCurve.value;
          final background = Color.lerp(
            LightAppTheme.marianumRed,
            surface,
            intro,
          );
          return Opacity(
            opacity: 1 - outro,
            child: ColoredBox(
              color: background ?? surface,
              child: Center(
                child: _composition == null
                    ? const SizedBox.shrink()
                    : Opacity(
                        opacity: intro,
                        child: Transform.scale(
                          scale: (0.94 + 0.06 * intro) * (1 + 0.05 * outro),
                          child: Lottie(
                            composition: _composition,
                            controller: _logo,
                            width: 220,
                            height: 220,
                            fit: BoxFit.contain,
                          ),
                        ),
                      ),
              ),
            ),
          );
        },
      ),
    );
  }
}
