import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../../core/auth/auth_notifier.dart';
import '../../../core/auth/auth_providers_provider.dart';
import '../../../core/constants.dart';
import '../../../core/theme/halo_tokens.dart';
import '../../../core/theme/widgets/widgets.dart';

class RegisterScreen extends ConsumerStatefulWidget {
  const RegisterScreen({super.key});

  @override
  ConsumerState<RegisterScreen> createState() => _RegisterScreenState();
}

class _RegisterScreenState extends ConsumerState<RegisterScreen> {
  final _phoneController = TextEditingController();
  ProviderSubscription<AsyncValue<AuthData>>? _authSub;

  // Server-imposed lockout: when /otp/request returns 429, the backend
  // includes retry_after_seconds. We disable "Kirim OTP" for that window.
  int _lockoutSeconds = 0;
  Timer? _lockoutTimer;
  String? _errorMessage;

  @override
  void initState() {
    super.initState();
    _authSub = ref.listenManual<AsyncValue<AuthData>>(authProvider, (prev, next) {
      if (!mounted) return;
      final data = next.valueOrNull;
      if (data is AuthOtpSentData) {
        // Use go (replace) so re-submitting the phone form doesn't stack
        // multiple OtpScreen instances with active listeners.
        context.go('/auth/otp', extra: _phoneController.text.trim());
        return;
      }
      if (next is AsyncError) {
        final err = next.error;
        setState(() => _errorMessage = err.toString());
        if (err is AuthErrorInfo &&
            err.retryAfterSeconds != null &&
            (err.code == 'OTP_COOLDOWN' ||
                err.code == 'OTP_RATE_LIMIT_PHONE' ||
                err.code == 'OTP_RATE_LIMIT_IP')) {
          _startLockout(err.retryAfterSeconds!);
        }
      } else if (next is AsyncData) {
        if (_errorMessage != null) setState(() => _errorMessage = null);
      }
    });
  }

  @override
  void dispose() {
    _authSub?.close();
    _lockoutTimer?.cancel();
    _phoneController.dispose();
    super.dispose();
  }

  void _startLockout(int seconds) {
    _lockoutTimer?.cancel();
    setState(() => _lockoutSeconds = seconds);
    _lockoutTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
      if (!mounted) {
        timer.cancel();
        return;
      }
      setState(() {
        if (_lockoutSeconds > 0) _lockoutSeconds--;
        if (_lockoutSeconds <= 0) timer.cancel();
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    final authState = ref.watch(authProvider);
    final isLoading = authState is AsyncLoading;
    final isLockedOut = _lockoutSeconds > 0;
    final canSubmit = !isLoading && !isLockedOut;
    final providersAsync = ref.watch(authProvidersProvider);
    final providers =
        providersAsync.valueOrNull ?? AuthProvidersConfig.fallback;

    return Scaffold(
      appBar: AppBar(title: const Text('Masuk / Daftar')),
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(HaloSpacing.s24),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              if (providers.hasAnySocial) ...[
                if (providers.google) ...[
                  HaloButton(
                    label: 'lanjut dengan Google',
                    icon: const Icon(Icons.g_mobiledata),
                    variant: HaloButtonVariant.secondary,
                    fullWidth: true,
                    onPressed: isLoading
                        ? null
                        : () => ref.read(authProvider.notifier).loginGoogle(),
                  ),
                  const SizedBox(height: HaloSpacing.s12),
                ],
                if (providers.apple) ...[
                  HaloButton(
                    label: 'lanjut dengan Apple',
                    icon: const Icon(Icons.apple),
                    variant: HaloButtonVariant.secondary,
                    fullWidth: true,
                    onPressed: isLoading
                        ? null
                        : () => ref.read(authProvider.notifier).loginApple(),
                  ),
                  const SizedBox(height: HaloSpacing.s12),
                ],
                const Padding(
                  padding: EdgeInsets.symmetric(vertical: HaloSpacing.s16),
                  child: Row(
                    children: [
                      Expanded(child: Divider(color: HaloTokens.border)),
                      Padding(
                        padding:
                            EdgeInsets.symmetric(horizontal: HaloSpacing.s12),
                        child: Text(
                          'atau',
                          style: TextStyle(
                            fontFamily: HaloTokens.fontBody,
                            color: HaloTokens.inkMuted,
                            fontSize: 13,
                          ),
                        ),
                      ),
                      Expanded(child: Divider(color: HaloTokens.border)),
                    ],
                  ),
                ),
              ],
              TextField(
                controller: _phoneController,
                decoration: const InputDecoration(
                  labelText: 'Nomor HP',
                  hintText: '+628xxxxxxxxxx',
                ),
                keyboardType: TextInputType.phone,
              ),
              const SizedBox(height: HaloSpacing.s16),
              HaloButton(
                label: isLoading
                    ? 'memproses...'
                    : isLockedOut
                        ? 'coba lagi dalam ${formatCountdown(_lockoutSeconds)}'
                        : 'kirim OTP',
                fullWidth: true,
                onPressed: canSubmit
                    ? () {
                        final phone = _phoneController.text.trim();
                        if (phone.isEmpty) return;
                        ref.read(authProvider.notifier).requestOtp(phone);
                      }
                    : null,
              ),
              if (_errorMessage != null) ...[
                const SizedBox(height: HaloSpacing.s12),
                Text(
                  _errorMessage!,
                  textAlign: TextAlign.center,
                  style: const TextStyle(
                    fontFamily: HaloTokens.fontBody,
                    color: HaloTokens.danger,
                    fontSize: 13,
                  ),
                ),
              ],
            ],
          ),
        ),
      ),
    );
  }
}
