import '../../../l10n/app_localizations.dart';
import 'dart:math';

// import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:kmobile/di/injection.dart';
import 'package:kmobile/security/secure_storage.dart';
import 'package:local_auth/local_auth.dart';
import 'package:flutter/services.dart';

enum MPinMode { enter, set, confirm }

class MPinScreen extends StatefulWidget {
  final MPinMode mode;
  final String? initialPin;
  final void Function(String pin)? onCompleted;
  final bool disableBiometric;
  final String? customTitle;
  final String? customConfirmTitle;

  const MPinScreen({
    super.key,
    required this.mode,
    this.initialPin,
    this.onCompleted,
    this.disableBiometric = false,
    this.customTitle,
    this.customConfirmTitle,
  });

  @override
  State<MPinScreen> createState() => _MPinScreenState();
}

class _MPinScreenState extends State<MPinScreen> with TickerProviderStateMixin {
  List<String> mPin = [];
  String? errorText;

  // Animation controllers
  late final AnimationController _bounceController;
  late final Animation<double> _bounceAnimation;
  late final AnimationController _shakeController;
  late final AnimationController _waveController;
  late final Animation<double> _waveAnimation;

  // State flags for animations
  bool _isError = false;
  bool _isSuccess = false;

  @override
  void initState() {
    super.initState();
    // Bounce animation for single dot entry
    _bounceController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 150),
    );
    _bounceAnimation = Tween<double>(begin: 1.0, end: 1.2).animate(
      CurvedAnimation(
        parent: _bounceController,
        curve: Curves.elasticIn,
        reverseCurve: Curves.elasticOut,
      ),
    )..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          _bounceController.reverse();
        }
      });

    // Shake animation for error
    _shakeController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 400),
    );

    // Wave animation for success
    _waveController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 800),
    );
    _waveAnimation = Tween<double>(begin: 0, end: 1).animate(
      CurvedAnimation(parent: _waveController, curve: Curves.easeInOut),
    );

    if (widget.mode == MPinMode.enter && !widget.disableBiometric) {
      _tryBiometricBeforePin();
    }
  }

  @override
  void dispose() {
    _bounceController.dispose();
    _shakeController.dispose();
    _waveController.dispose();
    super.dispose();
  }

  Future<void> _tryBiometricBeforePin() async {
    final storage = getIt<SecureStorage>();
    final enabled = await storage.read('biometric_enabled');
    // log('biometric_enabled: $enabled');
    if (enabled != null && enabled) {
      final auth = LocalAuthentication();
      if (await auth.canCheckBiometrics) {
        final didAuth = await auth.authenticate(
          // ignore: use_build_context_synchronously
          localizedReason: AppLocalizations.of(context).authenticateToAccess,
          options: const AuthenticationOptions(biometricOnly: true),
        );
        if (didAuth && mounted) {
          // success → directly “complete” your flow
          widget.onCompleted?.call('');
          // or navigate yourself:
          // Navigator.of(context).pushReplacement(
          //   MaterialPageRoute(builder: (_) => const NavigationScaffold()));
        }
      }
    }
  }

  void addDigit(String digit) {
    if (_shakeController.isAnimating || _waveController.isAnimating) return;
    if (mPin.length < 4) {
      setState(() {
        mPin.add(digit);
        errorText = null;
      });
      _bounceController.forward(from: 0);
      if (mPin.length == 4) {
        _handleComplete();
      }
    }
  }

  void deleteDigit() {
    if (_shakeController.isAnimating || _waveController.isAnimating) return;
    if (mPin.isNotEmpty) {
      setState(() {
        mPin.removeLast();
        errorText = null;
      });
    }
  }

  Future<void> _handleComplete() async {
    if (_shakeController.isAnimating || _waveController.isAnimating) return;

    final pin = mPin.join();
    final storage = SecureStorage();

    switch (widget.mode) {
      case MPinMode.enter:
        final storedPin = await storage.read('mpin');
        // log('storedPin: $storedPin');
        if (storedPin == int.tryParse(pin)) {
          // Correct PIN
          setState(() {
            _isSuccess = true;
            errorText = null;
          });
          await Future.delayed(const Duration(milliseconds: 100));
          _waveController.forward(from: 0).whenComplete(() {
            widget.onCompleted?.call(pin);
          });
        } else {
          // Incorrect PIN
          setState(() {
            _isError = true;
            errorText = AppLocalizations.of(context).incorrectMPIN;
          });
          await _shakeController.forward(from: 0);
          setState(() {
            mPin.clear();
            _isError = false;
            // Keep error text until next digit is entered
          });
        }
        break;
      case MPinMode.set:
        // Navigate to confirm and wait for result
        final result = await Navigator.push(
          context,
          MaterialPageRoute(
            builder: (_) => MPinScreen(
              mode: MPinMode.confirm,
              initialPin: pin,
              onCompleted: (confirmedPin) {
                // Just pop with the pin, don't call parent callback yet
                Navigator.of(context).pop(confirmedPin);
              },
              disableBiometric: widget.disableBiometric,
              customTitle: widget.customConfirmTitle,
            ),
          ),
        );

        // If confirm succeeded, call parent callback
        if (result != null && mounted) {
          widget.onCompleted?.call(result);
        }
        break;
      case MPinMode.confirm:
        if (widget.initialPin == pin) {
          // 1) persist the pin
          await storage.write('mpin', pin);

          // 2) Call the onCompleted callback to let the parent handle navigation
          if (mounted) {
            widget.onCompleted?.call(pin);
          }
        } else {
          setState(() {
            _isError = true;
            errorText = AppLocalizations.of(context).pinsDoNotMatch;
          });
          await _shakeController.forward(from: 0);
          setState(() {
            mPin.clear();
            _isError = false;
          });
        }
        break;
    }
  }

  Widget buildMPinDots(BuildContext context) {
    return AnimatedBuilder(
      animation: Listenable.merge(
          [_bounceController, _shakeController, _waveController]),
      builder: (context, child) {
        double shakeOffset = 0;
        if (_shakeController.isAnimating) {
          // 4 cycles of sine wave for shake
          shakeOffset = sin(_shakeController.value * 4 * pi) * 12;
        }

        return Transform.translate(
          offset: Offset(shakeOffset, 0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: List.generate(4, (index) {
              final isFilled = index < mPin.length;

              // Bounce animation for single dot
              final isAnimatingBounce =
                  index == mPin.length - 1 && _bounceController.isAnimating;
              double bounceScale =
                  isAnimatingBounce ? _bounceAnimation.value : 1.0;

              // Success wave animation
              double waveScale = 1.0;
              if (_isSuccess) {
                final waveDelay = index * 0.15;
                final waveValue =
                    (_waveAnimation.value - waveDelay).clamp(0.0, 1.0);
                // Grow and shrink
                waveScale = 1.0 + sin(waveValue * pi) * 0.4;
              }

              // Determine dot color
              Color dotColor;
              if (_isError) {
                dotColor = Theme.of(context).colorScheme.error;
              } else if (_isSuccess) {
                dotColor = Colors.green.shade600;
              } else {
                dotColor = isFilled
                    ? Theme.of(context).colorScheme.onSurfaceVariant
                    : Theme.of(context).colorScheme.surfaceContainerHighest;
              }

              return Transform.scale(
                scale: bounceScale * waveScale,
                child: Container(
                  margin: const EdgeInsets.all(8),
                  width: 25,
                  height: 25,
                  decoration: BoxDecoration(
                    shape: BoxShape.circle,
                    color: dotColor,
                  ),
                ),
              );
            }),
          ),
        );
      },
    );
  }

  Widget buildNumberPad() {
    List<List<String>> keys = [
      ['1', '2', '3'],
      ['4', '5', '6'],
      ['7', '8', '9'],
      ['Enter', '0', '<'],
    ];

    return Column(
      children: keys.map((row) {
        return Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: row.map((key) {
            return Padding(
              padding: const EdgeInsets.all(1.0),
              child: GestureDetector(
                onTap: () {
                  HapticFeedback.lightImpact();
                  if (key == '<') {
                    deleteDigit();
                  } else if (key == 'Enter') {
                    if (mPin.length == 4) {
                      _handleComplete();
                    } else {
                      setState(() {
                        errorText = AppLocalizations.of(
                          context,
                        ).pleaseEnter4Digits;
                      });
                    }
                  } else if (key.isNotEmpty) {
                    addDigit(key);
                  }
                },
                child: Container(
                  width: 80,
                  height: 80,
                  decoration: const BoxDecoration(
                    shape: BoxShape.circle,
                  ),
                  alignment: Alignment.center,
                  child: key == 'Enter'
                      ? const Icon(Icons.check)
                      : Text(
                          key == '<' ? '⌫' : key,
                          style: TextStyle(
                            fontSize: 30,
                            color: key == 'Enter'
                                ? Theme.of(context).primaryColor
                                : Theme.of(context).colorScheme.onSurface,
                          ),
                        ),
                ),
              ),
            );
          }).toList(),
        );
      }).toList(),
    );
  }

  String getTitle() {
    if (widget.customTitle != null) {
      return widget.customTitle!;
    }
    switch (widget.mode) {
      case MPinMode.enter:
        return AppLocalizations.of(context).enterMPIN;
      case MPinMode.set:
        return AppLocalizations.of(context).setMPIN;
      case MPinMode.confirm:
        return AppLocalizations.of(context).confirmMPIN;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: [
            const SizedBox(height: 50),
            // Logo
            Image.asset('assets/images/logo.png', height: 100),
            const SizedBox(height: 20),
            Text(
              getTitle(),
              style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
            ),
            const Spacer(),
            buildMPinDots(context),
            if (errorText != null)
              Padding(
                padding: const EdgeInsets.only(top: 8.0),
                child: Text(
                  errorText!,
                  style: TextStyle(color: Theme.of(context).colorScheme.error),
                ),
              ),
            const Spacer(),
            buildNumberPad(),
          ],
        ),
      ),
    );
  }
}
