import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';

import '../../../core/services/api_service.dart';
import '../../../data/utils/Pagination.dart';
import '../../../data/utils/toastNotification.dart';
import '../../layouts/main_layout.dart';
import '../../layouts/responsive_layout.dart';
import '../../providers/manager_provider.dart';
import '../../providers/userRoleProvider.dart';
import '../../themes/indicators/date_range_picker_field.dart';
import '../../themes/indicators/search_field_theme.dart';

/// Payout report — layout and styling aligned with [policylist] policy list screen.
class PayoutReportScreen extends ConsumerStatefulWidget {
  const PayoutReportScreen({super.key});

  @override
  ConsumerState<PayoutReportScreen> createState() => _PayoutReportScreenState();
}

class _PayoutReportScreenState extends ConsumerState<PayoutReportScreen> {
  late ApiService apiService;
  int currentPage = 1;
  int itemsPerPage = 10;
  bool isLoading = false;

  final TextEditingController _startController = TextEditingController();
  final TextEditingController _endController = TextEditingController();
  final TextEditingController _searchController = TextEditingController();

  List<Map<String, dynamic>> _rows = [];
  List<Map<String, dynamic>> _filtered = [];
  List<Map<String, dynamic>> _agentOptions = [];
  String? _selectedAgentId;
  /// `null` = "Select Payout Raised" (not chosen). `'all'` | `'yes'` | `'no'` sent to API.
  String? _payoutRaised;

  bool _hasSearched = false;

  /// From API root `count` and `summary.{total,raised,pending}`.
  int? _reportCount;
  num? _summaryTotal;
  num? _summaryRaised;
  num? _summaryPending;

  int? _managerId;

  bool _isAgentRole() {
    final r = (ref.read(userRoleProvider) ?? '').toString().trim().toLowerCase();
    return r == 'agent' || r == 'a';
  }

  /// `received_or_not` equals `no` (case-insensitive).
  bool _receivedIsNo(Map<String, dynamic> item) {
    final v = (item['received_or_not'] ?? '').toString().trim().toLowerCase();
    return v == 'no';
  }

  /// UI / export: capitalize first letter, lowercase the rest (e.g. `yes` → `Yes`).
  String _receivedLabel(dynamic v) {
    final s = v?.toString().trim() ?? '';
    if (s.isEmpty) return '-';
    return s[0].toUpperCase() +
        (s.length > 1 ? s.substring(1).toLowerCase() : '');
  }

  bool _isAccountsReceivedRole() {
    final role = (ref.read(userRoleProvider) ?? '')
        .toString()
        .trim()
        .toLowerCase()
        .replaceAll(RegExp(r'[\s_\-]+'), '');
    return role == 'accountsreceived' || role == 'accounts';
  }

  String _receivedDisplayLabel(dynamic v) {
    final raw = v?.toString().trim().toLowerCase() ?? '';
    if (_isAccountsReceivedRole()) {
      if (raw == 'yes' || raw == 'received' || raw == 'paid') {
        return 'Paid';
      }
    }
    return _receivedLabel(v);
  }

  String? _agentIdForApi() {
    if (_isAgentRole()) {
      final uid = ref.read(userIdProvider);
      return uid?.toString();
    }
    return _selectedAgentId;
  }

  static const _tableHeaderBg = Color(0xFFF1F5F9);
  static const _rowBorder = Color(0xFFEAEAEA);
  /// Pending summary chip + `received_or_not == no` row highlight (same palette).
  static const _pendingChipBg = Color(0xFFFFEBEE);
  static const _pendingChipBorder = Color(0xFFEF9A9A);
  static const _pendingChipValue = Color(0xFFC62828);
  static const _filterStripMobileBg = Color(0xffD9EBE8);
  /// Closed filter fields (light outline, white fill) — first design.
  static const _filterFieldBorder = Color(0xFFE2E8F0);
  static const _filterFocusTeal = Color(0xFF50A398);

  static final _dataBold = GoogleFonts.inter(
    fontSize: 11,
    fontWeight: FontWeight.w400,
    color: const Color(0xFF000000),
  );

  /// Table column titles (policy list: bold header row).
  static final _headerColumn = GoogleFonts.poppins(
    fontSize: 11.2,
    fontWeight: FontWeight.w600,
    color: const Color(0xFF1E293B),
  );

  InputDecoration _filterDropdownDecoration({required String hintText}) {
    return InputDecoration(
      isDense: true,
      hintText: hintText,
      hintStyle: GoogleFonts.inter(fontSize: 11, color: const Color(0xFF94A3B8)),
      filled: true,
      fillColor: Colors.white,
      contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
      border: OutlineInputBorder(
        borderRadius: BorderRadius.circular(8),
        borderSide: const BorderSide(color: _filterFieldBorder, width: 1),
      ),
      enabledBorder: OutlineInputBorder(
        borderRadius: BorderRadius.circular(8),
        borderSide: const BorderSide(color: _filterFieldBorder, width: 1),
      ),
      focusedBorder: OutlineInputBorder(
        borderRadius: BorderRadius.circular(8),
        borderSide: const BorderSide(color: _filterFocusTeal, width: 1.5),
      ),
    );
  }

  /// `agent/agentList` exposes display name as `name`; older payloads may use `agent_name`.
  String _partnerDisplayName(Map<String, dynamic> m) {
    final v = m['name'] ?? m['agent_name'] ?? m['partner_name'] ?? '';
    return v.toString().trim();
  }

  Map<String, dynamic> _allAgentItem() => {
        'id': '',
        'name': 'Select Agent',
        'agent_name': 'Select Agent',
        'agent_code': '',
      };

  Map<String, dynamic> _selectedAgentMap() {
    if (_selectedAgentId == null || _selectedAgentId!.isEmpty) {
      return _allAgentItem();
    }
    try {
      final m = _agentOptions.firstWhere(
        (a) => a['id'].toString() == _selectedAgentId,
      );
      return Map<String, dynamic>.from(m);
    } catch (_) {
      return _allAgentItem();
    }
  }

  List<Map<String, dynamic>> _payoutRaisedChoices() => [
        {'v': null, 'label': 'Select Payout Raised'},
        {'v': 'all', 'label': 'All'},
        {'v': 'yes', 'label': 'Yes'},
        {'v': 'no', 'label': 'No'},
      ];

  Map<String, dynamic> _selectedPayoutRaisedMap() {
    for (final e in _payoutRaisedChoices()) {
      if (e['v'] == _payoutRaised) return e;
    }
    return _payoutRaisedChoices().first;
  }

  Widget _buildAgentDropdownSearch(double width) {
    final agents = _agentOptions
        .where((a) => (a['id']?.toString() ?? '').isNotEmpty)
        .map((a) => Map<String, dynamic>.from(a))
        .toList();

    return SizedBox(
      height: 35,
      width: width,
      child: DropdownSearch<Map<String, dynamic>>(
        selectedItem: _selectedAgentMap(),
        items: (filter, infiniteScrollProps) {
          return [_allAgentItem(), ...agents];
        },
        itemAsString: (m) {
          if ((m['id']?.toString() ?? '').isEmpty) {
            return 'Select Agent';
          }
          final name = _partnerDisplayName(m);
          final code = (m['agent_code'] ?? '').toString();
          return '$name $code'.trim();
        },
        compareFn: (a, b) =>
            (a['id']?.toString() ?? '') == (b['id']?.toString() ?? ''),
        decoratorProps: DropDownDecoratorProps(
          decoration: _filterDropdownDecoration(hintText: 'Select Agent'),
        ),
        dropdownBuilder: (context, selectedItem) {
          final m = selectedItem ?? _allAgentItem();
          final isAll = (m['id']?.toString() ?? '').isEmpty;
          final name = _partnerDisplayName(m);
          final code = (m['agent_code'] ?? '').toString();
          final text = isAll
              ? 'Select Agent'
              : name.isEmpty
                  ? code
                  : (code.isNotEmpty ? '$name — $code' : name);
          return Align(
            alignment: Alignment.centerLeft,
            child: Text(
              text,
              style: GoogleFonts.inter(
                fontSize: 11,
                color: isAll
                    ? const Color(0xFF94A3B8)
                    : const Color(0xFF0F172A),
              ),
              overflow: TextOverflow.ellipsis,
              maxLines: 1,
            ),
          );
        },
        popupProps: PopupProps.menu(
          showSearchBox: true,
          fit: FlexFit.loose,
          constraints: const BoxConstraints(maxHeight: 280),
          menuProps: MenuProps(
            backgroundColor: Colors.white,
            elevation: 8,
            borderRadius: BorderRadius.circular(8),
          ),
          searchFieldProps: TextFieldProps(
            decoration: InputDecoration(
              filled: true,
              fillColor: Colors.white,
              hintText: 'Select Agent',
              hintStyle:
                  GoogleFonts.inter(fontSize: 12, color: const Color(0xFF94A3B8)),
              isDense: true,
              contentPadding:
                  const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
              border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
                borderSide: const BorderSide(color: _filterFieldBorder),
              ),
              enabledBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
                borderSide: const BorderSide(color: _filterFieldBorder),
              ),
              focusedBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
                borderSide:
                    const BorderSide(color: _filterFocusTeal, width: 1.5),
              ),
            ),
          ),
          itemBuilder: (context, item, isDisabled, isSelected) {
            final isAll = (item['id']?.toString() ?? '').isEmpty;
            return Container(
              color: isSelected ? const Color(0xFFF1F5F9) : null,
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
                child: isAll
                    ? Text(
                        'Select Agent',
                        style: GoogleFonts.inter(
                          fontSize: 12,
                          color: const Color(0xFF64748B),
                        ),
                      )
                    : Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          Text(
                            () {
                              final n = _partnerDisplayName(item);
                              final c = (item['agent_code'] ?? '').toString();
                              return (n.isEmpty ? c : n).toUpperCase();
                            }(),
                            style: GoogleFonts.inter(
                              fontSize: 12,
                              fontWeight: FontWeight.w700,
                              color: const Color(0xFF0F172A),
                            ),
                            maxLines: 2,
                            overflow: TextOverflow.ellipsis,
                          ),
                          const SizedBox(height: 2),
                          Text(
                            (item['agent_code'] ?? '').toString(),
                            style: GoogleFonts.inter(
                              fontSize: 10,
                              fontWeight: FontWeight.w400,
                              color: const Color(0xFF94A3B8),
                            ),
                          ),
                        ],
                      ),
              ),
            );
          },
        ),
        onChanged: (val) {
          setState(() {
            final id = val?['id']?.toString() ?? '';
            _selectedAgentId = id.isEmpty ? null : id;
          });
        },
      ),
    );
  }

  Widget _buildPayoutRaisedDropdownSearch(double width) {
    final choices = _payoutRaisedChoices();
    return SizedBox(
      height: 35,
      width: width,
      child: DropdownSearch<Map<String, dynamic>>(
        selectedItem: _selectedPayoutRaisedMap(),
        items: (filter, infiniteScrollProps) => choices,
        itemAsString: (m) => (m['label'] ?? '').toString(),
        compareFn: (a, b) => a['v'] == b['v'],
        decoratorProps: DropDownDecoratorProps(
          decoration: _filterDropdownDecoration(hintText: 'Select Payout Raised'),
        ),
        dropdownBuilder: (context, selectedItem) {
          final m = selectedItem ?? _payoutRaisedChoices().first;
          final label = (m['label'] ?? '').toString();
          final isUnset = m['v'] == null;
          return Align(
            alignment: Alignment.centerLeft,
            child: Text(
              label,
              style: GoogleFonts.inter(
                fontSize: 11,
                color: isUnset
                    ? const Color(0xFF94A3B8)
                    : const Color(0xFF0F172A),
              ),
              overflow: TextOverflow.ellipsis,
              maxLines: 1,
            ),
          );
        },
        popupProps: PopupProps.menu(
          showSearchBox: true,
          fit: FlexFit.loose,
          constraints: const BoxConstraints(maxHeight: 220),
          menuProps: MenuProps(
            backgroundColor: Colors.white,
            elevation: 8,
            borderRadius: BorderRadius.circular(8),
          ),
          searchFieldProps: TextFieldProps(
            decoration: InputDecoration(
              filled: true,
              fillColor: Colors.white,
              hintText: 'Select Payout Raised',
              hintStyle:
                  GoogleFonts.inter(fontSize: 12, color: const Color(0xFF94A3B8)),
              isDense: true,
              contentPadding:
                  const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
              border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
                borderSide: const BorderSide(color: _filterFieldBorder),
              ),
              enabledBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
                borderSide: const BorderSide(color: _filterFieldBorder),
              ),
              focusedBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
                borderSide:
                    const BorderSide(color: _filterFocusTeal, width: 1.5),
              ),
            ),
          ),
          itemBuilder: (context, item, isDisabled, isSelected) {
            final isUnset = item['v'] == null;
            return Container(
              color: isSelected ? const Color(0xFFF1F5F9) : null,
              padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
              child: Text(
                (item['label'] ?? '').toString(),
                style: GoogleFonts.inter(
                  fontSize: 12,
                  fontWeight: isUnset ? FontWeight.w400 : FontWeight.w500,
                  color: isUnset
                      ? const Color(0xFF64748B)
                      : const Color(0xFF0F172A),
                ),
              ),
            );
          },
        ),
        onChanged: (val) {
          setState(() {
            if (val == null) {
              _payoutRaised = null;
            } else {
              _payoutRaised = val['v'] as String?;
            }
          });
        },
      ),
    );
  }

  @override
  void initState() {
    super.initState();
    apiService = ApiService();
    Future.microtask(() async {
      _managerId = ref.read(managerIdProvider);
      if (_managerId != null && !_isAgentRole()) {
        await _loadAgents();
      }
    });
  }

  @override
  void dispose() {
    _startController.dispose();
    _endController.dispose();
    _searchController.dispose();
    super.dispose();
  }

  Future<void> _loadAgents() async {
    final mid = _managerId;
    if (mid == null) return;
    try {
      final response = await apiService.fetchAgentUserList(mid);
      if (response['status'] == 'success' && response['data'] is List) {
        if (mounted) {
          setState(() {
            _agentOptions = List<Map<String, dynamic>>.from(response['data']);
          });
        }
      }
    } catch (_) {}
  }

  String? _dateToIso(String ddMmYyyy) {
    final t = ddMmYyyy.trim();
    if (t.isEmpty) return null;
    try {
      final d = DateFormat('dd-MM-yyyy').parseStrict(t);
      return DateFormat('yyyy-MM-dd').format(d);
    } catch (_) {
      return null;
    }
  }

  bool _validateFiltersForSearch() {
    final from = _dateToIso(_startController.text);
    final to = _dateToIso(_endController.text);
    final startText = _startController.text.trim();
    final endText = _endController.text.trim();
    if (startText.isNotEmpty || endText.isNotEmpty) {
      if (from == null || to == null) {
        ToastHelper.showWarningToast(
          context,
          'Enter both From date and To date, or clear both.',
        );
        return false;
      }
    }
    final hasDates = from != null && to != null;
    final hasAgent = _isAgentRole()
        ? ref.read(userIdProvider) != null
        : (_selectedAgentId != null && _selectedAgentId!.trim().isNotEmpty);
    final hasPayoutRaised = _payoutRaised != null;
    if (!hasDates && !hasAgent && !hasPayoutRaised) {
      ToastHelper.showWarningToast(
        context,
        _isAgentRole()
            ? 'Select at least one filter: date range or payout raised.'
            : 'Select at least one filter: date range, agent, or payout raised.',
      );
      return false;
    }
    return true;
  }

  Future<void> _loadReport() async {
    if (!_validateFiltersForSearch()) return;

    setState(() {
      isLoading = true;
      _hasSearched = true;
    });
    try {
      final response = await apiService.fetchPayoutReportList(
        fromDate: _dateToIso(_startController.text),
        toDate: _dateToIso(_endController.text),
        agentId: _agentIdForApi(),
        payoutRaised: _payoutRaised,
      );
      if (!mounted) return;

      final data = response['data'];
      final ok = response['status']?.toString().toLowerCase() == 'success' ||
          response['code'] == 200 ||
          data is List;
      if (ok) {
        List<Map<String, dynamic>> next = [];
        if (data is List) {
          next = data.map((e) {
            if (e is Map<String, dynamic>) return e;
            if (e is Map) return Map<String, dynamic>.from(e);
            return <String, dynamic>{};
          }).toList();
        } else if (data is Map) {
          next = [Map<String, dynamic>.from(data)];
        }

        int? count;
        final cr = response['count'];
        if (cr is int) {
          count = cr;
        } else if (cr != null) {
          count = int.tryParse(cr.toString());
        }
        num? sumTotal;
        num? sumRaised;
        num? sumPending;
        final sm = response['summary'];
        if (sm is Map) {
          final m = Map<String, dynamic>.from(sm);
          sumTotal = _parseNum(m['total']);
          sumRaised = _parseNum(m['raised']);
          sumPending = _parseNum(m['pending']);
        }

        setState(() {
          _rows = next;
          _reportCount = count;
          _summaryTotal = sumTotal;
          _summaryRaised = sumRaised;
          _summaryPending = sumPending;
          _applySearch(_searchController.text);
          currentPage = 1;
        });
      } else {
        setState(() {
          _rows = [];
          _filtered = [];
          _reportCount = null;
          _summaryTotal = null;
          _summaryRaised = null;
          _summaryPending = null;
        });
        final msg = response['message']?.toString();
        if (msg != null && msg.isNotEmpty) {
          ToastHelper.showWarningToast(context, msg);
        }
      }
    } catch (e) {
      if (mounted) {
        ToastHelper.showErrorToast(context, e.toString());
      }
    } finally {
      if (mounted) setState(() => isLoading = false);
    }
  }

  void _filterData(String query) {
    setState(() {
      _applySearch(query);
      currentPage = 1;
    });
  }

  void _applySearch(String query) {
    final q = query.trim().toLowerCase();
    if (q.isEmpty) {
      _filtered = List.from(_rows);
      return;
    }
    _filtered = _rows.where((row) {
      return row.values.any(
        (v) => v != null && v.toString().toLowerCase().contains(q),
      );
    }).toList();
  }

  List<Map<String, dynamic>> get _paginated {
    if (_filtered.isEmpty) return [];
    final maxPage = (_filtered.length / itemsPerPage).ceil().clamp(1, 999999);
    final safe = currentPage.clamp(1, maxPage);
    final start = (safe - 1) * itemsPerPage;
    final end = (start + itemsPerPage).clamp(0, _filtered.length);
    return _filtered.sublist(start, end);
  }

  String _cell(Map<String, dynamic> row, List<String> keys) {
    for (final k in keys) {
      final v = row[k];
      if (v != null && v.toString().trim().isNotEmpty) {
        return v.toString();
      }
    }
    return '-';
  }

  String? _firstNonEmptyRaw(Map<String, dynamic> row, List<String> keys) {
    for (final k in keys) {
      final v = row[k];
      if (v != null && v.toString().trim().isNotEmpty) {
        return v.toString();
      }
    }
    return null;
  }

  /// API sometimes returns payout + UTR in one string (e.g. `5000.00UTR20260401164749`).
  /// Normalizes into separate display values for PAYOUT and UTR NO columns.
  ({String payout, String utr}) _payoutAndUtr(Map<String, dynamic> row) {
    const utrKeys = ['utr_no', 'utr', 'utr_number'];
    const payoutKeys = ['commission_amount', 'payout', 'commission'];

    String utrStr = (_firstNonEmptyRaw(row, utrKeys) ?? '').trim();
    String payoutRaw = (_firstNonEmptyRaw(row, payoutKeys) ?? '').trim();

    String stripTrailingPlaceholder(String s) =>
        s.replaceAll(RegExp(r'[\s\-–—]+$'), '').trim();

    if (payoutRaw.isNotEmpty) {
      final upper = payoutRaw.toUpperCase();
      final idx = upper.indexOf('UTR');
      if (idx > 0) {
        final gluedUtr = payoutRaw.substring(idx).trim();
        payoutRaw = stripTrailingPlaceholder(payoutRaw.substring(0, idx));
        if (utrStr.isEmpty || utrStr == '-') {
          utrStr = gluedUtr;
        }
      } else {
        payoutRaw = stripTrailingPlaceholder(payoutRaw);
      }
    }

    if (payoutRaw.isEmpty) payoutRaw = '-';
    if (utrStr.isEmpty) utrStr = '-';

    return (payout: payoutRaw, utr: utrStr);
  }

  static num? _parseNum(dynamic v) {
    if (v == null) return null;
    if (v is num) return v;
    return num.tryParse(v.toString());
  }

  String _fmtSummaryAmount(num? v) {
    if (v == null) return '-';
    return NumberFormat('#,##0.00').format(v);
  }

  Widget _buildSummaryChips() {
    if (!_hasSearched || isLoading) return const SizedBox.shrink();
    // API `data: []` — no rows; hide summary even if count/summary are zeros.
    if (_rows.isEmpty) return const SizedBox.shrink();
    final hasAny = _reportCount != null ||
        _summaryTotal != null ||
        _summaryRaised != null ||
        _summaryPending != null;
    if (!hasAny) return const SizedBox.shrink();

    return Padding(
      padding: const EdgeInsets.only(bottom: 8),
      child: Wrap(
        spacing: 10,
        runSpacing: 8,
        children: [
          _summaryChip(
            label: 'Count',
            value: _reportCount != null ? '$_reportCount' : '-',
            bg: const Color(0xFFE8F5E9),
            border: const Color(0xFFBBDCB5),
            labelColor: const Color(0xFF64748B),
            valueColor: const Color(0xFF2E7D32),
          ),
          _summaryChip(
            label: 'Total',
            value: _fmtSummaryAmount(_summaryTotal),
            bg: const Color(0xFFECEFF1),
            border: const Color(0xFFB0BEC5),
            labelColor: const Color(0xFF64748B),
            valueColor: const Color(0xFF37474F),
          ),
          _summaryChip(
            label: 'Paid',
            value: _fmtSummaryAmount(_summaryRaised),
            bg: const Color(0xFFE0F2F1),
            border: const Color(0xFF80CBC4),
            labelColor: const Color(0xFF64748B),
            valueColor: const Color(0xFF00695C),
          ),
          _summaryChip(
            label: 'Pending',
            value: _fmtSummaryAmount(_summaryPending),
            bg: _pendingChipBg,
            border: _pendingChipBorder,
            labelColor: const Color(0xFF64748B),
            valueColor: _pendingChipValue,
          ),
        ],
      ),
    );
  }

  Widget _summaryChip({
    required String label,
    required String value,
    required Color bg,
    required Color border,
    required Color labelColor,
    required Color valueColor,
  }) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
      decoration: BoxDecoration(
        color: bg,
        borderRadius: BorderRadius.circular(8),
        border: Border.all(color: border, width: 1),
      ),
      child: RichText(
        text: TextSpan(
          style: GoogleFonts.inter(fontSize: 12, color: labelColor),
          children: [
            TextSpan(text: '$label: '),
            TextSpan(
              text: value,
              style: GoogleFonts.inter(
                fontSize: 12,
                fontWeight: FontWeight.w700,
                color: valueColor,
              ),
            ),
          ],
        ),
      ),
    );
  }

  Future<void> _onExport() async {
    if (!_validateFiltersForSearch()) return;
    try {
      await apiService.downloadCommissionPayoutReportExport(
        fromDate: _dateToIso(_startController.text),
        toDate: _dateToIso(_endController.text),
        agentId: _agentIdForApi(),
        payoutRaised: _payoutRaised,
      );
    } catch (e) {
      if (mounted) {
        ToastHelper.showErrorToast(context, 'Export failed: $e');
      }
    }
  }

  Widget _filterControlsRow(BuildContext context) {
    final spacing = 5.0;
    final isMobile = ResponsiveLayout.isMobile(context);
    final role = (ref.watch(userRoleProvider) ?? '').toString().trim().toLowerCase();
    final showAgentFilter = role != 'agent' && role != 'a';

    final fields = Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        DateRangePickerField(
          startController: _startController,
          endController: _endController,
          hintText: 'Select date range',
          showLabelAboveField: false,
          txtwidth: isMobile
              ? null
              : MediaQuery.of(context).size.width * 0.15,
          lastDate: DateTime.now(),
          useFormField: false,
        ),
        if (showAgentFilter) ...[
          SizedBox(width: spacing),
          _buildAgentDropdownSearch(
            isMobile ? 168.0 : MediaQuery.of(context).size.width * 0.13,
          ),
        ],
        SizedBox(width: spacing),
        _buildPayoutRaisedDropdownSearch(
          isMobile ? 168.0 : MediaQuery.of(context).size.width * 0.13,
        ),
        SizedBox(width: spacing),
        Tooltip(
          message: 'Search',
          child: IconButton(
            icon: const Icon(Icons.search_rounded, size: 18, color: Color(0xFF94A3B8)),
            onPressed: _loadReport,
          ),
        ),
        Tooltip(
          message: 'Refresh',
          child: IconButton(
            icon: const Icon(Icons.refresh, size: 18, color: Color(0xFF94A3B8)),
            onPressed: () {
              _startController.clear();
              _endController.clear();
              _searchController.clear();
              setState(() {
                _selectedAgentId = null;
                _payoutRaised = null;
                _rows = [];
                _filtered = [];
                _hasSearched = false;
                _reportCount = null;
                _summaryTotal = null;
                _summaryRaised = null;
                _summaryPending = null;
                currentPage = 1;
              });
            },
          ),
        ),
      ],
    );

    return Container(
      padding: const EdgeInsets.all(8.0),
      color: isMobile ? _filterStripMobileBg : null,
      child: SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: fields,
      ),
    );
  }

  Widget _buildSearchAndActions(BuildContext context) {
    final isMobile = ResponsiveLayout.isMobile(context);
    final searchField = ThemedSearchField(
      hintText: 'Search',
      onChanged: _filterData,
      controller: _searchController,
      backgroundColor: const Color(0xFFFFFFFF),
      txtHeight: 30,
      txtwidth: isMobile
          ? MediaQuery.of(context).size.width * 0.7
          : MediaQuery.of(context).size.width * 0.15,
    );
    final actions = [
      Tooltip(
        message: 'Export Excel',
        child: InkWell(
          onTap: _onExport,
          child: Container(
            padding: const EdgeInsets.all(7.0),
            decoration: BoxDecoration(
              color: const Color(0xFF2E7D6E),
              borderRadius: BorderRadius.circular(8.0),
            ),
            child: Image.asset(
              'assets/miscellaneous/export.png',
              height: 13,
              width: 13,
            ),
          ),
        ),
      ),
      const SizedBox(width: 8),
    ];
    // Desktop: no Spacer — this Row sits after Expanded(filter); Row+Spacer has
    // unbounded intrinsic width and triggers RenderFlex layout failure.
    if (!isMobile) {
      return Row(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          searchField,
          const SizedBox(width: 10),
          ...actions,
        ],
      );
    }
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        searchField,
        const Spacer(),
        ...actions,
      ],
    );
  }

  Widget _buildFilterBar(BuildContext context) {
    final isMobile = ResponsiveLayout.isMobile(context);
    if (isMobile) {
      return Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          _filterControlsRow(context),
          const SizedBox(height: 8),
          _buildSearchAndActions(context),
        ],
      );
    }
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Expanded(child: _filterControlsRow(context)),
        _buildSearchAndActions(context),
      ],
    );
  } 

  Widget _tableHeader() {
    return Container(
      decoration: BoxDecoration(
        color: _tableHeaderBg,
        borderRadius: BorderRadius.circular(6),
      ),
      padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
      child: Row(
        children: [
          Expanded(flex: 1, child: Text('S NO', style: _headerColumn)),
          Expanded(flex: 2, child: Text('POLICY NO', style: _headerColumn)),
          Expanded(flex: 2, child: Text('REG NO', style: _headerColumn)),
          Expanded(flex: 1, child: Text('WEIGHT', style: _headerColumn)),
          Expanded(flex: 2, child: Text('FUEL TYPE', style: _headerColumn)),
          Expanded(flex: 2, child: Text('VEHICLE TYPE', style: _headerColumn)),
          Expanded(flex: 2, child: Text('UTR NO', style: _headerColumn)),
          Expanded(
            flex: 2,
            child: Text('PREMIUM', style: _headerColumn, textAlign: TextAlign.right),
          ),
          Expanded(
            flex: 2,
            child: Text('PAYOUT', style: _headerColumn, textAlign: TextAlign.right),
          ),
          const SizedBox(width: 15),
          Expanded(
            flex: 2,
            child: Text(
              _isAccountsReceivedRole() ? 'PAID' : 'RECEIVED',
              style: _headerColumn,
            ),
          ),
        ],
      ),
    );
  }

  Widget _dataRow(Map<String, dynamic> item, int sno) {
    final highlightNo = _receivedIsNo(item);
    // Fresh style (not copyWith on _dataBold): GoogleFonts may set `foreground`,
    // which overrides `color` and can make text invisible on web.
    final rowStyle = highlightNo
        ? GoogleFonts.inter(
            fontSize: 11,
            fontWeight: FontWeight.w400,
            color: const Color(0xFF0F172A),
          )
        : _dataBold;

    final pu = _payoutAndUtr(item);

    final row = Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Expanded(flex: 1, child: Text('$sno', style: rowStyle)),
        Expanded(
          flex: 2,
          child: Text(
            _cell(item, ['policy_no']),
            style: rowStyle,
            maxLines: 2,
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Expanded(
          flex: 2,
          child: Text(
            _cell(item, ['reg_no']),
            style: rowStyle,
            maxLines: 2,
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Expanded(
          flex: 1,
          child: Text(
            _cell(item, ['weight']),
            style: rowStyle,
            maxLines: 2,
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Expanded(
          flex: 2,
          child: Text(
            _cell(item, ['fuel_type']),
            style: rowStyle,
            maxLines: 2,
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Expanded(
          flex: 2,
          child: Text(
            _cell(item, ['vehicle_type']),
            style: rowStyle,
            maxLines: 2,
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Expanded(
          flex: 2,
          child: Text(
            pu.utr,
            style: rowStyle,
            maxLines: 2,
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Expanded(
          flex: 2,
          child: Text(
            _cell(item, ['premium']),
            style: rowStyle,
            textAlign: TextAlign.right,
            maxLines: 2,
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Expanded(
          flex: 2,
          child: Text(
            pu.payout,
            style: rowStyle,
            textAlign: TextAlign.right,
            maxLines: 2,
            overflow: TextOverflow.ellipsis,
          ),
        ),
        const SizedBox(width: 15),
        Expanded(
          flex: 2,
          child: Text(
            _receivedDisplayLabel(item['received_or_not']),
            style: rowStyle,
            maxLines: 2,
            overflow: TextOverflow.ellipsis,
          ),
        ),
      ],
    );

    final padded = Padding(
      padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
      child: row,
    );

    if (highlightNo) {
      // Background in a separate layer so ListView/Container decoration never clips text (web).
      return Stack(
        clipBehavior: Clip.none,
        children: [
          Positioned.fill(
            child: DecoratedBox(
              decoration: BoxDecoration(
                color: _pendingChipBg,
                borderRadius: BorderRadius.circular(8),
                border: Border(
                  bottom: const BorderSide(color: _rowBorder, width: 1),
                  left: const BorderSide(color: _pendingChipBorder, width: 3),
                ),
              ),
            ),
          ),
          padded,
        ],
      );
    }

    return Container(
      clipBehavior: Clip.none,
      decoration: BoxDecoration(
        color: Colors.white,
        border: const Border(
          bottom: BorderSide(color: _rowBorder, width: 1),
        ),
        borderRadius: BorderRadius.circular(8),
      ),
      child: padded,
    );
  }

  Widget _buildDataTable(BuildContext context) {
    if (!_hasSearched) {
      return Center(
        child: Padding(
          padding: const EdgeInsets.all(24),
          child: Text(
            () {
              final r =
                  (ref.watch(userRoleProvider) ?? '').toString().trim().toLowerCase();
              final hideAgent = r == 'agent' || r == 'a';
              return hideAgent
                  ? 'Choose filters (date range and/or payout raised) and tap Search to load the report.'
                  : 'Choose filters (date range, agent, and/or payout raised) and tap Search to load the report.';
            }(),
            textAlign: TextAlign.center,
            style: GoogleFonts.inter(
              fontSize: 13,
              color: const Color(0xFF64748B),
              height: 1.4,
            ),
          ),
        ),
      );
    }

    if (isLoading) {
      return const Center(child: CircularProgressIndicator());
    }

    final pageItems = _paginated;
    final startIndex = _filtered.isEmpty ? 0 : (currentPage - 1) * itemsPerPage;

    if (pageItems.isEmpty) {
      return const SizedBox(
        height: 50,
        child: Center(child: Text('No available data')),
      );
    }

    final isMobile = ResponsiveLayout.isMobile(context);
    final tableWidth =
        MediaQuery.of(context).size.width < 1500 ? 1500.0 : MediaQuery.of(context).size.width;

    if (isMobile) {
      return Scrollbar(
        thumbVisibility: true,
        child: SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: SizedBox(
            width: tableWidth,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                _tableHeader(),
                ListView.builder(
                  shrinkWrap: true,
                  physics: const NeverScrollableScrollPhysics(),
                  itemCount: pageItems.length,
                  itemBuilder: (context, i) {
                    return _dataRow(pageItems[i], startIndex + i + 1);
                  },
                ),
              ],
            ),
          ),
        ),
      );
    }

    // One ListView inside a fixed-height box (no Column+Expanded) avoids relayout
    // conflicts with horizontal SingleChildScrollView on web.
    return LayoutBuilder(
      builder: (context, constraints) {
        final w = constraints.maxWidth < 1500 ? 1500.0 : constraints.maxWidth;
        var h = constraints.maxHeight;
        if (!h.isFinite || h <= 0) {
          h = MediaQuery.sizeOf(context).height * 0.45;
        }
        return Scrollbar(
          thumbVisibility: true,
          child: SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: SizedBox(
              width: w,
              height: h,
              child: ListView(
                padding: EdgeInsets.zero,
                children: [
                  _tableHeader(),
                  ...pageItems.asMap().entries.map((e) {
                    final i = e.key;
                    return _dataRow(e.value, startIndex + i + 1);
                  }),
                ],
              ),
            ),
          ),
        );
      },
    );
  }

  /// Filters + table only (title row lives in [build] like [policylist]).
  Widget _buildContent(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        _buildFilterBar(context),
        _buildSummaryChips(),
        const SizedBox(height: 5),
        ResponsiveLayout.isMobile(context)
            ? _buildDataTable(context)
            : Expanded(child: _buildDataTable(context)),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    final isMobile = ResponsiveLayout.isMobile(context);
    return MainLayout(
      title: 'Payout Report',
      // Single Column under MainLayout's Expanded — do not nest LayoutBuilder here;
      // nested LayoutBuilder + Expanded caused _debugRelayoutBoundaryAlreadyMarkedNeedsLayout on web.
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          SizedBox(
            height: 30,
            child: Align(
              alignment: Alignment.centerLeft,
              child: Text(
                'Payout Report',
                style: GoogleFonts.poppins(
                  fontSize: 14,
                  fontWeight: FontWeight.w500,
                ),
              ),
            ),
          ),
          const SizedBox(height: 5),
          Expanded(
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: isMobile
                  ? SingleChildScrollView(
                      child: _buildContent(context),
                    )
                  : _buildContent(context),
            ),
          ),
          PaginationControls(
            currentPage: currentPage,
            itemsPerPage: itemsPerPage,
            totalItems: _filtered.length,
            onPageChanged: (page) {
              setState(() => currentPage = page);
            },
            onItemsPerPageChanged: (items) {
              setState(() {
                itemsPerPage = items;
                currentPage = 1;
              });
            },
          ),
        ],
      ),
    );
  }
}
