// lib/screens/auth/otp.dart
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sms_autofill/sms_autofill.dart';
import 'package:pinput/pinput.dart';

// your localization & theme
import 'package:fl_sevengen_society_user_app/localization/localization_const.dart';
import 'package:fl_sevengen_society_user_app/theme/theme.dart';

class OTPScreen extends StatefulWidget {
  /// Phone number in E.164 format (e.g. +9190xxxxxxxx)
  final String phoneNumber;

  /// OPTIONAL: old flow – verificationId from previous screen.
  /// If null, this screen will call `verifyPhoneNumber` itself.
  final String? verificationId;

  /// Optional callback on verified
  final VoidCallback? onVerified;

  const OTPScreen({
    super.key,
    required this.phoneNumber,
    this.verificationId,
    this.onVerified,
  });

  @override
  State<OTPScreen> createState() => _OTPScreenState();
}

class _OTPScreenState extends State<OTPScreen> with CodeAutoFill {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final TextEditingController _pinController = TextEditingController();

  Timer? countdownTimer;
  Duration myDuration = const Duration(minutes: 2);

  String? _verificationId;
  int? _resendToken;
  bool _loading = false;

  /// prevent multiple success flows (auto-read + manual tap)
  bool _handled = false;

  static const String _backendLoginUrl =
      'https://rmbferodeunited.in/api/login.php'; // <-- your backend URL

  @override
  void initState() {
    super.initState();
    print('DEBUG: OTPScreen initState for phone ${widget.phoneNumber}');
    startTimer();

    // Take verificationId from previous screen, if provided
    _verificationId = widget.verificationId;

    // Start listening for SMS autofill (Android)
    _listenForSms();

    if (widget.verificationId != null) {
      // Old flow: login.dart already called verifyPhoneNumber
      print(
          'DEBUG: Using passed verificationId from previous screen: ${widget.verificationId}');
    } else {
      // New flow: this screen starts verification & auto-read
      print('DEBUG: No verificationId passed, starting phone verification here.');
      _startPhoneVerification();
    }
  }

  // ================== SMS AUTOFILL LISTEN ==================
  // We use sms_autofill's CodeAutoFill mixin to receive incoming codes.
  // If an SMS with the code arrives, the package will call `codeUpdated`.
  void _listenForSms() async {
    try {
      await SmsAutoFill().listenForCode();
      // also register CodeAutoFill (mix-in). The mixin already registers on init.
      listenForCode();
      print('DEBUG: sms_autofill: listening for SMS code.');
    } catch (e, st) {
      print('DEBUG: sms_autofill listen failed -> $e');
      print(st.toString());
    }
  }

  @override
  void codeUpdated() {
    // fixed: don't shadow the `code` field; use a different local variable name
    final String? detectedCode = this.code ?? _pinController.text;

    if (detectedCode != null && detectedCode.length >= 4) {
      // prefer exact length 6
      if (detectedCode.length == 6) {
        print('DEBUG: codeUpdated auto-filled code=$detectedCode');
        _pinController.text = detectedCode;
        // automatically trigger verify
        _verifyCode(detectedCode);
      } else {
        // fill controller but wait until complete length
        _pinController.text = detectedCode;
        print('DEBUG: codeUpdated filled partial code=$detectedCode');
      }
    }
  }

  // ================== TIMER ==================
  void startTimer() {
    print('DEBUG: startTimer called');
    countdownTimer =
        Timer.periodic(const Duration(seconds: 1), (_) => setCountDown());
  }

  void stopTimer() {
    print('DEBUG: stopTimer called');
    if (countdownTimer != null && countdownTimer!.isActive) {
      countdownTimer!.cancel();
    }
  }

  void resetTimer() {
    print('DEBUG: resetTimer called');
    stopTimer();
    setState(() => myDuration = const Duration(minutes: 2));
  }

  void setCountDown() {
    const reduceSecondsBy = 1;
    if (!mounted) return;

    setState(() {
      final seconds = myDuration.inSeconds - reduceSecondsBy;
      if (seconds < 0) {
        print('DEBUG: timer finished');
        countdownTimer?.cancel();
      } else {
        myDuration = Duration(seconds: seconds);
      }
    });
  }

  // ================== PHONE VERIFICATION (FIREBASE OTP) ==================
  Future<void> _startPhoneVerification() async {
    print(
        'DEBUG: _startPhoneVerification called for ${widget.phoneNumber}, resendToken=$_resendToken');

    try {
      await _auth.verifyPhoneNumber(
        phoneNumber: widget.phoneNumber,
        timeout: const Duration(seconds: 60),
        forceResendingToken: _resendToken,
        verificationCompleted: (PhoneAuthCredential credential) async {
          // Auto-retrieval or instant verification
          if (_handled) {
            print('DEBUG: verificationCompleted called but already handled.');
            return;
          }

          final smsCode = credential.smsCode;
          print('DEBUG: verificationCompleted; smsCode=$smsCode');

          if (smsCode != null) {
            // Auto-fill text field
            _pinController.text = smsCode;
            print('DEBUG: Auto-filled Pinput with smsCode: $smsCode');

            // Also run verify flow
            await _verifyCode(smsCode, credential: credential);
          } else {
            // instant verification without code
            print('DEBUG: Instant verification (no smsCode). Signing in directly.');
            await _signInWithCredential(credential);
          }
        },
        verificationFailed: (FirebaseAuthException e) {
          print('DEBUG: verificationFailed -> $e');
          _showSnack(e.message ?? 'Verification failed');
        },
        codeSent: (String verificationId, int? resendToken) {
          print(
              'DEBUG: codeSent; verificationId=$verificationId, resendToken=$resendToken');
          setState(() {
            _verificationId = verificationId;
            _resendToken = resendToken;
          });
        },
        codeAutoRetrievalTimeout: (String verificationId) {
          print(
              'DEBUG: codeAutoRetrievalTimeout; last verificationId=$verificationId');
          _verificationId = verificationId;
        },
      );
    } catch (e, st) {
      print('DEBUG: _startPhoneVerification error -> $e');
      print(st.toString());
      _showSnack('Verification start error: $e');
    }
  }

  // ================== VERIFY & SIGN IN (FIREBASE) ==================
  Future<void> _verifyCode(String code,
      {PhoneAuthCredential? credential}) async {
    if (_handled) {
      print('DEBUG: _verifyCode called but already handled, ignoring.');
      return;
    }

    print('DEBUG: _verifyCode called with code=$code');

    if (code.trim().isEmpty) {
      _showSnack(getTranslate(context, 'otp.enter_code') ?? 'Enter code');
      return;
    }

    if (_verificationId == null && credential == null) {
      print(
          'DEBUG: _verifyCode -> verificationId is null and no credential passed.');
      _showSnack('Verification ID not ready. Please wait or resend OTP.');
      return;
    }

    setState(() => _loading = true);

    try {
      final PhoneAuthCredential finalCredential = credential ??
          PhoneAuthProvider.credential(
            verificationId: _verificationId!,
            smsCode: code.trim(),
          );

      print('DEBUG: Created PhoneAuthCredential, attempting signInWithCredential.');
      await _signInWithCredential(finalCredential);
    } on FirebaseAuthException catch (e, st) {
      print('DEBUG: OTP verify exception -> $e');
      print(st.toString());
      _showSnack(e.message ?? 'Verification error');
    } catch (e, st) {
      print('DEBUG: OTP verify unknown error -> $e');
      print(st.toString());
      _showSnack('Error: $e');
    } finally {
      if (mounted) setState(() => _loading = false);
    }
  }

  Future<void> _signInWithCredential(PhoneAuthCredential credential) async {
    if (_handled) {
      print('DEBUG: _signInWithCredential called but already handled.');
      return;
    }

    print('DEBUG: _signInWithCredential -> signing in with Firebase...');
    final userCredential = await _auth.signInWithCredential(credential);

    if (userCredential.user != null) {
      _handled = true;
      print('DEBUG: Firebase OTP verification succeeded for ${widget.phoneNumber}');

      // 🔹 AFTER Firebase success, hit backend and save to SharedPreferences
      await _loginBackendAndSave();

      // optional callback
      try {
        widget.onVerified?.call();
        print(
            'DEBUG: OTP verified callback invoked for ${widget.phoneNumber}');
      } catch (cbErr, cbSt) {
        print('DEBUG: onVerified callback threw -> $cbErr');
        print(cbSt.toString());
      }

      // Small delay to ensure everything syncs
      await Future.delayed(const Duration(milliseconds: 250));

      if (!mounted) return;

      print('DEBUG: Navigating to /bottomBar and clearing stack');
      Navigator.pushNamedAndRemoveUntil(
        context,
        '/bottomBar',
            (route) => false,
      );
    } else {
      print('DEBUG: userCredential.user is null, verification failed.');
      _showSnack(getTranslate(context, 'otp.verification_failed') ??
          'Verification failed');
    }
  }

  // ================== BACKEND LOGIN + SHARED PREFERENCES ==================

  /// Extract last 10 digits of phone number
  String _local10(String? phone) {
    if (phone == null) return '';
    final digits = phone.replaceAll(RegExp(r'\D'), '');
    if (digits.length <= 10) return digits;
    return digits.substring(digits.length - 10);
  }

  /// Save user object to SharedPreferences
  Future<void> _saveUserToPrefs(dynamic user) async {
    print('DEBUG: _saveUserToPrefs called with user: $user');

    final prefs = await SharedPreferences.getInstance();

    await prefs.setString('name', user['name']?.toString() ?? '');
    await prefs.setString('positions', user['positions']?.toString() ?? '');
    await prefs.setString('rid_no', user['rid_no']?.toString() ?? '');
    await prefs.setString('teams', user['teams']?.toString() ?? '');

    // store photo_image from API response
    await prefs.setString('photo_image', user['photo_image']?.toString() ?? '');

    // NEW: store company_name and business_type from API response
    await prefs.setString('company_name', user['company_name']?.toString() ?? '');
    await prefs.setString(
        'business_type', user['business_type']?.toString() ?? '');

    // phone from backend if available, else from Firebase phoneNumber
    String local = user['phone']?.toString() ?? widget.phoneNumber;
    local = _local10(local);
    await prefs.setString('phone', local);

    print('DEBUG: User saved to SharedPreferences with local phone=$local');
  }

  /// Call your backend login API and save user to prefs
  Future<void> _loginBackendAndSave() async {
    try {
      final localPhone = _local10(widget.phoneNumber);
      print(
          'DEBUG: _loginBackendAndSave called, phone(original)=${widget.phoneNumber}, local10=$localPhone');

      final uri = Uri.parse(_backendLoginUrl);
      print('DEBUG: Backend login URL: $uri');

      final response = await http.post(
        uri,
        body: {
          'phone': localPhone,
          'auth_type': 'firebase_only',
        },
      );

      print(
          'DEBUG: Backend response status=${response.statusCode}, body=${response.body}');

      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        print('DEBUG: Decoded backend JSON: $data');

        if (data is Map &&
            (data['success'] == true || data['status'] == 'success')) {
          final user = data['user'] ?? data['data'];
          if (user != null) {
            await _saveUserToPrefs(user);
          } else {
            print('DEBUG: Backend success but user field is null');
            _showSnack('Login success but user data missing.');
          }
        } else {
          print('DEBUG: Backend login failed with message: ${data['message']}');
          _showSnack(data['message']?.toString() ?? 'Backend login failed.');
        }
      } else {
        _showSnack('Server error: ${response.statusCode}');
      }
    } catch (e, st) {
      print('DEBUG: _loginBackendAndSave error -> $e');
      print(st.toString());
      _showSnack('Backend login error: $e');
    }
  }

  // ================== UI HELPERS ==================
  void _showSnack(String s) {
    print('DEBUG: Snack -> $s');
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(s)));
  }

  @override
  void dispose() {
    print('DEBUG: OTPScreen dispose called');
    _pinController.dispose();
    countdownTimer?.cancel();

    // unregister sms_autofill listener
    try {
      cancel();
      SmsAutoFill().unregisterListener();
      print('DEBUG: sms_autofill: listener unregistered');
    } catch (e) {
      print('DEBUG: error unregistering sms_autofill -> $e');
    }

    super.dispose();
  }

  Widget backbutton(BuildContext context) {
    return IconButton(
      onPressed: () {
        print('DEBUG: Back button pressed, popping OTPScreen');
        Navigator.pop(context);
      },
      padding: (Platform.isIOS)
          ? const EdgeInsets.fromLTRB(
        fixPadding * 2.0,
        fixPadding * 4.0,
        fixPadding * 2.0,
        fixPadding * 2.0,
      )
          : const EdgeInsets.all(fixPadding * 2.0),
      icon: const Icon(Icons.arrow_back, color: black33Color),
    );
  }

  Widget otpField() {
    // Using PinFieldAutoFill so sms_autofill can fill codes automatically on Android.
    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.symmetric(vertical: 8.0),
          child: PinFieldAutoFill(
            controller: _pinController,
            decoration: UnderlineDecoration(
              textStyle: medium20Black33,
              colorBuilder: FixedColorBuilder(black33Color),
              gapSpace: fixPadding / 2,
            ),
            currentCode: _pinController.text,
            codeLength: 6,
            onCodeSubmitted: (code) async {
              print('DEBUG: PinFieldAutoFill onCodeSubmitted code=$code');
              await _verifyCode(code);
            },
            onCodeChanged: (code) {
              print('DEBUG: PinFieldAutoFill onCodeChanged code=$code');
              if (code != null && code.length == 6) {
                // auto trigger verify if code is complete
                _verifyCode(code);
                // dismiss keyboard
                FocusScope.of(context).unfocus();
              }
            },
          ),
        ),
      ],
    );
  }

  Widget verifyButton() {
    return GestureDetector(
      onTap: _loading
          ? null
          : () {
        final code = _pinController.text.trim();
        print('DEBUG: Verify button tapped with code=$code');
        _verifyCode(code);
      },
      child: Container(
        padding: const EdgeInsets.symmetric(
          horizontal: fixPadding * 2.0,
          vertical: fixPadding * 1.5,
        ),
        decoration: BoxDecoration(
          color: primaryColor,
          borderRadius: BorderRadius.circular(10.0),
          boxShadow: [
            BoxShadow(
              color: primaryColor.withOpacity(0.1),
              blurRadius: 12.0,
              offset: const Offset(0, 6),
            ),
          ],
        ),
        alignment: Alignment.center,
        child: _loading
            ? const CupertinoActivityIndicator(color: Colors.white)
            : Text(
          getTranslate(context, 'otp.verify') ?? 'Verify',
          style: semibold18White,
        ),
      ),
    );
  }

  Widget timerWidget() {
    String strDigits(int n) => n.toString().padLeft(2, '0');
    final minutes = strDigits(myDuration.inMinutes.remainder(60));
    final seconds = strDigits(myDuration.inSeconds.remainder(60));

    return Center(
      child: Container(
        padding: const EdgeInsets.symmetric(
          horizontal: fixPadding * 1.5,
          vertical: fixPadding / 2,
        ),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(40.0),
          color: const Color(0xFFD6E9F5),
        ),
        child: Text(
          "$minutes:$seconds",
          style: regular16Black,
        ),
      ),
    );
  }

  Widget resendText() {
    return Text.rich(
      TextSpan(
        text: getTranslate(context, 'otp.didnt_recived') ??
            "Didn't receive the code?",
        style: medium16Primary,
        children: [
          const TextSpan(text: " "),
          TextSpan(
            text: getTranslate(context, 'otp.resend') ?? 'Resend',
            recognizer: TapGestureRecognizer()
              ..onTap = () async {
                print(
                    'DEBUG: Resend tapped, myDuration.inSeconds=${myDuration.inSeconds}');
                if (myDuration.inSeconds == 0) {
                  resetTimer();
                  startTimer();
                  if (widget.verificationId == null) {
                    // New flow: re-call phone verification here
                    print('DEBUG: Resend -> calling _startPhoneVerification');
                    await _startPhoneVerification();
                    _showSnack(
                        getTranslate(context, 'otp.go_back_to_resend') ??
                            'OTP resent');
                  } else {
                    // Old flow: verificationId is managed from previous screen
                    print(
                        'DEBUG: Resend tapped but verificationId is controlled by previous screen. Show message.');
                    _showSnack(
                        getTranslate(context, 'otp.go_back_to_resend') ??
                            'Go back and request resend');
                  }
                }
              },
          ),
        ],
      ),
      textAlign: TextAlign.center,
    );
  }

  // ================== BUILD ==================
  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;

    return Scaffold(
      body: Container(
        height: size.height,
        width: size.width,
        decoration: const BoxDecoration(
          image: DecorationImage(
            image: AssetImage("assets/auth/bg.png"),
            fit: BoxFit.fill,
          ),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            heightSpace,
            height5Space,
            backbutton(context),
            Expanded(
              child: ListView(
                physics: const BouncingScrollPhysics(),
                padding: const EdgeInsets.symmetric(
                  horizontal: fixPadding * 2.0,
                ),
                children: [
                  Text(
                    getTranslate(context, 'otp.OTP_VERIFICATION') ??
                        'OTP VERIFICATION',
                    style: semibold21Primary,
                    textAlign: TextAlign.center,
                  ),
                  heightSpace,
                  Text(
                    getTranslate(context, 'otp.please_text') ??
                        'Please enter the verification code',
                    textAlign: TextAlign.center,
                    style: medium14Grey77,
                  ),
                  heightSpace,
                  heightSpace,
                  heightSpace,
                  heightSpace,
                  height5Space,
                  otpField(),
                  heightSpace,
                  heightSpace,
                  heightSpace,
                  heightSpace,
                  height5Space,
                  timerWidget(),
                  heightSpace,
                  height5Space,
                  verifyButton(),
                  heightSpace,
                  resendText(),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
