import 'package:flutter/material.dart';

import 'package:pshared/models/payment/asset.dart';
import 'package:pshared/models/payment/chain_network.dart';
import 'package:pshared/models/payment/methods/crypto_address.dart';
import 'package:pshared/utils/l10n/chain.dart';

import 'package:pweb/utils/text_field_styles.dart';

import 'package:pweb/generated/i18n/app_localizations.dart';


class CryptoAddressForm extends StatefulWidget {
  final void Function(CryptoAddressPaymentMethod) onChanged;
  final CryptoAddressPaymentMethod? initialData;
  final bool isEditable;

  const CryptoAddressForm({
    super.key,
    required this.onChanged,
    this.initialData,
    required this.isEditable,
  });

  @override
  State<CryptoAddressForm> createState() => _CryptoAddressFormState();
}

class _CryptoAddressFormState extends State<CryptoAddressForm> {
  final _formKey = GlobalKey<FormState>();

  late TextEditingController _addressCtrl;
  late TextEditingController _tokenCtrl;
  late TextEditingController _contractCtrl;
  late TextEditingController _memoCtrl;
  late ChainNetwork _chain;

  @override
  void initState() {
    super.initState();
    final initial = widget.initialData;
    _chain = initial?.asset?.chain ?? ChainNetwork.unspecified;
    _addressCtrl = TextEditingController(text: initial?.address ?? '');
    _tokenCtrl = TextEditingController(text: initial?.asset?.tokenSymbol ?? '');
    _contractCtrl = TextEditingController(text: initial?.asset?.contractAddress ?? '');
    _memoCtrl = TextEditingController(text: initial?.memo ?? '');

    WidgetsBinding.instance.addPostFrameCallback((_) => _emitIfValid());
  }

  bool get _hasChainSelection => _chain != ChainNetwork.unspecified;

  String? _validateAddress(AppLocalizations l10n, String? value) {
    if (value == null || value.trim().isEmpty) return l10n.enterCryptoAddress;
    return null;
  }

  String? _validateToken(AppLocalizations l10n) {
    final token = _tokenCtrl.text.trim();
    final contract = _contractCtrl.text.trim();
    if ((_hasChainSelection || contract.isNotEmpty) && token.isEmpty) {
      return l10n.tokenSymbolRequiredWhenNetwork;
    }
    return null;
  }

  PaymentAsset? _buildAsset() {
    final token = _tokenCtrl.text.trim();
    final contract = _contractCtrl.text.trim();

    if (token.isEmpty && contract.isEmpty && !_hasChainSelection) return null;
    if (token.isEmpty) return null;

    return PaymentAsset(
      chain: _chain,
      tokenSymbol: token,
      contractAddress: contract.isNotEmpty ? contract : null,
    );
  }

  void _emitIfValid() {
    if (!(_formKey.currentState?.validate() ?? false)) return;

    widget.onChanged(
      CryptoAddressPaymentMethod(
        asset: _buildAsset(),
        address: _addressCtrl.text.trim(),
        memo: _memoCtrl.text.trim().isNotEmpty ? _memoCtrl.text.trim() : null,
      ),
    );
  }

  @override
  void didUpdateWidget(covariant CryptoAddressForm oldWidget) {
    super.didUpdateWidget(oldWidget);
    final newData = widget.initialData;
    final oldData = oldWidget.initialData;

    if (newData == null && oldData != null) {
      _addressCtrl.clear();
      _tokenCtrl.clear();
      _contractCtrl.clear();
      _memoCtrl.clear();
      _chain = ChainNetwork.unspecified;
      return;
    }

    if (newData != null && newData != oldData) {
      final hasAddressChange = newData.address != _addressCtrl.text;
      final hasTokenChange = newData.asset?.tokenSymbol != _tokenCtrl.text;
      final hasContractChange = newData.asset?.contractAddress != _contractCtrl.text;
      final hasMemoChange = newData.memo != _memoCtrl.text;
      final hasChainChange = newData.asset?.chain != _chain;

      if (hasAddressChange) _addressCtrl.text = newData.address;
      if (hasTokenChange) _tokenCtrl.text = newData.asset?.tokenSymbol ?? '';
      if (hasContractChange) _contractCtrl.text = newData.asset?.contractAddress ?? '';
      if (hasMemoChange) _memoCtrl.text = newData.memo ?? '';
      if (hasChainChange) _chain = newData.asset?.chain ?? ChainNetwork.unspecified;

      if (hasAddressChange || hasTokenChange || hasContractChange || hasMemoChange || hasChainChange) {
        WidgetsBinding.instance.addPostFrameCallback((_) => _emitIfValid());
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;

    return Form(
      key: _formKey,
      onChanged: _emitIfValid,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        spacing: 12.0,
        children: [
          TextFormField(
            readOnly: !widget.isEditable,
            controller: _addressCtrl,
            decoration: getInputDecoration(context, l10n.cryptoAddressLabel, widget.isEditable),
            style: getTextFieldStyle(context, widget.isEditable),
            validator: (val) => _validateAddress(l10n, val),
          ),
          DropdownButtonFormField<ChainNetwork>(
            initialValue: _chain,
            decoration: getInputDecoration(context, l10n.walletTopUpNetworkLabel, widget.isEditable),
            items: ChainNetwork.values
              .map((chain) => DropdownMenuItem(
                    value: chain,
                    child: Text(chain.localizedName(context)),
                  ))
              .toList(),
            onChanged: widget.isEditable
              ? (value) {
                  if (value == null) return;
                  setState(() => _chain = value);
                  _emitIfValid();
                }
              : null,
          ),
          TextFormField(
            readOnly: !widget.isEditable,
            controller: _tokenCtrl,
            decoration: getInputDecoration(context, l10n.tokenSymbolLabel, widget.isEditable),
            style: getTextFieldStyle(context, widget.isEditable),
            validator: (_) => _validateToken(l10n),
          ),
          TextFormField(
            readOnly: !widget.isEditable,
            controller: _contractCtrl,
            decoration: getInputDecoration(context, l10n.contractAddressLabel, widget.isEditable),
            style: getTextFieldStyle(context, widget.isEditable),
          ),
          TextFormField(
            readOnly: !widget.isEditable,
            controller: _memoCtrl,
            decoration: getInputDecoration(context, l10n.memoLabel, widget.isEditable),
            style: getTextFieldStyle(context, widget.isEditable),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _addressCtrl.dispose();
    _tokenCtrl.dispose();
    _contractCtrl.dispose();
    _memoCtrl.dispose();
    super.dispose();
  }
}
