import 'dart:async';

import 'package:flutter/foundation.dart' show kDebugMode;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sms_autofill/sms_autofill.dart';

import 'package:doormile/main.dart';
import 'package:doormile/shared/state/app_state.dart';
import 'package:doormile/core/utils/snackbar_utils.dart';
import 'package:doormile/core/theme/app_colors.dart';
import 'package:doormile/core/theme/app_theme.dart';
import 'package:doormile/core/widgets/common.dart';

class OtpScreen extends StatefulWidget {
  const OtpScreen({super.key});

  @override
  State<OtpScreen> createState() => _OtpScreenState();
}

class _OtpScreenState extends State<OtpScreen> with CodeAutoFill {
  final List<TextEditingController> _controllers =
      List.generate(6, (_) => TextEditingController());
  final List<FocusNode> _nodes = List.generate(6, (_) => FocusNode());
  Timer? _timer;
  int _seconds = 28;
  bool _loading = false;

  @override
  void initState() {
    super.initState();
    _startTimer();
    listenForCode();
    _prefillDebugBypass();
    WidgetsBinding.instance.addPostFrameCallback((_) => _nodes[0].requestFocus());
  }

  /// Debug-only tester shortcut, see [AppState.verifyOtp]. Compiled out of
  /// release builds via kDebugMode.
  Future<void> _prefillDebugBypass() async {
    if (!kDebugMode) return;
    final prefs = await SharedPreferences.getInstance();
    final provider = prefs.getInt('smsDefaultProvider') ?? 0;
    final passKey = prefs.getInt('smsPassKey');
    if (provider != 1 || passKey == null) return;
    if (!mounted || _controllers.any((c) => c.text.isNotEmpty)) return;

    final passKeyStr = passKey.toString().padLeft(6, '0');
    for (int i = 0; i < 6; i++) {
      _controllers[i].text = passKeyStr[i];
    }
    setState(() {});
  }

  @override
  void codeUpdated() {
    if (!mounted) return;
    final digits = (code ?? '').replaceAll(RegExp(r'[^0-9]'), '');
    if (digits.length < 6) return;
    for (int i = 0; i < 6; i++) {
      _controllers[i].text = digits[i];
    }
    setState(() {});
    _verify();
  }

  void _startTimer() {
    _seconds = 28;
    _timer?.cancel();
    _timer = Timer.periodic(const Duration(seconds: 1), (t) {
      if (_seconds == 0) {
        t.cancel();
      } else {
        setState(() => _seconds--);
      }
    });
  }

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

  void _verify() async {
    if (_loading) return;
    FocusScope.of(context).unfocus();
    setState(() => _loading = true);
    
    await context.read<AppState>().verifyOtp(
      _code,
      onSuccess: () {
        if (!mounted) return;
        final state = context.read<AppState>();
        if (state.isResettingPin) {
          Navigator.pushReplacementNamed(context, Routes.resetPin);
        } else {
          Navigator.pushReplacementNamed(context, Routes.setPin);
        }
      },
      onError: (err) {
        if (!mounted) return;
        setState(() => _loading = false);
        SnackbarUtils.showError(context, err);
        for (var c in _controllers) {
          c.clear();
        }
        _nodes[0].requestFocus();
      },
    );
  }

  void _resendOtp() async {
    setState(() => _loading = true);
    await context.read<AppState>().sendOtp(
      context.read<AppState>().phone,
      onSuccess: () {
        if (!mounted) return;
        setState(() => _loading = false);
        _startTimer();
        SnackbarUtils.showSuccess(context, 'OTP Resent');
      },
      onError: (err) {
        if (!mounted) return;
        setState(() => _loading = false);
        SnackbarUtils.showError(context, err);
      },
    );
  }

  void _onChanged(int i, String v) {
    if (v.length > 1) {
      final chars = v.replaceAll(RegExp(r'[^0-9]'), '').split('');
      for (int j = 0; j < 6; j++) {
        _controllers[j].text = j < chars.length ? chars[j] : '';
      }
      _nodes[5].requestFocus();
      setState(() {});
      if (_code.length == 6) _verify();
      return;
    }
    if (v.isNotEmpty && i < 5) _nodes[i + 1].requestFocus();
    if (v.isEmpty && i > 0) _nodes[i - 1].requestFocus();
    setState(() {});
    if (_code.length == 6) _verify();
  }

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

  @override
  Widget build(BuildContext context) {
    final phone = context.watch<AppState>().phone;
    final filled = _code.length == 6;
    return Scaffold(
      backgroundColor: AppColors.surface,
      appBar: AppBar(
        leading: BackButton(color: AppColors.primary, onPressed: () => Navigator.pop(context)),
      ),
      body: SafeArea(
        child: Center(
          child: SingleChildScrollView(
            padding: const EdgeInsets.symmetric(horizontal: 20),
            child: ConstrainedBox(
              constraints: const BoxConstraints(maxWidth: 400),
              child: AppCard(
                padding: const EdgeInsets.all(28),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Container(
                    width: 88,
                    height: 88,
                    decoration: const BoxDecoration(
                        color: AppColors.primaryFixed, shape: BoxShape.circle),
                    child: const Icon(Icons.sms_rounded, size: 40, color: AppColors.primary),
                  ),
                  const SizedBox(height: 24),
                  Text('Verify your number',
                      textAlign: TextAlign.center, style: AppTheme.headlineLg),
                  const SizedBox(height: 8),
                  Text.rich(
                    TextSpan(
                      style: AppTheme.bodyMd.copyWith(color: AppColors.onSurfaceVariant),
                      children: [
                        const TextSpan(text: 'We sent a 6-digit code to '),
                        TextSpan(
                          text: '+91 $phone',
                          style: AppTheme.labelMd,
                        ),
                      ],
                    ),
                    textAlign: TextAlign.center,
                  ),
                  const SizedBox(height: 28),
                  Row(
                    children: List.generate(
                      6,
                      (i) => Expanded(
                        child: Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 3),
                          child: _OtpBox(
                            controller: _controllers[i],
                            node: _nodes[i],
                            onChanged: (v) => _onChanged(i, v),
                          ),
                        ),
                      ),
                    ),
                  ),
                  const SizedBox(height: 28),
                  if (_seconds > 0)
                    Text('Resend code in 0:${_seconds.toString().padLeft(2, '0')}',
                        style: AppTheme.labelMd.copyWith(color: AppColors.onSurfaceVariant))
                  else
                    TextButton(
                      onPressed: _resendOtp,
                      child: Text('Resend code now',
                          style: AppTheme.labelMd
                              .copyWith(color: AppColors.primary, fontWeight: FontWeight.w700)),
                    ),
                  const SizedBox(height: 24),
                  PrimaryButton(
                    label: 'Verify & Continue',
                    trailingIcon: Icons.arrow_forward,
                    loading: _loading,
                    onPressed: filled ? _verify : null,
                  ),
                ],
              ),
            ),
          ),
        ),
        ),
      ),
    );
  }
}

class _OtpBox extends StatelessWidget {
  final TextEditingController controller;
  final FocusNode node;
  final ValueChanged<String> onChanged;
  const _OtpBox({required this.controller, required this.node, required this.onChanged});

  @override
  Widget build(BuildContext context) {
    final filled = controller.text.isNotEmpty;
    return SizedBox(
      height: 56,
      child: TextField(
        controller: controller,
        focusNode: node,
        onChanged: onChanged,
        textAlign: TextAlign.center,
        keyboardType: TextInputType.number,
        maxLength: 6,
        autofillHints: const [AutofillHints.oneTimeCode],
        cursorColor: AppColors.primary,
        style: AppTheme.headlineMd,
        inputFormatters: [FilteringTextInputFormatter.digitsOnly],
        decoration: InputDecoration(
          counterText: '',
          filled: true,
          contentPadding: EdgeInsets.zero,
          fillColor: filled ? AppColors.primaryFixed.withValues(alpha: 0.3) : AppColors.surface,
          enabledBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(12),
            borderSide: const BorderSide(color: AppColors.outlineVariant),
          ),
          focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(12),
            borderSide: const BorderSide(color: AppColors.primary, width: 2),
          ),
        ),
      ),
    );
  }
}
