import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:lucide_icons_flutter/lucide_icons.dart'; import 'package:intl/intl.dart'; import '../../../../core/widgets/premium_text_field.dart'; import '../../../transactions/providers/providers.dart'; import '../../providers/invoices_provider.dart'; import '../../providers/customers_provider.dart'; import '../../domain/invoice.dart'; class ReceivePaymentSheet extends ConsumerStatefulWidget { final Invoice invoice; const ReceivePaymentSheet({super.key, required this.invoice}); @override ConsumerState createState() => _ReceivePaymentSheetState(); } class _ReceivePaymentSheetState extends ConsumerState { final _formKey = GlobalKey(); late TextEditingController _amountCtrl; String _paymentMethod = 'Cash'; int? _selectedWalletId; bool _isLoading = false; final List> _methods = [ {'key': 'Cash', 'label': 'Cash', 'icon': LucideIcons.banknote}, {'key': 'UPI', 'label': 'UPI', 'icon': LucideIcons.smartphone}, {'key': 'Bank Transfer', 'label': 'Bank Transfer', 'icon': LucideIcons.building2}, {'key': 'Card', 'label': 'Card', 'icon': LucideIcons.creditCard}, ]; @override void initState() { super.initState(); final balance = widget.invoice.totalAmount - widget.invoice.amountPaid; _amountCtrl = TextEditingController( text: balance > 0 ? balance.toStringAsFixed(2) : '0.00', ); } @override void dispose() { _amountCtrl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final isDark = Theme.of(context).brightness == Brightness.dark; final formatCurrency = NumberFormat.currency(symbol: '₹'); final balanceDue = (widget.invoice.totalAmount - widget.invoice.amountPaid).clamp(0.0, double.infinity); final customersState = ref.watch(customersProvider); final customer = customersState.value?.where((c) => c.id == widget.invoice.customerId).firstOrNull; final walletsState = ref.watch(walletProvider); final allWallets = walletsState.value ?? []; final wallets = allWallets.where((w) { if (_paymentMethod == 'Cash') { return w.nature == 'CASH'; } else { return w.nature == 'INCOME' || w.nature == 'SAVINGS'; } }).toList(); if (wallets.isNotEmpty && (_selectedWalletId == null || !wallets.any((w) => w.id == _selectedWalletId))) { _selectedWalletId = wallets.first.id; } return Container( decoration: BoxDecoration( color: isDark ? const Color(0xFF1E293B) : Colors.white, borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.15), blurRadius: 20, offset: const Offset(0, -5), ), ], ), padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom + 20, top: 12, left: 20, right: 20, ), child: SafeArea( top: false, child: Form( key: _formKey, child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Drag Handle Center( child: Container( width: 40, height: 4, decoration: BoxDecoration( color: isDark ? Colors.white24 : Colors.grey.shade300, borderRadius: BorderRadius.circular(2), ), ), ), const SizedBox(height: 14), // Header Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.blue.withValues(alpha: 0.12), borderRadius: BorderRadius.circular(10), ), child: const Icon(LucideIcons.arrowDownLeft, size: 20, color: Colors.blue), ), const SizedBox(width: 12), const Text( 'Receive Payment', style: TextStyle(fontSize: 19, fontWeight: FontWeight.bold), ), ], ), IconButton( icon: const Icon(LucideIcons.x, size: 20), style: IconButton.styleFrom( backgroundColor: isDark ? Colors.white10 : Colors.grey.shade100, ), onPressed: () => Navigator.pop(context), ), ], ), const SizedBox(height: 16), // Invoice Summary Card Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: isDark ? Colors.white.withValues(alpha: 0.04) : Colors.grey.shade50, borderRadius: BorderRadius.circular(14), border: Border.all( color: isDark ? Colors.white10 : Colors.grey.shade200, ), ), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( customer?.name ?? 'Customer', style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14), maxLines: 1, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 2), Text( 'Invoice #${widget.invoice.invoiceNumber}', style: TextStyle( fontSize: 12, color: isDark ? Colors.grey.shade400 : Colors.grey.shade600, ), ), ], ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( 'Balance Due', style: TextStyle( fontSize: 11, fontWeight: FontWeight.w500, color: isDark ? Colors.grey.shade400 : Colors.grey.shade600, ), ), const SizedBox(height: 2), Text( formatCurrency.format(balanceDue), style: const TextStyle( fontSize: 15, fontWeight: FontWeight.bold, color: Colors.deepOrange, ), ), ], ), ], ), ), const SizedBox(height: 18), // Amount Field Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Payment Amount', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600), ), if (balanceDue > 0) InkWell( onTap: () { setState(() { _amountCtrl.text = balanceDue.toStringAsFixed(2); }); }, child: Text( 'Receive Full (${formatCurrency.format(balanceDue)})', style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Colors.blue.shade600, ), ), ), ], ), const SizedBox(height: 8), PremiumTextField( controller: _amountCtrl, labelText: 'Amount Paid (₹)', keyboardType: const TextInputType.numberWithOptions(decimal: true), prefixIcon: const Icon(LucideIcons.indianRupee, size: 18), validator: (val) { if (val == null || val.trim().isEmpty) return 'Required'; final parsed = double.tryParse(val); if (parsed == null || parsed <= 0) return 'Invalid amount'; return null; }, ), const SizedBox(height: 16), // Payment Method Chips const Text( 'Payment Method', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600), ), const SizedBox(height: 8), SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: _methods.map((m) { final isSelected = _paymentMethod == m['key']; return Padding( padding: const EdgeInsets.only(right: 8.0), child: ChoiceChip( avatar: Icon( m['icon'] as IconData, size: 15, color: isSelected ? Colors.white : (isDark ? Colors.grey.shade300 : Colors.grey.shade700), ), label: Text(m['label'] as String), labelStyle: TextStyle( fontSize: 12, fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, color: isSelected ? Colors.white : (isDark ? Colors.grey.shade300 : Colors.grey.shade800), ), selected: isSelected, selectedColor: Colors.blue.shade600, backgroundColor: isDark ? Colors.white.withValues(alpha: 0.05) : Colors.grey.shade100, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), side: BorderSide( color: isSelected ? Colors.blue.shade600 : (isDark ? Colors.white10 : Colors.grey.shade300), width: 0.8, ), ), onSelected: (_) { setState(() { _paymentMethod = m['key'] as String; _selectedWalletId = null; }); }, ), ); }).toList(), ), ), const SizedBox(height: 16), // Receive Into Wallet if (wallets.isNotEmpty) ...[ const Text( 'Receive Into Wallet', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600), ), const SizedBox(height: 8), Container( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 4), decoration: BoxDecoration( color: isDark ? Colors.white.withValues(alpha: 0.04) : Colors.grey.shade50, borderRadius: BorderRadius.circular(12), border: Border.all( color: isDark ? Colors.white12 : Colors.grey.shade300, ), ), child: DropdownButtonHideUnderline( child: DropdownButton( value: _selectedWalletId, isExpanded: true, dropdownColor: isDark ? const Color(0xFF1E293B) : Colors.white, hint: const Text('Select Wallet'), items: wallets .map( (w) => DropdownMenuItem(value: w.id, child: Text(w.name)), ) .toList(), onChanged: (val) => setState(() => _selectedWalletId = val), ), ), ), const SizedBox(height: 22), ] else const SizedBox(height: 8), // Submit Button SizedBox( width: double.infinity, height: 52, child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.blue.shade600, foregroundColor: Colors.white, elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), ), ), onPressed: _isLoading ? null : () async { if (!_formKey.currentState!.validate()) return; final amount = double.tryParse(_amountCtrl.text) ?? 0; if (amount <= 0) return; setState(() => _isLoading = true); try { await ref .read(invoicesProvider.notifier) .addPayment( widget.invoice.id!, InvoicePayment( amount: amount, paymentMethod: _paymentMethod, walletId: _selectedWalletId, ), ); if (mounted) { Navigator.pop( context, true, ); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Payment of ₹${amount.toStringAsFixed(2)} received successfully!'), backgroundColor: Colors.green.shade700, ), ); } } catch (e) { if (mounted) { ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text(e.toString()))); setState(() => _isLoading = false); } } }, child: _isLoading ? const SizedBox( width: 22, height: 22, child: CircularProgressIndicator( color: Colors.white, strokeWidth: 2.5, ), ) : const Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(LucideIcons.checkCircle2, size: 18), SizedBox(width: 8), Text( 'Confirm Payment', style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, ), ), ], ), ), ), ], ), ), ), ), ); } }