import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';

import '../../widgets/image_button.dart';

typedef TokenPasswordSubmit = Future<void> Function({
  required String token,
  required String password,
  required String passwordConfirmation,
});

typedef TokenVerifier = Future<bool> Function(String token);
typedef ErrorMapper = String Function(String rawError);

/// Ecran commun pour les flows mot de passe basés sur un token URL.
class PasswordTokenFormScreen extends StatefulWidget {
  final String? token;
  final String title;
  final String? subtitle;
  final String submitLabel;
  final String successMessage;
  final String invalidTokenTitle;
  final String invalidTokenMessage;
  final TokenPasswordSubmit onSubmit;
  final TokenVerifier? verifyToken;
  final ErrorMapper? mapError;

  const PasswordTokenFormScreen({
    super.key,
    required this.token,
    required this.title,
    this.subtitle,
    required this.submitLabel,
    required this.successMessage,
    required this.invalidTokenTitle,
    this.invalidTokenMessage = 'Lien invalide ou expiré.',
    required this.onSubmit,
    this.verifyToken,
    this.mapError,
  });

  @override
  State<PasswordTokenFormScreen> createState() => _PasswordTokenFormScreenState();
}

class _PasswordTokenFormScreenState extends State<PasswordTokenFormScreen> {
  final _formKey = GlobalKey<FormState>();
  final _passwordCtrl = TextEditingController();
  final _confirmCtrl = TextEditingController();

  bool _checkingToken = false;
  bool _submitting = false;
  bool _tokenValid = false;
  String? _message;

  String get _token => (widget.token ?? '').trim();

  @override
  void initState() {
    super.initState();
    _initTokenState();
  }

  @override
  void dispose() {
    _passwordCtrl.dispose();
    _confirmCtrl.dispose();
    super.dispose();
  }

  void _initTokenState() {
    if (_token.isEmpty) {
      _tokenValid = false;
      _checkingToken = false;
      return;
    }
    if (widget.verifyToken == null) {
      _tokenValid = true;
      _checkingToken = false;
      return;
    }
    _checkingToken = true;
    _verifyToken();
  }

  Future<void> _verifyToken() async {
    try {
      final ok = await widget.verifyToken!(_token);
      if (!mounted) return;
      setState(() {
        _checkingToken = false;
        _tokenValid = ok;
      });
    } catch (e) {
      if (!mounted) return;
      final raw = e.toString().replaceAll('Exception: ', '');
      setState(() {
        _checkingToken = false;
        _tokenValid = false;
        _message = widget.mapError?.call(raw) ?? raw;
      });
    }
  }

  bool _isStrongPassword(String v) {
    if (v.length < 8) return false;
    final hasUpper = RegExp(r'[A-Z]').hasMatch(v);
    final hasDigit = RegExp(r'\d').hasMatch(v);
    return hasUpper && hasDigit;
  }

  String? _validatePassword(String? value) {
    final v = value ?? '';
    if (v.isEmpty) return 'Veuillez saisir un mot de passe.';
    if (!_isStrongPassword(v)) {
      return 'Minimum 8 caractères, avec au moins 1 majuscule et 1 chiffre.';
    }
    return null;
  }

  String? _validateConfirmation(String? value) {
    final v = value ?? '';
    if (v.isEmpty) return 'Veuillez confirmer le mot de passe.';
    if (v != _passwordCtrl.text) return 'Les mots de passe ne correspondent pas.';
    return null;
  }

  Future<void> _submit() async {
    if (_submitting || !_tokenValid) return;
    if (!(_formKey.currentState?.validate() ?? false)) return;
    setState(() {
      _submitting = true;
      _message = null;
    });
    try {
      await widget.onSubmit(
        token: _token,
        password: _passwordCtrl.text,
        passwordConfirmation: _confirmCtrl.text,
      );
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(widget.successMessage, style: GoogleFonts.merienda()),
        ),
      );
      context.go('/login');
    } catch (e) {
      if (!mounted) return;
      final raw = e.toString().replaceAll('Exception: ', '');
      setState(() {
        _submitting = false;
        _message = widget.mapError?.call(raw) ?? raw;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        decoration: const BoxDecoration(
          image: DecorationImage(
            image: AssetImage('assets/images/paper2.png'),
            fit: BoxFit.cover,
            repeat: ImageRepeat.repeat,
          ),
        ),
        child: Center(
          child: ConstrainedBox(
            constraints: const BoxConstraints(maxWidth: 560),
            child: Card(
              color: const Color(0xF4FFFFFF),
              margin: const EdgeInsets.all(24),
              shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
              child: Padding(
                padding: const EdgeInsets.all(24),
                child: _checkingToken
                    ? const Center(child: CircularProgressIndicator())
                    : _tokenValid
                        ? _buildForm(context)
                        : _buildInvalidToken(),
              ),
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildForm(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Text(
            widget.title,
            style: GoogleFonts.merienda(fontSize: 28, fontWeight: FontWeight.w700),
            textAlign: TextAlign.center,
          ),
          if (widget.subtitle != null && widget.subtitle!.trim().isNotEmpty) ...[
            const SizedBox(height: 10),
            Text(
              widget.subtitle!,
              style: GoogleFonts.merienda(fontSize: 14, color: Colors.black87),
              textAlign: TextAlign.center,
            ),
          ],
          const SizedBox(height: 18),
          TextFormField(
            controller: _passwordCtrl,
            obscureText: true,
            textInputAction: TextInputAction.next,
            onFieldSubmitted: (_) => FocusScope.of(context).nextFocus(),
            validator: _validatePassword,
            decoration: const InputDecoration(
              labelText: 'Mot de passe',
              border: OutlineInputBorder(),
            ),
          ),
          const SizedBox(height: 14),
          TextFormField(
            controller: _confirmCtrl,
            obscureText: true,
            textInputAction: TextInputAction.done,
            onFieldSubmitted: (_) => _submit(),
            validator: _validateConfirmation,
            decoration: const InputDecoration(
              labelText: 'Confirmer le mot de passe',
              border: OutlineInputBorder(),
            ),
          ),
          const SizedBox(height: 10),
          Text(
            'Au moins 8 caractères, dont 1 majuscule et 1 chiffre.',
            style: GoogleFonts.merienda(fontSize: 12, color: Colors.black54),
          ),
          if (_message != null) ...[
            const SizedBox(height: 12),
            Text(
              _message!,
              style: GoogleFonts.merienda(
                color: Colors.red.shade700,
                fontSize: 13,
              ),
            ),
          ],
          const SizedBox(height: 16),
          _submitting
              ? const Center(child: CircularProgressIndicator())
              : ImageButton(
                  bg: 'assets/images/bg_green.png',
                  width: double.infinity,
                  height: 44,
                  text: widget.submitLabel,
                  textColor: const Color(0xFF2D6A4F),
                  onPressed: _submit,
                ),
        ],
      ),
    );
  }

  Widget _buildInvalidToken() {
    final msg = _message ?? widget.invalidTokenMessage;
    return Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        Text(
          widget.invalidTokenTitle,
          style: GoogleFonts.merienda(fontSize: 28, fontWeight: FontWeight.w700),
          textAlign: TextAlign.center,
        ),
        const SizedBox(height: 20),
        Text(
          msg,
          style: GoogleFonts.merienda(fontSize: 16),
          textAlign: TextAlign.center,
        ),
        const SizedBox(height: 20),
        ImageButton(
          bg: 'assets/images/bg_green.png',
          width: double.infinity,
          height: 44,
          text: 'Retour à la connexion',
          textColor: const Color(0xFF2D6A4F),
          onPressed: () => context.go('/login'),
        ),
      ],
    );
  }
}
