import 'dart:convert';
import 'dart:math' as math;

import 'package:dropdown_search/dropdown_search.dart';
import 'package:file_picker/file_picker.dart';
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 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;

import '../../../../core/config/env.dart';
import '../../../../core/routing/routes.dart';
import '../../../../core/services/api_service.dart';
import '../../../../data/services/auth_service.dart';
import '../../../../data/utils/toastNotification.dart';
import '../../../../data/utils/validators.dart';
import '../../../layouts/main_layout.dart';
import '../../../layouts/responsive_layout.dart';
import '../../../providers/manager_provider.dart';
import '../../../providers/user_provider.dart';
import '../../../providers/userRoleProvider.dart';
import '../../../themes/indicators/input_field_decoration.dart';
import '../../../themes/indicators/search_field_theme.dart';
import '../../../themes/indicators/text_field_theme.dart';
import '../../../themes/indicators/customizd_file_upload.dart';

/// Full-page partner (agent) create / edit with per–vehicle-type retention rates.
class AgentDetailsScreen extends ConsumerStatefulWidget {
  const AgentDetailsScreen({super.key, required this.agentId});

  /// Use `'new'` for create, otherwise the numeric agent id as string.
  final String agentId;

  bool get isCreate {
    final s = agentId.trim().toLowerCase();
    return s == 'new' || s == 'create';
  }

  @override
  ConsumerState<AgentDetailsScreen> createState() => _AgentDetailsScreenState();
}

class _AgentDetailsScreenState extends ConsumerState<AgentDetailsScreen> {
  /// Digits only, max 10 (India-style mobile).
  static final List<TextInputFormatter> _phoneInputFormatters = [
    FilteringTextInputFormatter.digitsOnly,
    LengthLimitingTextInputFormatter(10),
  ];

  /// Percentage 0–100 with up to 2 decimal places; cannot exceed 100.
  static final List<TextInputFormatter> _retentionPercentFormatters = [
    FilteringTextInputFormatter.allow(RegExp(r'^\d{0,3}(\.\d{0,2})?$')),
    TextInputFormatter.withFunction((oldValue, newValue) {
      if (newValue.text.isEmpty) return newValue;
      final v = double.tryParse(newValue.text);
      if (v == null) return oldValue;
      if (v > 100 || v < 0) return oldValue;
      return newValue;
    }),
  ];

  final _formKey = GlobalKey<FormState>();
  final ApiService _api = ApiService();

  final _nameCtrl = TextEditingController();
  final _emailCtrl = TextEditingController();
  final _mobileCtrl = TextEditingController();
  final _codeCtrl = TextEditingController();
  final _addressCtrl = TextEditingController();
  final _retentionSearchCtrl = TextEditingController();

  final GlobalKey<DropdownSearchState<Map<String, dynamic>>> _seKey =
      GlobalKey<DropdownSearchState<Map<String, dynamic>>>();

  List<Map<String, dynamic>> _vehicleTypes = [];
  final Map<String, TextEditingController> _rateControllers = {};

  List<Map<String, dynamic>> _salesExecutives = [];
  dynamic _selectedSalesExecutiveId;

  PlatformFile? _certificateFile;
  String? _certificateLabel;
  String? _certificateUrlFromApi;
  String? _token;
  String? _loadedAgentPk;

  bool _loading = true;
  bool _saving = false;
  bool _savingAllRetention = false;

  /// Retention rows can be saved only after the partner exists (`agent_id`).
  bool get _retentionTableEnabled =>
      _loadedAgentPk != null && _loadedAgentPk!.trim().isNotEmpty;

  bool get _retentionActionsBusy => _saving || _savingAllRetention;

  @override
  void initState() {
    super.initState();
    _retentionSearchCtrl.addListener(() => setState(() {}));
    _bootstrap();
  }

  /// After create, [context.go] to `/agentDetails/:id` can update [widget.agentId] while
  /// reusing this [State] — [initState] does not run again, so we must load the new id here.
  @override
  void didUpdateWidget(covariant AgentDetailsScreen oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.agentId != widget.agentId && !widget.isCreate) {
      _reloadAgentForRouteIdChange();
    }
  }

  Future<void> _reloadAgentForRouteIdChange() async {
    await _loadAgent();
    if (mounted) setState(() {});
  }

  Future<void> _bootstrap() async {
    _token = await AuthService.getToken();
    await _loadSalesExecutives();
    await _loadVehicleTypes();
    if (!widget.isCreate) {
      await _loadAgent();
    } else {
      _initRateControllersFromTypes();
    }
    if (mounted) setState(() => _loading = false);
  }

  Future<void> _loadSalesExecutives() async {
    final managerId = ref.read(managerIdProvider);
    final role = ref.read(userRoleProvider);
    if (managerId == null || role == null) return;
    try {
      final res = await _api.fetchSalesExecutiveList(managerId, role);
      if (res['status'] == 'success' && res['data'] is List) {
        final list = List<Map<String, dynamic>>.from(res['data']);
        setState(() {
          _salesExecutives =
              list.where((e) => int.tryParse(e['is_active'].toString()) == 1).toList();
        });
      }
    } catch (_) {}
  }

  Future<void> _loadVehicleTypes() async {
    try {
      final res = await _api.fetchPartnerVehicleTypes();
      if (res['status'] == 'success' && res['data'] is List) {
        setState(() {
          _vehicleTypes = List<Map<String, dynamic>>.from(res['data']);
        });
      }
    } catch (_) {}
  }

  String _retentionKey(int vehicleTypeId, int segmentId) => '${vehicleTypeId}_$segmentId';

  int _readInt(dynamic value) => int.tryParse(value?.toString() ?? '') ?? 0;

  String _displayVehicleSegment(Map<String, dynamic> vt) {
    final name = (vt['vehicle_type'] ?? '-').toString();
    final segment = (vt['segment'] ?? '').toString().trim();
    if (segment.isEmpty) return name;
    return '$name - $segment';
  }

  void _initRateControllersFromTypes({Map<String, String>? initial}) {
    for (final c in _rateControllers.values) {
      c.dispose();
    }
    _rateControllers.clear();
    for (final vt in _vehicleTypes) {
      final vehicleTypeId = _readInt(vt['vehicle_type_id'] ?? vt['id']);
      final segmentId = _readInt(vt['segment_id']);
      if (vehicleTypeId == 0 || segmentId == 0) continue;
      final key = _retentionKey(vehicleTypeId, segmentId);
      final text = initial?[key] ?? '';
      _rateControllers[key] = TextEditingController(text: text);
    }
  }

  /// Builds (vehicle_type_id + segment_id) → retention % text from [findAgent].
  Map<String, String> _retentionMapFromAgentData(Map<String, dynamic> data) {
    final Map<String, String> initial = {};
    final raw = data['retention_by_vehicle'] ?? data['retentionByVehicle'];
    if (raw is! List) return initial;
    for (final row in raw) {
      if (row is! Map) continue;
      final m = Map<String, dynamic>.from(row);
      final vid = _readInt(m['vehicle_type_id'] ?? m['vehicleTypeId']);
      final sid = _readInt(m['segment_id'] ?? m['segmentId']);
      if (vid == 0 || sid == 0) continue;
      final rate = m['retention_rate'] ?? m['retentionRate'];
      if (rate == null) continue;
      initial[_retentionKey(vid, sid)] = rate.toString();
    }
    return initial;
  }

  Future<void> _loadAgent({bool silent = false}) async {
    try {
      final res = await _api.findSingleAgentData(widget.agentId);
      if (res['status'] != 'success' || res['data'] == null) {
        if (!silent && mounted) {
          ToastHelper.showErrorToast(context, 'Partner not found');
          context.go(AppRoutes.agentLst);
        }
        return;
      }
      final data = Map<String, dynamic>.from(res['data'] as Map);
      final pk = data['id'] ?? data['agent_id'];
      _loadedAgentPk = pk?.toString().trim();
      if (_loadedAgentPk != null && _loadedAgentPk!.isEmpty) {
        _loadedAgentPk = null;
      }

      _nameCtrl.text = (data['name'] ?? '').toString();
      _emailCtrl.text = (data['email'] ?? '').toString();
      _mobileCtrl.text = (data['mobile'] ?? '').toString();
      _codeCtrl.text = (data['agent_code'] ?? '').toString();
      _addressCtrl.text = (data['address'] ?? '').toString();

      if (data['sales_executive_id'] != null) {
        _selectedSalesExecutiveId = int.tryParse(data['sales_executive_id'].toString());
      }

      final cert = data['certificate_file_name']?.toString();
      if (cert != null && cert.isNotEmpty) {
        _certificateLabel = cert.split('/').last;
        _certificateUrlFromApi = cert;
        _certificateFile = null;
      }

      final initial = _retentionMapFromAgentData(data);
      _initRateControllersFromTypes(initial: initial);
      if (silent && mounted) setState(() {});
    } catch (e) {
      if (!silent && mounted) {
        ToastHelper.showErrorToast(context, 'Failed to load partner');
        context.go(AppRoutes.agentLst);
      }
    }
  }

  List<Map<String, dynamic>> get _filteredVehicleTypes {
    final q = _retentionSearchCtrl.text.trim().toLowerCase();
    if (q.isEmpty) return _vehicleTypes;
    final terms = q.split(RegExp(r'\s+')).where((t) => t.isNotEmpty).toList();
    return _vehicleTypes.where((vt) {
      final vehicle = (vt['vehicle_type'] ?? '').toString().toLowerCase();
      final segment = (vt['segment'] ?? '').toString().toLowerCase();
      final searchable = '$vehicle $segment';
      return terms.every(searchable.contains);
    }).toList();
  }

  @override
  void dispose() {
    _nameCtrl.dispose();
    _emailCtrl.dispose();
    _mobileCtrl.dispose();
    _codeCtrl.dispose();
    _addressCtrl.dispose();
    _retentionSearchCtrl.dispose();
    for (final c in _rateControllers.values) {
      c.dispose();
    }
    super.dispose();
  }

  /// Collect valid rates from **all** vehicle types (not search-filtered) for bulk API.
  List<Map<String, dynamic>> _collectBulkRetentionPayload() {
    final out = <Map<String, dynamic>>[];
    for (final vt in _vehicleTypes) {
      final vehicleTypeId = _readInt(vt['vehicle_type_id'] ?? vt['id']);
      final segmentId = _readInt(vt['segment_id']);
      if (vehicleTypeId == 0 || segmentId == 0) continue;
      final key = _retentionKey(vehicleTypeId, segmentId);
      final ctrl = _rateControllers[key];
      if (ctrl == null) continue;
      final t = ctrl.text.trim();
      if (t.isEmpty) continue;
      final v = double.tryParse(t);
      if (v == null || v < 0 || v > 100) continue;
      out.add({
        'vehicle_type_id': vehicleTypeId,
        'segment_id': segmentId,
        'retention_rate': v,
      });
    }
    return out;
  }

  Future<void> _saveAllRetentionRates() async {
    if (!_retentionTableEnabled) {
      ToastHelper.showWarningToast(
        context,
        'Save partner details first to get an agent id',
      );
      return;
    }
    if (_retentionActionsBusy) return;

    final rates = _collectBulkRetentionPayload();
    if (rates.isEmpty) {
      ToastHelper.showWarningToast(
        context,
        'Enter at least one retention rate (0–100%)',
      );
      return;
    }

    final userId = ref.read(userIdProvider)?.toString() ?? '';
    if (userId.isEmpty) {
      ToastHelper.showErrorToast(context, 'Please log in again');
      return;
    }

    if (_token == null) {
      _token = await AuthService.getToken();
    }
    if (_token == null) {
      ToastHelper.showErrorToast(context, 'Please log in again');
      return;
    }

    setState(() => _savingAllRetention = true);
    try {
      final res = await _api.saveAgentRetentionRatesBulk(
        agentId: _loadedAgentPk!,
        retentionRates: rates,
        updatedBy: userId,
      );
      if (res['status'] == 'success') {
        if (mounted) {
          ToastHelper.showSuccessToast(context, 'All retention rates saved');
          context.go(AppRoutes.agentLst);
        }
        return;
      } else {
        ToastHelper.showErrorToast(
          context,
          res['data']?.toString() ?? 'Save failed',
        );
      }
    } catch (e) {
      ToastHelper.showErrorToast(context, 'Save failed');
    } finally {
      if (mounted) setState(() => _savingAllRetention = false);
    }
  }

  /// Backend may return the new row id under [data.id], [data.agent_id], or top-level keys.
  String? _newAgentIdFromCreateBody(dynamic body) {
    if (body is! Map) return null;
    final m = Map<String, dynamic>.from(body);
    final data = m['data'];
    if (data is Map) {
      final dm = Map<String, dynamic>.from(data);
      for (final key in ['agent_id', 'id', 'agentId']) {
        final v = dm[key];
        final s = v?.toString().trim();
        if (s != null && s.isNotEmpty && s != 'null') return s;
      }
    } else if (data != null && data is! List) {
      final s = data.toString().trim();
      if (s.isNotEmpty && s != 'null') return s;
    }
    for (final key in ['agent_id', 'id']) {
      final v = m[key];
      final s = v?.toString().trim();
      if (s != null && s.isNotEmpty && s != 'null') return s;
    }
    return null;
  }

  Future<void> _saveRowRetention(Map<String, dynamic> vt) async {
    if (!_retentionTableEnabled) {
      ToastHelper.showWarningToast(
        context,
        'Save partner details first to get an agent id',
      );
      return;
    }
    if (_savingAllRetention) return;
    final vehicleTypeId = _readInt(vt['vehicle_type_id'] ?? vt['id']);
    final segmentId = _readInt(vt['segment_id']);
    if (vehicleTypeId == 0 || segmentId == 0) {
      ToastHelper.showErrorToast(context, 'Vehicle type or segment missing');
      return;
    }
    final key = _retentionKey(vehicleTypeId, segmentId);
    final ctrl = _rateControllers[key];
    if (ctrl == null) return;
    final t = ctrl.text.trim();
    if (t.isEmpty) {
      ToastHelper.showWarningToast(context, 'Enter a retention rate');
      return;
    }
    final v = double.tryParse(t);
    if (v == null || v < 0 || v > 100) {
      ToastHelper.showWarningToast(context, 'Rate must be between 0 and 100');
      return;
    }
    final userId = ref.read(userIdProvider)?.toString() ?? '';
    if (userId.isEmpty) {
      ToastHelper.showErrorToast(context, 'Please log in again');
      return;
    }
    setState(() => _saving = true);
    try {
      final res = await _api.updateAgentVehicleRetention(
        agentId: _loadedAgentPk!,
        vehicleTypeId: '$vehicleTypeId',
        segmentId: '$segmentId',
        retentionRate: t,
        updatedBy: userId,
      );
      if (res['status'] == 'success') {
        if (mounted) {
          ToastHelper.showSuccessToast(context, 'Retention updated');
          await _loadAgent(silent: true);
        }
      } else {
        ToastHelper.showErrorToast(
          context,
          res['data']?.toString() ?? 'Update failed',
        );
      }
    } catch (e) {
      ToastHelper.showErrorToast(context, 'Update failed');
    } finally {
      if (mounted) setState(() => _saving = false);
    }
  }

  Future<void> _savePartnerDetails() async {
    final ok = _formKey.currentState?.validate() ?? false;
    if (!ok) {
      FocusManager.instance.primaryFocus?.unfocus();
      WidgetsBinding.instance.addPostFrameCallback((_) {
        FocusManager.instance.primaryFocus?.unfocus();
      });
      return;
    }

    final email = _emailCtrl.text.trim();
    final phone = _mobileCtrl.text.trim();
    if (_selectedSalesExecutiveId == null) {
      ToastHelper.showWarningToast(context, 'Select a sales executive');
      return;
    }

    if (_token == null) {
      _token = await AuthService.getToken();
    }
    if (_token == null) {
      ToastHelper.showErrorToast(context, 'Please log in again');
      return;
    }

    final managerId = ref.read(managerIdProvider)?.toString() ?? '';
    final userId = ref.read(userIdProvider)?.toString() ?? '';
    final isUpdate = !widget.isCreate && _loadedAgentPk != null;

    final uri = Uri.parse(
      isUpdate ? '${Env.apiUrl}agent/updateAgent' : '${Env.apiUrl}agent/createAgent',
    );
    final request = http.MultipartRequest('POST', uri);
    request.headers['Authorization'] = 'Bearer $_token';
    request.headers['app-signature'] = Env.App_Signature;

    request.fields['name'] = _nameCtrl.text.trim();
    request.fields['email'] = email;
    request.fields['mobile'] = phone;
    request.fields['address'] = _addressCtrl.text.trim();
    request.fields['agent_code'] = _codeCtrl.text.trim();
    request.fields['sales_executive_id'] = _selectedSalesExecutiveId.toString();
    request.fields['manager_id'] = managerId;

    if (isUpdate) {
      request.fields['id'] = _loadedAgentPk!;
      request.fields['updated_by'] = userId;
    } else {
      request.fields['created_by'] = userId;
    }

    if (_certificateFile != null) {
      try {
        if (_certificateFile!.bytes != null) {
          request.files.add(
            http.MultipartFile.fromBytes(
              'certificate_file_name',
              _certificateFile!.bytes!,
              filename: _certificateFile!.name,
            ),
          );
        } else if (_certificateFile!.path != null) {
          request.files.add(
            await http.MultipartFile.fromPath(
              'certificate_file_name',
              _certificateFile!.path!,
              filename: _certificateFile!.name,
            ),
          );
        }
      } catch (e) {
        ToastHelper.showErrorToast(context, 'Could not attach certificate');
        return;
      }
    }

    setState(() => _saving = true);
    try {
      final streamed = await request.send();
      final response = await http.Response.fromStream(streamed);
      if (response.statusCode == 403 || response.statusCode == 401) {
        await _api.clearLocalStorageAndRedirect();
        return;
      }
      final body = jsonDecode(response.body);
      if (response.statusCode == 200 &&
          body is Map &&
          body['status'] == 'success') {
        ToastHelper.showSuccessToast(
          context,
          isUpdate ? 'Partner updated' : 'Partner created',
        );
        if (isUpdate && mounted) {
          context.go(AppRoutes.agentLst);
          return;
        }
        if (!isUpdate && mounted) {
          final newId = _newAgentIdFromCreateBody(body);
          if (newId != null && newId.isNotEmpty) {
            setState(() => _loadedAgentPk = newId);
            context.go(AppRoutes.agentDetailsFor(newId));
            return;
          }
          ToastHelper.showWarningToast(
            context,
            'Partner saved but agent id missing — open from list to set retention',
          );
          context.go(AppRoutes.agentLst);
          return;
        }
      } else {
        final msg = body is Map ? body['data']?.toString() : response.body;
        ToastHelper.showErrorToast(context, msg ?? 'Save failed');
      }
    } catch (e) {
      ToastHelper.showErrorToast(context, 'Save failed');
    } finally {
      if (mounted) setState(() => _saving = false);
    }
  }

  Map<String, dynamic>? _selectedSalesExecutiveMap() {
    if (_selectedSalesExecutiveId == null) return null;
    for (final e in _salesExecutives) {
      if (e['id'].toString() == _selectedSalesExecutiveId.toString()) return e;
    }
    return null;
  }

  @override
  Widget build(BuildContext context) {
    if (_loading) {
      return MainLayout(
        title: 'Partner',
        body: const Center(child: CircularProgressIndicator()),
      );
    }

    final pageTitle = widget.isCreate ? 'New Partner' : 'Edit Partner';

    return MainLayout(
      title: 'Partner',
      body: SelectionArea(
        child: Container(
          color: Colors.white,
          width: double.infinity,
          height: double.infinity,
          child: LayoutBuilder(
            builder: (context, constraints) {
              final mobile = ResponsiveLayout.isMobile(context);
              final hPad = mobile ? 12.0 : 20.0;
              final vPad = mobile ? 12.0 : 16.0;
              final viewW = constraints.hasBoundedWidth && constraints.maxWidth.isFinite
                  ? constraints.maxWidth
                  : MediaQuery.sizeOf(context).width;
              final contentW = (viewW - 2 * hPad).clamp(280.0, double.infinity);

              final form = Form(
                key: _formKey,
                autovalidateMode: AutovalidateMode.disabled,
                child: mobile
                    ? Column(
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        children: [
                          _pageHeaderBar(context, pageTitle),
                          const SizedBox(height: 12),
                          Expanded(
                            child: SingleChildScrollView(
                              padding: EdgeInsets.only(bottom: vPad),
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.stretch,
                                children: [
                                  _partnerDetailsHeading(),
                                  const SizedBox(height: 14),
                                  _partnerDetailsCard(context, contentW),
                                  const SizedBox(height: 24),
                                  _retentionSection(context, expandTableHeight: false),
                                  SizedBox(height: mobile ? 24 : 16),
                                ],
                              ),
                            ),
                          ),
                        ],
                      )
                    : Column(
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        children: [
                          _pageHeaderBar(context, pageTitle),
                          const SizedBox(height: 12),
                          Expanded(
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.stretch,
                              children: [
                                Row(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: [
                                    Expanded(
                                      flex: 5,
                                      child: _partnerDetailsHeading(),
                                    ),
                                    const SizedBox(width: 16),
                                    Expanded(
                                      flex: 6,
                                      child: _retentionTitleSearchRow(),
                                    ),
                                  ],
                                ),
                                const SizedBox(height: 12),
                                Expanded(
                                  child: Row(
                                    crossAxisAlignment: CrossAxisAlignment.stretch,
                                    children: [
                                      Expanded(
                                        flex: 5,
                                        child: SingleChildScrollView(
                                          padding: const EdgeInsets.only(right: 10),
                                          child: LayoutBuilder(
                                            builder: (ctx, c) {
                                              final w = c.maxWidth.isFinite && c.maxWidth > 0
                                                  ? c.maxWidth
                                                  : contentW * 0.48;
                                              return _partnerDetailsCard(context, w);
                                            },
                                          ),
                                        ),
                                      ),
                                      const SizedBox(width: 16),
                                      Expanded(
                                        flex: 6,
                                        child: _retentionSection(
                                          context,
                                          expandTableHeight: true,
                                          showSectionTitleRow: false,
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
              );

              return Padding(
                padding: EdgeInsets.symmetric(horizontal: hPad, vertical: vPad),
                child: form,
              );
            },
          ),
        ),
      ),
    );
  }

  Widget _partnerDetailsHeading() {
    return Text(
      'Partner Details',
      style: GoogleFonts.poppins(
        fontSize: 14,
        fontWeight: FontWeight.w600,
        color: const Color(0xFF1E293B),
      ),
    );
  }

  Widget _partnerDetailsCard(BuildContext context, double contentW) {
    final pad = ResponsiveLayout.isMobile(context) ? 14.0 : 20.0;
    return Container(
      width: double.infinity,
      decoration: BoxDecoration(
        color: const Color(0xFFE6F4F1),
        borderRadius: BorderRadius.circular(12),
      ),
      padding: EdgeInsets.all(pad),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          _partnerRows(context, contentW),
          const SizedBox(height: 20),
          Align(
            alignment: Alignment.centerRight,
            child: FilledButton(
              onPressed: (_saving || _savingAllRetention) ? null : _savePartnerDetails,
              style: FilledButton.styleFrom(
                backgroundColor: const Color(0xFF2E7D6E),
                padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 12),
              ),
              child: _saving
                  ? const SizedBox(
                      width: 20,
                      height: 20,
                      child: CircularProgressIndicator(
                        strokeWidth: 2,
                        color: Colors.white,
                      ),
                    )
                  : const Text('Save'),
            ),
          ),
        ],
      ),
    );
  }

  /// Same pattern as [PayOutDetails] — list-style back control + title.
  Widget _pageHeaderBar(BuildContext context, String pageTitle) {
    return SizedBox(
      height: 40,
      width: double.infinity,
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Tooltip(
            message: 'Back',
            child: IconButton(
              icon: const Icon(
                Icons.arrow_left_sharp,
                size: 25,
                color: Color(0xFF425B5B),
              ),
              onPressed: () => context.go(AppRoutes.agentLst),
              splashRadius: 18,
              hoverColor: Colors.black12,
              padding: const EdgeInsets.all(4),
              constraints: const BoxConstraints(),
            ),
          ),
          const SizedBox(width: 5),
          Expanded(
            child: Text(
              pageTitle,
              style: GoogleFonts.inter(
                fontSize: 14,
                fontWeight: FontWeight.w500,
                color: const Color(0xFF0F172A),
              ),
              overflow: TextOverflow.ellipsis,
            ),
          ),
        ],
      ),
    );
  }

  Widget _partnerRows(BuildContext context, double viewportWidth) {
    final mobile = ResponsiveLayout.isMobile(context);
    final usable = viewportWidth.isFinite ? viewportWidth.clamp(280.0, 1200.0) : 800.0;
    const rowGap = 12.0;
    const verticalGap = 16.0;
    /// Desktop: two equal columns per row (one horizontal gap).
    final fieldWidth = mobile
        ? double.infinity
        : ((usable - rowGap) / 2).clamp(140.0, 520.0);

    if (mobile) {
      return Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          _labeledField('Full name *', _nameCtrl, _reqName,
              width: fieldWidth, keyboardType: TextInputType.name),
          const SizedBox(height: 12),
          _labeledField(
            'Email *',
            _emailCtrl,
            _emailVal,
            width: fieldWidth,
            keyboardType: TextInputType.emailAddress,
          ),
          const SizedBox(height: 12),
          _labeledField(
            'Phone number *',
            _mobileCtrl,
            _phoneVal,
            width: fieldWidth,
            keyboardType: TextInputType.phone,
            inputFormatters: _phoneInputFormatters,
          ),
          const SizedBox(height: 12),
          _labeledField(
            'Partner Id *',
            _codeCtrl,
            _reqCode,
            width: fieldWidth,
            inputFormatters: [
              FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9]')),
            ],
          ),
          const SizedBox(height: 12),
          _salesDropdown(context, fieldWidth),
          const SizedBox(height: 12),
          _labeledField(
            'Address *',
            _addressCtrl,
            _reqAddress,
            width: fieldWidth,
            keyboardType: TextInputType.streetAddress,
          ),
          const SizedBox(height: 12),
          _certificateColumn(context),
        ],
      );
    }

    Widget pair(Widget a, Widget b) {
      return Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Expanded(child: a),
          SizedBox(width: rowGap),
          Expanded(child: b),
        ],
      );
    }

    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        pair(
          _labeledField('Full name *', _nameCtrl, _reqName,
              width: fieldWidth, keyboardType: TextInputType.name),
          _labeledField(
            'Email *',
            _emailCtrl,
            _emailVal,
            width: fieldWidth,
            keyboardType: TextInputType.emailAddress,
          ),
        ),
        const SizedBox(height: verticalGap),
        pair(
          _labeledField(
            'Phone number *',
            _mobileCtrl,
            _phoneVal,
            width: fieldWidth,
            keyboardType: TextInputType.phone,
            inputFormatters: _phoneInputFormatters,
          ),
          _labeledField(
            'Partner Id *',
            _codeCtrl,
            _reqCode,
            width: fieldWidth,
            inputFormatters: [
              FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9]')),
            ],
          ),
        ),
        const SizedBox(height: verticalGap),
        pair(
          _salesDropdown(context, fieldWidth),
          _labeledField(
            'Address *',
            _addressCtrl,
            _reqAddress,
            width: fieldWidth,
            keyboardType: TextInputType.streetAddress,
          ),
        ),
        const SizedBox(height: verticalGap),
        pair(
          _certificateColumn(context),
          const SizedBox.shrink(),
        ),
      ],
    );
  }

  String? _reqName(String? v) => Validators.requiredField(v, 'Name');

  String? _reqCode(String? v) => Validators.requiredField(v, 'Partner Id');

  String? _reqAddress(String? v) => Validators.requiredField(v, 'Address');

  String? _emailVal(String? v) {
    final email = (v ?? '').trim();
    final phone = _mobileCtrl.text.trim();
    if (email.isEmpty && phone.isEmpty) {
      return 'Enter email or phone number';
    }
    if (email.isEmpty && phone.isNotEmpty) return null;
    return Validators.email(email, 'Email');
  }

  String? _phoneVal(String? v) {
    final phone = (v ?? '').trim();
    final email = _emailCtrl.text.trim();
    if (email.isEmpty && phone.isEmpty) {
      return 'Enter email or phone number';
    }
    if (phone.isEmpty && email.isNotEmpty) return null;
    if (!RegExp(r'^[0-9]+$').hasMatch(phone)) {
      return 'Phone must contain only digits';
    }
    if (phone.length != 10) {
      return 'Enter a valid 10-digit phone number';
    }
    return null;
  }

  Widget _labeledField(
    String label,
    TextEditingController c,
    String? Function(String?)? validator, {
    required double width,
    TextInputType? keyboardType,
    List<TextInputFormatter>? inputFormatters,
  }) {
    final w = width == double.infinity ? null : width;
    final mq = MediaQuery.sizeOf(context).width;
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(label, style: _labelStyle),
        const SizedBox(height: 8),
        SizedBox(
          width: w ?? double.infinity,
          child: ThemedFormField(
            controller: c,
            validator: validator,
            keyboardType: keyboardType,
            inputFormatters: inputFormatters,
            borderColor: const Color(0xFFE2E8F0),
            highlightColor: const Color(0xFF50A398),
            txtwidth: w ?? mq,
          ),
        ),
      ],
    );
  }

  Widget _salesDropdown(BuildContext context, double fieldWidth) {
    final w = fieldWidth == double.infinity ? null : fieldWidth;
    final mq = MediaQuery.sizeOf(context).width;
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text('Sales executive *', style: _labelStyle),
        const SizedBox(height: 8),
        SizedBox(
          width: w ?? double.infinity,
          child: DropdownSearch<Map<String, dynamic>>(
            key: _seKey,
            selectedItem: _selectedSalesExecutiveMap(),
            items: (f, i) => _salesExecutives,
            itemAsString: (m) => (m['name'] ?? '').toString(),
            compareFn: (a, b) => a['id'] == b['id'],
            onChanged: (v) {
              setState(() => _selectedSalesExecutiveId = v?['id']);
            },
            decoratorProps: DropDownDecoratorProps(
              decoration: AppInputDecorations.dropdownDecoration(
                label: 'Select executive',
              ).copyWith(
                filled: true,
                fillColor: Colors.white,
                isDense: true,
                contentPadding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
              ),
            ),
            popupProps: PopupProps.menu(
              showSearchBox: true,
              fit: FlexFit.loose,
              constraints: const BoxConstraints(maxHeight: 280),
              menuProps: const MenuProps(
                backgroundColor: Colors.white,
              ),
              searchFieldProps: TextFieldProps(
                decoration: InputDecoration(
                  hintText: 'Search…',
                  contentPadding: const EdgeInsets.all(8),
                ),
              ),
            ),
          ),
        ),
      ],
    );
  }

  Widget _certificateColumn(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        final w = constraints.maxWidth;
        final uploadW = w.isFinite && w > 0 ? w : 240.0;
        return Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('Upload certificate', style: _labelStyle),
            const SizedBox(height: 8),
            ThemedUploadField(
              hintText: _certificateLabel ?? 'Upload document',
              txtwidth: uploadW,
              txtheight: 45,
              borderColor: const Color(0xFFE2E8F0),
              onFileSelected: (name, file) {
                setState(() {
                  _certificateFile = file;
                  _certificateLabel = name;
                });
              },
            ),
            if ((_certificateFile != null || _certificateUrlFromApi != null) &&
                _loadedAgentPk != null) ...[
              const SizedBox(height: 6),
              TextButton(
                onPressed: () {
                  _api.downloadFile(
                    apiUrl: 'agent/downloadAgentCertificateFile?agent_id=$_loadedAgentPk',
                    apiId: _loadedAgentPk,
                    localFile: _certificateFile,
                    fileName: _certificateLabel,
                  );
                },
                child: const Text('Download certificate'),
              ),
            ],
          ],
        );
      },
    );
  }

  Widget _retentionTableInCard({
    required double viewportHeight,
    required double parentWidth,
  }) {
    final tableColumn = Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        _retentionTableHeader(),
        ..._filteredVehicleTypes.map(_retentionDataRow),
      ],
    );

    return ClipRRect(
      borderRadius: BorderRadius.circular(8),
      child: Container(
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(8),
          border: Border.all(color: const Color(0xFFE2E8F0)),
        ),
        child: SizedBox(
          height: viewportHeight,
          width: double.infinity,
          child: Scrollbar(
            thumbVisibility: true,
            child: SingleChildScrollView(
              scrollDirection: Axis.vertical,
              primary: false,
              child: ConstrainedBox(
                constraints: BoxConstraints(minWidth: parentWidth),
                child: tableColumn,
              ),
            ),
          ),
        ),
      ),
    );
  }

  /// Table shell with a fixed header row; only data rows scroll (web two-column layout).
  Widget _retentionTableStickyHeaderCard() {
    return ClipRRect(
      borderRadius: BorderRadius.circular(8),
      child: Container(
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(8),
          border: Border.all(color: const Color(0xFFE2E8F0)),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            _retentionTableHeader(),
            Expanded(
              child: Scrollbar(
                thumbVisibility: true,
                child: ListView.builder(
                  padding: EdgeInsets.zero,
                  primary: false,
                  itemCount: _filteredVehicleTypes.length,
                  itemBuilder: (context, i) =>
                      _retentionDataRow(_filteredVehicleTypes[i]),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _retentionTitleSearchRow() {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Expanded(
          child: Text(
            'Retention rate by vehicle type',
            style: GoogleFonts.poppins(
              fontSize: 14,
              fontWeight: FontWeight.w600,
              color: const Color(0xFF1E293B),
            ),
          ),
        ),
        SizedBox(
          width: 220,
          child: ThemedSearchField(
            hintText: 'Search vehicle type and segment',
            backgroundColor: Colors.white,
            txtHeight: 34,
            controller: _retentionSearchCtrl,
            onChanged: (_) => setState(() {}),
          ),
        ),
      ],
    );
  }

  /// [expandTableHeight]: when true (web two-column layout), the table fills remaining
  /// height beside Partner Details. When false (mobile), uses list/cards and vertical stack.
  ///
  /// [showSectionTitleRow]: when false, the title + search row is omitted (shown beside
  /// Partner Details in the parent [Row]).
  Widget _retentionSection(
    BuildContext context, {
    bool expandTableHeight = false,
    bool showSectionTitleRow = true,
  }) {
    final mobile = ResponsiveLayout.isMobile(context);

    if (mobile) {
      return Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              Text(
                'Retention rate by vehicle type',
                style: GoogleFonts.poppins(
                  fontSize: 14,
                  fontWeight: FontWeight.w600,
                  color: const Color(0xFF1E293B),
                ),
              ),
              const SizedBox(height: 10),
              ThemedSearchField(
                hintText: 'Search vehicle type',
                backgroundColor: Colors.white,
                txtHeight: 36,
                txtwidth: double.infinity,
                controller: _retentionSearchCtrl,
                onChanged: (_) => setState(() {}),
              ),
            ],
          ),
          const SizedBox(height: 12),
          _retentionMobileList(context),
          const SizedBox(height: 12),
          _retentionSaveAllButtonBottom(context),
        ],
      );
    }

    if (!showSectionTitleRow) {
      assert(expandTableHeight, 'showSectionTitleRow false is only used with expandTableHeight');
      return Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(child: _retentionTableStickyHeaderCard()),
          const SizedBox(height: 12),
          _retentionSaveAllButtonBottom(context),
        ],
      );
    }

    final Widget tableArea;
    if (expandTableHeight) {
      tableArea = Expanded(
        child: _retentionTableStickyHeaderCard(),
      );
    } else {
      tableArea = LayoutBuilder(
        builder: (context, constraints) {
          final parentW = constraints.maxWidth.isFinite
              ? constraints.maxWidth
              : MediaQuery.sizeOf(context).width;
          final screenH = MediaQuery.sizeOf(context).height;
          final viewportH = math.min(520.0, math.max(240.0, screenH * 0.42));
          return _retentionTableInCard(viewportHeight: viewportH, parentWidth: parentW);
        },
      );
    }

    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        _retentionTitleSearchRow(),
        const SizedBox(height: 12),
        tableArea,
        const SizedBox(height: 12),
        _retentionSaveAllButtonBottom(context),
      ],
    );
  }

  Widget _retentionSaveAllButtonBottom(BuildContext context) {
    final mobile = ResponsiveLayout.isMobile(context);
    return Align(
      alignment: mobile ? Alignment.center : Alignment.centerRight,
      child: FilledButton(
        onPressed: _savingAllRetention
            ? null
            : (_retentionTableEnabled && !_retentionActionsBusy)
                ? _saveAllRetentionRates
                : null,
        style: FilledButton.styleFrom(
          backgroundColor: const Color(0xFF2E7D6E),
          padding: EdgeInsets.symmetric(
            horizontal: mobile ? 20 : 24,
            vertical: 12,
          ),
        ),
        child: _savingAllRetention
            ? const SizedBox(
                width: 20,
                height: 20,
                child: CircularProgressIndicator(
                  strokeWidth: 2,
                  color: Colors.white,
                ),
              )
            : const Text('Save all retention rates'),
      ),
    );
  }

  /// Stacked cards on narrow screens (no forced horizontal scroll).
  Widget _retentionMobileList(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        for (final vt in _filteredVehicleTypes) _retentionMobileCard(vt),
      ],
    );
  }

  Widget _retentionMobileCard(Map<String, dynamic> vt) {
    final vehicleTypeId = _readInt(vt['vehicle_type_id'] ?? vt['id']);
    final segmentId = _readInt(vt['segment_id']);
    final key = _retentionKey(vehicleTypeId, segmentId);
    final name = _displayVehicleSegment(vt);
    final ctrl = _rateControllers[key];
    if (ctrl == null) return const SizedBox.shrink();

    return Padding(
      padding: const EdgeInsets.only(bottom: 10),
      child: DecoratedBox(
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(8),
          border: Border.all(color: const Color(0xFFE2E8F0)),
        ),
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              Text(name, style: _headerStyle),
              const SizedBox(height: 8),
              TextField(
                controller: ctrl,
                keyboardType: const TextInputType.numberWithOptions(decimal: true),
                inputFormatters: _retentionPercentFormatters,
                decoration: InputDecoration(
                  isDense: true,
                  filled: true,
                  fillColor: Colors.white,
                  hintText: '0–100%',
                  border: OutlineInputBorder(borderRadius: BorderRadius.circular(6)),
                  contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
                ),
              ),
              const SizedBox(height: 8),
              Align(
                alignment: Alignment.centerRight,
                child: TextButton(
                  onPressed: (_retentionTableEnabled && !_retentionActionsBusy)
                      ? () => _saveRowRetention(vt)
                      : null,
                  style: TextButton.styleFrom(
                    foregroundColor: const Color(0xFF2E7D6E),
                    backgroundColor: const Color(0xFFE8ECF0),
                    padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(20),
                    ),
                  ),
                  child: const Text('UPDATE'),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _retentionTableHeader() {
    return Container(
      padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 14),
      decoration: const BoxDecoration(
        color: Color(0xFFEDF2F9),
        border: Border(bottom: BorderSide(color: Color(0xFFE2E8F0))),
      ),
      child: Row(
        children: [
          Expanded(
            flex: 5,
            child: Text(
              'Vehicle type / Segment',
              style: _headerStyle,
              overflow: TextOverflow.ellipsis,
            ),
          ),
          Expanded(
            flex: 3,
            child: Text(
              'Retention %',
              style: _headerStyle,
              overflow: TextOverflow.ellipsis,
            ),
          ),
          SizedBox(
            width: 88,
            child: Text(
              'Action',
              style: _headerStyle,
              textAlign: TextAlign.center,
              overflow: TextOverflow.ellipsis,
            ),
          ),
        ],
      ),
    );
  }

  Widget _retentionDataRow(Map<String, dynamic> vt) {
    final vehicleTypeId = _readInt(vt['vehicle_type_id'] ?? vt['id']);
    final segmentId = _readInt(vt['segment_id']);
    final key = _retentionKey(vehicleTypeId, segmentId);
    final name = _displayVehicleSegment(vt);
    final ctrl = _rateControllers[key];
    if (ctrl == null) return const SizedBox.shrink();

    return Container(
      padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 12),
      decoration: const BoxDecoration(
        color: Colors.white,
        border: Border(bottom: BorderSide(color: Color(0xFFE5E7EB))),
      ),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Expanded(
            flex: 5,
            child: Text(
              name,
              style: _cellStyle,
              overflow: TextOverflow.ellipsis,
              maxLines: 2,
            ),
          ),
          Expanded(
            flex: 3,
            child: TextField(
              controller: ctrl,
              keyboardType: const TextInputType.numberWithOptions(decimal: true),
              inputFormatters: _retentionPercentFormatters,
              decoration: InputDecoration(
                isDense: true,
                filled: true,
                fillColor: Colors.white,
                hintText: '0–100%',
                border: OutlineInputBorder(borderRadius: BorderRadius.circular(6)),
                contentPadding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
              ),
            ),
          ),
          SizedBox(
            width: 88,
            child: Center(
              child: TextButton(
                onPressed: (_retentionTableEnabled && !_retentionActionsBusy)
                    ? () => _saveRowRetention(vt)
                    : null,
                style: TextButton.styleFrom(
                  foregroundColor: const Color(0xFF2E7D6E),
                  backgroundColor: const Color(0xFFE8ECF0),
                  minimumSize: Size.zero,
                  tapTargetSize: MaterialTapTargetSize.shrinkWrap,
                  padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(20),
                  ),
                ),
                child: const Text('UPDATE', style: TextStyle(fontSize: 11, fontWeight: FontWeight.w600)),
              ),
            ),
          ),
        ],
      ),
    );
  }

  static final _labelStyle = GoogleFonts.poppins(
    fontSize: 12,
    fontWeight: FontWeight.w500,
    color: const Color(0xFF334155),
  );

  static final _headerStyle = GoogleFonts.poppins(
    fontSize: 11,
    fontWeight: FontWeight.w600,
    color: const Color(0xFF1E293B),
  );

  static final _cellStyle = GoogleFonts.inter(fontSize: 12, color: const Color(0xFF0F172A));
}
