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

/// S3a — WhatsApp input screen.
///
/// Visual contract is `Figma/screens/onboarding.jsx::S3Phone`:
///   - HaloStepDots at the top (step 3 of 4: S2 Nama → S5 ESP → S5b USP → S3a)
///   - Personalised display-title `"nomor wa-mu, {name}?"`
///   - +62 prefix as static chip; user types only the trailing digits
///   - Privacy reassurance card
///   - Primary CTA `"kirim kode"` (disabled until ≥9 digits)
///   - Ghost link `"lanjut tanpa verifikasi (harga normal)"` → anonymous path
///
/// Two callers route here:
///   1. New-user verified onboarding (USP → here) — auth state has the
///      anonymous display_name set by S2.
///   2. SHome1st "masuk →" banner for returning-user recovery — auth state
///      is initial; the name greeting falls back to "kamu".
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 from /otp/request 429s. Backend embeds
  // retry_after_seconds in the AuthErrorInfo so we can disable the CTA
  // until the next slot opens.
  int _lockoutSeconds = 0;
  Timer? _lockoutTimer;
  String? _errorMessage;

  @override
  void initState() {
    super.initState();
    _phoneController.addListener(() => setState(() {}));
    _authSub =
        ref.listenManual<AsyncValue<AuthData>>(authProvider, (prev, next) {
      if (!mounted) return;
      final data = next.valueOrNull;
      if (data is AuthOtpSentData) {
        // go (replace) so re-submitting the form doesn't stack OtpScreens
        // with leftover listeners.
        context.go('/auth/otp', extra: _e164Phone());
        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();
      });
    });
  }

  /// Subscriber digits with leading zeros stripped. Users commonly type
  /// `0812…` (local format); the backend wants `+62812…`, so the 0 must go.
  String _subscriberDigits() {
    final digits = _phoneController.text.replaceAll(RegExp(r'\D'), '');
    return digits.replaceFirst(RegExp(r'^0+'), '');
  }

  /// Local digits (no country code) → E.164 string the backend expects.
  String _e164Phone() => '+62${_subscriberDigits()}';

  String _greetingName(AuthData? data) => switch (data) {
        AuthAnonymousData d => d.displayName,
        AuthAuthenticatedData d => (d.profile['display_name'] as String?) ?? '',
        AuthNeedsDisplayNameData d =>
          (d.profile['display_name'] as String?) ?? '',
        _ => '',
      };

  @override
  Widget build(BuildContext context) {
    final authState = ref.watch(authProvider);
    final isLoading = authState is AsyncLoading;
    final isLockedOut = _lockoutSeconds > 0;
    final hasMinDigits = _subscriberDigits().length >= 9;
    final canSubmit = hasMinDigits && !isLoading && !isLockedOut;

    final name = _greetingName(authState.valueOrNull);
    final shownName = name.isEmpty ? 'kamu' : name;

    return Scaffold(
      backgroundColor: HaloTokens.bg,
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.fromLTRB(28, 8, 28, 28),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              const Padding(
                padding: EdgeInsets.only(top: 8, bottom: 8),
                child: HaloStepDots(total: 4, current: 3),
              ),
              Expanded(
                child: LayoutBuilder(
                  builder: (context, constraints) => SingleChildScrollView(
                    child: ConstrainedBox(
                      constraints:
                          BoxConstraints(minHeight: constraints.maxHeight),
                      child: IntrinsicHeight(
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.stretch,
                          children: [
                            Text(
                              'nomor wa-mu, $shownName?',
                              style: const TextStyle(
                                fontFamily: HaloTokens.fontDisplay,
                                fontSize: 28,
                                fontWeight: FontWeight.w700,
                                color: HaloTokens.brandDark,
                                height: 1.15,
                                letterSpacing: -0.56,
                              ),
                            ),
                            const SizedBox(height: 10),
                            const Text(
                              'supaya bisa lanjut kapan aja, dan dapat harga khusus pengguna baru.',
                              style: TextStyle(
                                fontFamily: HaloTokens.fontBody,
                                fontSize: 14.5,
                                color: HaloTokens.inkSoft,
                                height: 1.5,
                              ),
                            ),
                            const SizedBox(height: 24),
                            _PhoneRow(
                              controller: _phoneController,
                              borderColor: hasMinDigits
                                  ? HaloTokens.brand
                                  : HaloTokens.border,
                            ),
                            const SizedBox(height: 16),
                            const _PrivacyCard(),
                            if (_errorMessage != null) ...[
                              const SizedBox(height: 12),
                              Text(
                                _errorMessage!,
                                textAlign: TextAlign.center,
                                style: const TextStyle(
                                  fontFamily: HaloTokens.fontBody,
                                  color: HaloTokens.danger,
                                  fontSize: 13,
                                ),
                              ),
                            ],
                          ],
                        ),
                      ),
                    ),
                  ),
                ),
              ),
              HaloButton(
                label: isLoading
                    ? 'memproses...'
                    : isLockedOut
                        ? 'coba lagi dalam ${formatCountdown(_lockoutSeconds)}'
                        : 'kirim kode',
                fullWidth: true,
                onPressed: canSubmit
                    ? () =>
                        ref.read(authProvider.notifier).requestOtp(_e164Phone())
                    : null,
              ),
              const SizedBox(height: 4),
              TextButton(
                onPressed: isLoading
                    ? null
                    // Skip ESPb/USPb — the verified branch already ran ESPa+USPa,
                    // so the redirect alias drops the user straight at PickMethod.
                    : () => context.go('/onboarding/anon/method'),
                style: TextButton.styleFrom(
                  foregroundColor: HaloTokens.inkSoft,
                  minimumSize: const Size(0, 40),
                ),
                child: const Text(
                  'lanjut tanpa verifikasi (harga normal)',
                  style: TextStyle(
                    fontFamily: HaloTokens.fontBody,
                    fontSize: 12.5,
                    decoration: TextDecoration.underline,
                    decorationColor: HaloTokens.inkSoft,
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class _PhoneRow extends StatelessWidget {
  final TextEditingController controller;
  final Color borderColor;
  const _PhoneRow({required this.controller, required this.borderColor});

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 60,
      padding: const EdgeInsets.symmetric(horizontal: 18),
      decoration: BoxDecoration(
        color: HaloTokens.surface,
        borderRadius: HaloRadius.lg,
        border: Border.all(color: borderColor, width: 1.5),
      ),
      child: Row(
        children: [
          const Text(
            '🇮🇩 +62',
            style: TextStyle(
              fontFamily: HaloTokens.fontBody,
              fontSize: 15,
              fontWeight: FontWeight.w600,
              color: HaloTokens.ink,
            ),
          ),
          const SizedBox(width: 12),
          Expanded(
            child: TextField(
              controller: controller,
              keyboardType: TextInputType.phone,
              inputFormatters: [FilteringTextInputFormatter.digitsOnly],
              maxLength: 13, // enough headroom for 12-digit ID mobiles
              style: const TextStyle(
                fontFamily: HaloTokens.fontBody,
                fontSize: 16,
                fontWeight: FontWeight.w500,
                color: HaloTokens.ink,
              ),
              decoration: const InputDecoration(
                hintText: '812 3456 7890',
                hintStyle: TextStyle(
                  fontFamily: HaloTokens.fontBody,
                  fontSize: 16,
                  fontWeight: FontWeight.w500,
                  color: HaloTokens.inkMuted,
                ),
                // Override the app-wide inputDecorationTheme so the input
                // sits flush inside the outer pill — no fill, no border.
                filled: false,
                border: InputBorder.none,
                enabledBorder: InputBorder.none,
                focusedBorder: InputBorder.none,
                errorBorder: InputBorder.none,
                focusedErrorBorder: InputBorder.none,
                disabledBorder: InputBorder.none,
                isCollapsed: true,
                counterText: '',
                contentPadding: EdgeInsets.symmetric(vertical: 18),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _PrivacyCard extends StatelessWidget {
  const _PrivacyCard();

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        color: HaloTokens.brandSofter,
        borderRadius: HaloRadius.md,
        border: Border.all(color: HaloTokens.brandSoft),
      ),
      child: const Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('🛡️', style: TextStyle(fontSize: 14)),
          SizedBox(width: 10),
          Expanded(
            child: Text(
              'anonim — bestie cuma tau nama panggilan kamu. nomor gak akan dishare.',
              style: TextStyle(
                fontFamily: HaloTokens.fontBody,
                fontSize: 12,
                color: HaloTokens.brandDark,
                height: 1.45,
              ),
            ),
          ),
        ],
      ),
    );
  }
}
