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


class OtpCodeInput extends StatefulWidget {

  final int length;


  final ValueChanged<String> onChanged;


  final ValueChanged<String>? onCompleted;


  final bool enabled;


  final bool autofocus;


  final Color foreground;


  final Color accent;

  const OtpCodeInput({
    super.key,
    this.length = 6,
    required this.onChanged,
    this.onCompleted,
    this.enabled = true,
    this.autofocus = true,
    this.foreground = Colors.white,
    this.accent = const Color(0xFF1677FF),
  });

  @override
  State<OtpCodeInput> createState() => _OtpCodeInputState();
}

class _OtpCodeInputState extends State<OtpCodeInput> {
  late final List<TextEditingController> _controllers;
  late final List<FocusNode> _nodes;

  @override
  void initState() {
    super.initState();
    _controllers = List.generate(widget.length, (_) => TextEditingController());
    _nodes = List.generate(widget.length, (_) {
      final node = FocusNode();
      node.addListener(() {
        if (node.hasFocus) {
          final i = _nodes.indexOf(node);
          final c = _controllers[i];
          c.selection = TextSelection(
            baseOffset: 0,
            extentOffset: c.text.length,
          );
        }
        if (mounted) setState(() {});
      });
      return node;
    });
  }

  @override
  void dispose() {
    for (final c in _controllers) {
      c.dispose();
    }
    for (final n in _nodes) {
      n.dispose();
    }
    super.dispose();
  }

  String get _value => _controllers.map((c) => c.text).join();

  void _emit() {
    final v = _value;
    widget.onChanged(v);
    if (v.length == widget.length) widget.onCompleted?.call(v);
  }


  void _spread(int startIndex, String digits) {
    var idx = startIndex;
    for (final ch in digits.split('')) {
      if (idx >= widget.length) break;
      _controllers[idx].text = ch;
      idx++;
    }
    final focusIndex = idx >= widget.length ? widget.length - 1 : idx;
    _nodes[focusIndex].requestFocus();
    _emit();
  }

  void _onChanged(int index, String raw) {
    final digits = raw.replaceAll(RegExp(r'\D'), '');
    if (digits.isEmpty) {
      _controllers[index].text = '';
      _emit();
      return;
    }
    if (digits.length == 1) {
      final c = _controllers[index];
      c.text = digits;
      c.selection = TextSelection.collapsed(offset: c.text.length);
      if (index < widget.length - 1) _nodes[index + 1].requestFocus();
      _emit();
    } else {
      _spread(index, digits);
    }
  }

  KeyEventResult _onKey(int index, KeyEvent event) {
    if (event is KeyDownEvent &&
        event.logicalKey == LogicalKeyboardKey.backspace &&
        _controllers[index].text.isEmpty &&
        index > 0) {
      _controllers[index - 1].text = '';
      _nodes[index - 1].requestFocus();
      _emit();
      return KeyEventResult.handled;
    }
    return KeyEventResult.ignored;
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: List.generate(widget.length, (i) {
        final focused = _nodes[i].hasFocus;
        final filled = _controllers[i].text.isNotEmpty;
        final borderColor = focused
            ? widget.accent
            : widget.foreground.withValues(alpha: filled ? 0.45 : 0.18);
        return Padding(
          padding: const EdgeInsets.symmetric(horizontal: 5),
          child: SizedBox(
            width: 46,
            height: 56,
            child: Focus(
              canRequestFocus: false,
              skipTraversal: true,
              onKeyEvent: (_, event) => _onKey(i, event),
              child: TextField(
                controller: _controllers[i],
                focusNode: _nodes[i],
                enabled: widget.enabled,
                autofocus: widget.autofocus && i == 0,
                textAlign: TextAlign.center,
                keyboardType: TextInputType.number,
                cursorColor: widget.accent,
                showCursor: true,
                style: TextStyle(
                  color: widget.foreground,
                  fontSize: 22,
                  fontWeight: FontWeight.w600,
                ),
                decoration: InputDecoration(
                  counterText: '',
                  filled: true,
                  fillColor: widget.foreground.withValues(alpha: 0.06),
                  contentPadding: EdgeInsets.zero,
                  enabledBorder: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(10),
                    borderSide: BorderSide(color: borderColor, width: 1.2),
                  ),
                  focusedBorder: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(10),
                    borderSide: BorderSide(color: widget.accent, width: 1.6),
                  ),
                  disabledBorder: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(10),
                    borderSide: BorderSide(color: borderColor, width: 1.2),
                  ),
                ),
                onChanged: (v) => _onChanged(i, v),
              ),
            ),
          ),
        );
      }),
    );
  }
}
