import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:geolocator/geolocator.dart';
import '../config/app_config.dart';
import '../models/kontrakan.dart';
import '../models/laundry.dart';
import '../models/user.dart';
import '../services/auth_service.dart';
import '../services/server_discovery_service.dart';
import '../widgets/kontrakan_card.dart';
import '../widgets/laundry_card.dart';

class RecommendationScreen extends StatefulWidget {
  final String category;

  const RecommendationScreen({Key? key, required this.category})
    : super(key: key);

  @override
  State<RecommendationScreen> createState() => _RecommendationScreenState();
}

class _RecommendationScreenState extends State<RecommendationScreen> {
  bool _isLoading = false;
  bool _hasCalculated = false;
  List<dynamic> _recommendations = [];
  String? _errorMessage;
  bool _noData =
      false; // true = memang tidak ada data, false = filter terlalu ketat

  // User info
  final _authService = AuthService();
  User? _currentUser;

  // ============================================================================
  // QUESTIONNAIRE STATE (Smart Questions untuk mahasiswa)
  // ============================================================================
  bool _showQuestionnaire = false; // Show input view by default
  bool _loadingRange = true; // Loading range data

  // Range data dari database
  int _hargaMin = 0;
  int _hargaMax = 10000000;
  List<String> _availableFasilitas = [];
  // Laundry specific data
  List<String> _availableJenisLayanan = [];
  // rating removed by request

  // Q1: Budget
  double? _budgetSelected; // null = belum pilih

  // Q2: Required Facilities (checkbox)
  Set<String> _selectedFacilities =
      {}; // e.g. {'WiFi', 'AC', 'Dapur', 'Parkir', 'Air Saniter'}

  // Q3: Distance preference
  String _distancePreference =
      'sedang'; // 'dekat', 'sedang', 'jauh_ok', 'tidak_peduli'

  // Q4: Room preference
  String _roomPreference =
      'tidak_peduli'; // '1_kamar', '2_3_kamar', '4_plus_kamar', 'tidak_peduli'

  // Bobot values (percentage, total must = 100) - CALCULATED FROM QUESTIONNAIRE
  // Default: profil mahasiswa
  int _bobotHarga = 50;
  int _bobotJarak = 20;
  int _bobotKriteria3 = 15; // jumlah_kamar (kontrakan) or kecepatan (laundry)
  int _bobotKriteria4 = 15; // fasilitas (kontrakan) or layanan (laundry)

  // Jenis layanan selection for laundry
  String _selectedJenisLayanan = 'harian';
  // Laundry quick preset and antar/jemput
  String _selectedPreset = 'Normal';
  bool _antarJemput = false;

  // Location values untuk referensi jarak (deteksi lokasi user)
  double? _userLatitude;
  double? _userLongitude;
  bool _isDetectingLocation = false;

  String get _kriteria3Label =>
      widget.category == 'kontrakan' ? 'Jumlah Kamar' : 'Kecepatan Layanan';
  String get _kriteria4Label => 'Fasilitas';

  int get _totalBobot =>
      _bobotHarga + _bobotJarak + _bobotKriteria3 + _bobotKriteria4;

  Color get _categoryColor => widget.category == 'kontrakan'
      ? const Color(0xFF1565C0)
      : const Color(0xFF00897B);

  @override
  void initState() {
    super.initState();
    // Default bobot: profil mahasiswa (akan di-override oleh questionnaire)

    _bobotHarga = 50;
    _bobotJarak = 20;
    _bobotKriteria3 = 15;
    _bobotKriteria4 = 15;

    // Load user info
    _loadUser();

    // Load range data untuk questionnaire (kontrakan & laundry)
    if (widget.category == 'kontrakan' || widget.category == 'laundry') {
      _loadRangeData();

      // Safety fallback: jika API lambat atau menggantung, paksa fallback setelah 5s
      Future.delayed(const Duration(seconds: 5), () {
        if (!mounted) return;
        if (_loadingRange) {
          setState(() {
            _loadingRange = false;
            if (_availableFasilitas.isEmpty) {
              _availableFasilitas = [
                'WiFi',
                'Parkir',
                'Dapur Bersama',
                'Lemari',
                'Air Panas',
              ];
            }
            if (_hargaMin == _hargaMax) {
              _hargaMax = _hargaMin + 500000;
            }
          });
        }
      });
    }

    // Auto-detect lokasi untuk laundry
    if (widget.category == 'laundry') {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _detectUserLocation();
      });
    }
  }

  Widget _buildBobotStackedBar() {
    final items = _getBobotItems();
    final values = items.map((e) => e['value'] as int).toList();

    final colors = [
      _categoryColor.withOpacity(1.0),
      _categoryColor.withOpacity(0.78),
      _categoryColor.withOpacity(0.56),
      _categoryColor.withOpacity(0.34),
    ];

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        ClipRRect(
          borderRadius: BorderRadius.circular(999),
          child: LayoutBuilder(
            builder: (ctx, constraints) {
              final fullWidth = constraints.maxWidth;
              final widths = <double>[];
              double used = 0;
              for (int i = 0; i < values.length; i++) {
                if (i == values.length - 1) {
                  widths.add((fullWidth - used).clamp(0, fullWidth));
                } else {
                  final w = fullWidth * (values[i] / 100.0);
                  widths.add(w);
                  used += w;
                }
              }

              return SizedBox(
                height: 14,
                child: Row(
                  children: List.generate(values.length, (i) {
                    final isFirst = i == 0;
                    return InkWell(
                      onTap: () => _showBobotPicker(i),
                      child: Container(
                        width: widths[i],
                        decoration: BoxDecoration(
                          color: colors[i],
                          border: isFirst
                              ? null
                              : const Border(
                                  left: BorderSide(color: Colors.white, width: 2),
                                ),
                        ),
                      ),
                    );
                  }),
                ),
              );
            },
          ),
        ),
        const SizedBox(height: 8),
        Text(
          'Ringkasan bobot (tap segmen untuk edit)',
          style: TextStyle(fontSize: 11, color: Colors.grey[500]),
        ),
      ],
    );
  }

  Widget _buildBobotRows() {
    final items = _getBobotItems();

    return Column(
      children: List.generate(items.length, (i) {
        final item = items[i];
        return Padding(
          padding: EdgeInsets.only(bottom: i == items.length - 1 ? 0 : 10),
          child: _buildBobotRow(
            index: i,
            label: item['label'] as String,
            icon: item['icon'] as IconData,
            tipe: item['tipe'] as String,
            tipeDesc: item['tipeDesc'] as String,
            value: item['value'] as int,
          ),
        );
      }),
    );
  }

  Widget _buildBobotRow({
    required int index,
    required String label,
    required IconData icon,
    required String tipe,
    required String tipeDesc,
    required int value,
  }) {
    final isCost = tipe.toLowerCase() == 'cost';
    final percent = value.clamp(0, 100);
    final priorityColor = _getPriorityColor(value);

    return InkWell(
      onTap: () => _showBobotPicker(index),
      borderRadius: BorderRadius.circular(14),
      child: Container(
        padding: const EdgeInsets.all(12),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(14),
          border: Border.all(color: const Color(0xFFE4EDF7)),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Container(
                  padding: const EdgeInsets.all(8),
                  decoration: BoxDecoration(
                    color: _categoryColor.withOpacity(0.1),
                    borderRadius: BorderRadius.circular(10),
                  ),
                  child: Icon(icon, size: 18, color: _categoryColor),
                ),
                const SizedBox(width: 10),
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        label,
                        style: TextStyle(
                          fontSize: 14,
                          fontWeight: FontWeight.w700,
                          color: Colors.grey[850],
                        ),
                      ),
                      const SizedBox(height: 2),
                      Text(
                        tipeDesc,
                        style: TextStyle(fontSize: 11, color: Colors.grey[500]),
                        maxLines: 1,
                        overflow: TextOverflow.ellipsis,
                      ),
                    ],
                  ),
                ),
                const SizedBox(width: 8),
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(10),
                    border: Border.all(color: _categoryColor.withOpacity(0.3)),
                  ),
                  child: Text(
                    '$percent%',
                    style: TextStyle(
                      fontSize: 14,
                      fontWeight: FontWeight.w800,
                      color: _categoryColor,
                    ),
                  ),
                ),
                const SizedBox(width: 6),
                Icon(Icons.chevron_right, color: Colors.grey[400]),
              ],
            ),
            const SizedBox(height: 10),
            Row(
              children: [
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                  decoration: BoxDecoration(
                    color: priorityColor.withOpacity(0.12),
                    borderRadius: BorderRadius.circular(999),
                  ),
                  child: Text(
                    'Prioritas ${_getPriorityLabel(value)}',
                    style: TextStyle(
                      fontSize: 11,
                      fontWeight: FontWeight.w600,
                      color: priorityColor,
                    ),
                  ),
                ),
                const Spacer(),
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
                  decoration: BoxDecoration(
                    color: isCost
                        ? Colors.orange.withOpacity(0.15)
                        : Colors.green.withOpacity(0.15),
                    borderRadius: BorderRadius.circular(6),
                  ),
                  child: Text(
                    isCost ? 'Cost' : 'Benefit',
                    style: TextStyle(
                      fontSize: 10,
                      fontWeight: FontWeight.w700,
                      color: isCost ? Colors.orange[800] : Colors.green[800],
                    ),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 10),
            ClipRRect(
              borderRadius: BorderRadius.circular(999),
              child: Stack(
                children: [
                  Container(
                    height: 10,
                    color: _categoryColor.withOpacity(0.12),
                  ),
                  LayoutBuilder(
                    builder: (ctx, c) {
                      return Container(
                        height: 10,
                        width: c.maxWidth * (percent / 100.0),
                        color: _categoryColor,
                      );
                    },
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  List<Map<String, Object>> _getBobotItems() {
    return [
      {
        'label': 'Harga',
        'icon': Icons.payments_outlined,
        'tipe': 'Cost',
        'tipeDesc': 'Semakin murah semakin baik',
        'value': _bobotHarga,
      },
      {
        'label': 'Jarak',
        'icon': Icons.location_on_outlined,
        'tipe': 'Cost',
        'tipeDesc': 'Semakin dekat semakin baik',
        'value': _bobotJarak,
      },
      {
        'label': _kriteria3Label,
        'icon': widget.category == 'kontrakan'
            ? Icons.bed_outlined
            : Icons.speed_outlined,
        'tipe': 'Benefit',
        'tipeDesc': widget.category == 'kontrakan'
            ? 'Semakin banyak semakin baik'
            : 'Semakin cepat semakin baik',
        'value': _bobotKriteria3,
      },
      {
        'label': _kriteria4Label,
        'icon': widget.category == 'kontrakan'
            ? Icons.wifi_outlined
            : Icons.local_laundry_service_outlined,
        'tipe': 'Benefit',
        'tipeDesc': widget.category == 'kontrakan'
            ? 'Semakin lengkap semakin baik'
            : 'Semakin lengkap semakin baik',
        'value': _bobotKriteria4,
      },
    ];
  }

  void _showBobotPicker(int index) {
    final items = _getBobotItems();
    final item = items[index];
    final label = item['label'] as String;
    final icon = item['icon'] as IconData;
    final tipeDesc = item['tipeDesc'] as String;

    final currentValues = [
      _bobotHarga,
      _bobotJarak,
      _bobotKriteria3,
      _bobotKriteria4,
    ];

    final options = _getBobotOptionsFor(index);
    final selected = currentValues[index];

    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
      ),
      builder: (ctx) {
        return SafeArea(
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  children: [
                    Container(
                      padding: const EdgeInsets.all(10),
                      decoration: BoxDecoration(
                        color: _categoryColor.withOpacity(0.1),
                        borderRadius: BorderRadius.circular(12),
                      ),
                      child: Icon(icon, color: _categoryColor),
                    ),
                    const SizedBox(width: 12),
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            label,
                            style: const TextStyle(
                              fontSize: 16,
                              fontWeight: FontWeight.w800,
                            ),
                          ),
                          const SizedBox(height: 2),
                          Text(
                            tipeDesc,
                            style: TextStyle(fontSize: 12, color: Colors.grey[600]),
                          ),
                        ],
                      ),
                    ),
                    Container(
                      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(10),
                        border: Border.all(color: _categoryColor.withOpacity(0.3)),
                      ),
                      child: Text(
                        '$selected%',
                        style: TextStyle(
                          fontSize: 14,
                          fontWeight: FontWeight.w800,
                          color: _categoryColor,
                        ),
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 10),
                Text(
                  'Pilih bobot. Total otomatis diseimbangkan menjadi 100%.',
                  style: TextStyle(fontSize: 12, color: Colors.grey[600]),
                ),
                const SizedBox(height: 12),
                Wrap(
                  spacing: 10,
                  runSpacing: 10,
                  children: options.map((v) {
                    final isSel = v == selected;
                    return InkWell(
                      borderRadius: BorderRadius.circular(12),
                      onTap: () {
                        _updateBobot(index, v);
                        Navigator.of(ctx).pop();
                      },
                      child: Container(
                        padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
                        decoration: BoxDecoration(
                          color: isSel ? _categoryColor : Colors.white,
                          borderRadius: BorderRadius.circular(12),
                          border: Border.all(
                            color: isSel
                                ? _categoryColor
                                : const Color(0xFFE4EDF7),
                            width: isSel ? 2 : 1,
                          ),
                        ),
                        child: Text(
                          '$v%',
                          style: TextStyle(
                            fontSize: 14,
                            fontWeight: FontWeight.w800,
                            color: isSel ? Colors.white : Colors.grey[800],
                          ),
                        ),
                      ),
                    );
                  }).toList(),
                ),
                const SizedBox(height: 12),
              ],
            ),
          ),
        );
      },
    );
  }

  /// Load range data (min/max harga, jarak, kamar) dari API
  Future<void> _loadRangeData() async {
    try {
      final endpoint = widget.category == 'kontrakan' ? '/kontrakan/range' : '/laundry/range';
      final url = Uri.parse('${AppConfig.baseUrl}$endpoint');
      final response = await http.get(url).timeout(const Duration(seconds: 10));

      if (response.statusCode == 200) {
        final json = jsonDecode(response.body);
        if (json['success'] == true) {
          final data = json['data'];
          if (mounted) {
            setState(() {
              _hargaMin = data['harga']['min'] ?? 0;
              _hargaMax = data['harga']['max'] ?? 10000000;
              if (widget.category != 'kontrakan') {
                _availableJenisLayanan = List<String>.from(data['jenis_layanan'] ?? []);
              }

              _availableFasilitas = List<String>.from(data['fasilitas'] ?? []);
              if (_availableFasilitas.isEmpty) {
                _availableFasilitas = ['Antar Jemput', 'Express', 'Paket Kiloan', 'Satuan'];
              }

              _loadingRange = false;
            });
          }
        }
      }
    } catch (e) {
      debugPrint('Load range data error: $e');
      if (mounted) {
        // Provide safe fallbacks so dropdowns appear even when the API fails
        setState(() {
          _loadingRange = false;
          if (_availableFasilitas.isEmpty) {
            _availableFasilitas = [
              'WiFi',
              'Parkir',
              'Dapur Bersama',
              'Lemari',
              'Air Panas',
            ];
          }
          if (_hargaMin == _hargaMax) {
            // ensure some sensible max for budget dropdown
            _hargaMax = _hargaMin + 500000; // add 500k fallback
          }
        });
      }
    }
  }

  Future<void> _loadUser() async {
    try {
      // Use cached user first (no API call needed)
      if (_authService.currentUser != null) {
        if (!mounted) return;
        setState(() => _currentUser = _authService.currentUser);
        return;
      }
      // Fallback: load from SharedPreferences via API
      await _authService.loadToken();
      if (!mounted) return;
      setState(() => _currentUser = _authService.currentUser);
    } catch (e) {
      debugPrint('Load user error: $e');
    }
  }

  /// ============================================================================
  /// AUTO-CALCULATE BOBOT FROM QUESTIONNAIRE ANSWERS
  /// ============================================================================
  /// Smart logic: infer user priority dari jawaban tanpa perlu slider
  /// IMPORTANT: Always ensure total = 100% (auto-normalize)
  void _calculateBobotFromQuestionnaire() {
    // Start with base values
    double hargaBobot = 50.0;
    double jarakBobot = 20.0;
    double fasilitasBobot = 15.0;
    double kamarBobot = 15.0;

    // Q1: Budget adjustment (sesuai data real dari database)
    if (_budgetSelected != null) {
      double budgetRange = (_hargaMax - _hargaMin).toDouble();
      double budgetPercent =
          (_budgetSelected! - _hargaMin.toDouble()) / budgetRange;

      if (budgetPercent < 0.3) {
        // Budget kecil (bottom 30%) → harga SUPER penting, tapi kamar tetap relevan
        hargaBobot = 70.0;
        fasilitasBobot = 15.0;
        jarakBobot = 10.0;
        kamarBobot = 5.0; // ← Kamar tetap penting (tidak 0%)
      } else if (budgetPercent < 0.7) {
        // Budget sedang (30-70%) → balanced
        hargaBobot = 50.0;
        fasilitasBobot = 30.0;
        jarakBobot = 15.0;
        kamarBobot = 5.0;
      } else {
        // Budget besar (top 30%) → fasilitas lebih penting
        hargaBobot = 30.0;
        fasilitasBobot = 35.0;
        jarakBobot = 20.0;
        kamarBobot = 15.0;
      }
    }

    // Q2: Facilities selected adjustment
    if (_selectedFacilities.isNotEmpty) {
      // Lebih banyak fasilitas critical → naikkan fasilitas weight
      if (_selectedFacilities.length >= 4) {
        fasilitasBobot += 10.0;
        // Kamar tetap penting, minimal 5%
        kamarBobot = (kamarBobot - 2.0).clamp(5.0, 40.0);
      }
    }

    // Q3: Distance preference adjustment
    if (_distancePreference == 'dekat') {
      jarakBobot += 15.0;
      // Jarak penting, tapi jangan reduce kamar terlalu banyak
      kamarBobot = (kamarBobot - 3.0).clamp(5.0, 40.0);
    } else if (_distancePreference == 'jauh_ok') {
      jarakBobot = (jarakBobot - 10.0).clamp(5.0, 40.0);
    }

    // Q4: Room preference adjustment
    // NEW LOGIC: 4+ kamar = very important, 2-3 kamar = medium, 1 kamar = low
    if (_roomPreference == '1_kamar') {
      // 1 kamar → kamar tidak terlalu penting (mahasiswa fokus hemat)
      kamarBobot = (kamarBobot - 5.0).clamp(5.0, 40.0);
      fasilitasBobot = (fasilitasBobot + 5.0).clamp(10.0, 50.0);
    } else if (_roomPreference == '2_3_kamar') {
      // 2-3 kamar → kamar agak penting
      kamarBobot = (kamarBobot + 10.0).clamp(5.0, 40.0);
      fasilitasBobot = (fasilitasBobot - 5.0).clamp(10.0, 40.0);
    } else if (_roomPreference == '4_plus_kamar') {
      // 4+ kamar → kamar SANGAT penting (premium selection)
      kamarBobot = (kamarBobot + 25.0).clamp(5.0, 40.0);
      fasilitasBobot = (fasilitasBobot - 15.0).clamp(10.0, 40.0);
    }

    // ============================================================
    // ENFORCE MINIMUM: Kamar ALWAYS >= 5% (penting untuk seleksi)
    // ============================================================
    kamarBobot = kamarBobot.clamp(5.0, 40.0);

    // ============================================================
    // NORMALIZE TO 100% - CRITICAL!
    // Simple proportional normalization (safest approach)
    // ============================================================
    double total = hargaBobot + jarakBobot + fasilitasBobot + kamarBobot;
    if (total > 0 && total != 100.0) {
      double factor = 100.0 / total;
      hargaBobot = (hargaBobot * factor).round().toDouble();
      jarakBobot = (jarakBobot * factor).round().toDouble();
      fasilitasBobot = (fasilitasBobot * factor).round().toDouble();

      // Last one gets exact remainder to guarantee total = 100
      double distributed = hargaBobot + jarakBobot + fasilitasBobot;
      kamarBobot = 100.0 - distributed;
    }

    // Final sanity check: ensure kamarBobot >= 5
    if (kamarBobot < 5.0) {
      // Adjust other bobot to accommodate minimum kamar
      double adjustment = 5.0 - kamarBobot;
      kamarBobot = 5.0;

      // Reduce harga first (usually most critical)
      if (hargaBobot > adjustment + 10.0) {
        hargaBobot -= adjustment;
      } else {
        // If can't reduce harga enough, reduce others
        hargaBobot = (hargaBobot - adjustment / 2.0).clamp(20.0, 80.0);
        fasilitasBobot = (fasilitasBobot - adjustment / 2.0).clamp(10.0, 50.0);
      }

      // Re-normalize to ensure total = 100
      double total2 = hargaBobot + jarakBobot + fasilitasBobot + kamarBobot;
      if (total2 != 100.0) {
        double factor2 = 100.0 / total2;
        hargaBobot = (hargaBobot * factor2).round().toDouble();
        jarakBobot = (jarakBobot * factor2).round().toDouble();
        fasilitasBobot = (fasilitasBobot * factor2).round().toDouble();

        double distributed2 = hargaBobot + jarakBobot + fasilitasBobot;
        kamarBobot = 100.0 - distributed2;
      }
    }

    // Final sanity check
    if (hargaBobot + jarakBobot + fasilitasBobot + kamarBobot != 100.0) {
      // If something weird happened, use defaults
      hargaBobot = 50.0;
      jarakBobot = 20.0;
      fasilitasBobot = 15.0;
      kamarBobot = 15.0;
    }

    setState(() {
      _bobotHarga = hargaBobot.toInt();
      _bobotJarak = jarakBobot.toInt();
      _bobotKriteria4 = fasilitasBobot.toInt(); // Fasilitas
      _bobotKriteria3 = kamarBobot.toInt(); // Kamar
    });
  }

  /// Check if questionnaire complete
  bool _isQuestionnaireComplete() {
    // Facilities optional: allow submit tanpa memilih fasilitas
    if (widget.category == 'kontrakan') {
      return _budgetSelected != null && _distancePreference.isNotEmpty && _roomPreference.isNotEmpty;
    } else {
      // Laundry: require jenis layanan + budget
      return _budgetSelected != null && _distancePreference.isNotEmpty && _selectedJenisLayanan.isNotEmpty;
    }
  }

  /// ============================================================================
  /// AUTO-BALANCE BOBOT (existing function - keep as is)
  /// ============================================================================
  /// percentage proportionally among the other three (min 10% each),
  /// always snapping to multiples of 5 so displayed values match actual sum.
  void _updateBobot(int index, int newValue) {
    setState(() {
      List<int> bobots = [
        _bobotHarga,
        _bobotJarak,
        _bobotKriteria3,
        _bobotKriteria4,
      ];
      if (newValue == bobots[index]) return;

      // Clamp newValue to valid range and snap to multiple of 5
      newValue = ((newValue.clamp(10, 70)) ~/ 5) * 5;
      bobots[index] = newValue;

      int remaining = 100 - newValue;
      List<int> otherIdx = [0, 1, 2, 3].where((i) => i != index).toList();
      int otherSum = otherIdx.fold(0, (sum, i) => sum + bobots[i]);

      List<int> newOther = List.filled(otherIdx.length, 0);

      if (otherSum == 0) {
        // Edge case: distribute equally in steps of 5
        int share = ((remaining / otherIdx.length / 5).round() * 5).clamp(
          10,
          70,
        );
        for (int i = 0; i < otherIdx.length; i++) {
          newOther[i] = share;
        }
      } else {
        // Proportional redistribution snapped to nearest multiple of 5
        for (int i = 0; i < otherIdx.length - 1; i++) {
          double proportional = bobots[otherIdx[i]] * remaining / otherSum;
          newOther[i] = ((proportional / 5).round() * 5).clamp(10, 70);
        }
        // Last one gets exact remainder to guarantee total = 100
        int distributed = newOther
            .take(newOther.length - 1)
            .fold(0, (a, b) => a + b);
        int lastVal = remaining - distributed;
        newOther[newOther.length - 1] = lastVal.clamp(10, 70);
      }

      // Apply computed values
      for (int i = 0; i < otherIdx.length; i++) {
        bobots[otherIdx[i]] = newOther[i];
      }

      // Final safety: force total == 100 by adjusting the largest other bobot
      // without snapping to 5 (exact correction takes priority over pretty numbers)
      int total = bobots.reduce((a, b) => a + b);
      if (total != 100) {
        int diff = 100 - total;
        int adjustIdx = otherIdx.reduce(
          (a, b) => bobots[a] >= bobots[b] ? a : b,
        );
        bobots[adjustIdx] = (bobots[adjustIdx] + diff).clamp(5, 75);
      }

      _bobotHarga = bobots[0];
      _bobotJarak = bobots[1];
      _bobotKriteria3 = bobots[2];
      _bobotKriteria4 = bobots[3];
    });
  }

  /// Get the maximum dropdown value for a given bobot index
  int _getMaxBobot(int index) {
    int othersMin = 0;
    for (int i = 0; i < 4; i++) {
      if (i != index) othersMin += 10; // minimum 10% each
    }
    return (100 - othersMin).clamp(10, 70); // max 70
  }

  List<int> _getBobotOptionsFor(int index) {
    int max = _getMaxBobot(index);
    return List.generate(((max - 10) ~/ 5) + 1, (i) => 10 + i * 5);
  }

  String _getPriorityLabel(int value) {
    if (value <= 20) return 'Rendah';
    if (value <= 35) return 'Sedang';
    if (value <= 50) return 'Tinggi';
    return 'Prioritas';
  }

  Color _getPriorityColor(int value) {
    if (value <= 20) return const Color(0xFF8E8E93);
    if (value <= 35) return const Color(0xFF00A389);
    if (value <= 50) return const Color(0xFF2F80ED);
    return const Color(0xFF7B61FF);
  }

  bool _isConnectivityError(Object error) {
    final msg = error.toString().toLowerCase();
    return error is TimeoutException ||
        error is SocketException ||
        error is http.ClientException ||
        msg.contains('future not completed') ||
        msg.contains('connection') ||
        msg.contains('timed out');
  }

  Future<void> _resetConnectionAndRetry() async {
    setState(() {
      _isLoading = true;
      _errorMessage = null;
      _noData = false;
    });

    try {
      await ServerDiscoveryService.resetCache();
      final found = await ServerDiscoveryService.discover();

      if (!mounted) return;

      if (found) {
        await _calculateSAW();
      } else {
        setState(() {
          _isLoading = false;
          _hasCalculated = true;
          _errorMessage =
              'Reset koneksi selesai, tetapi server belum ditemukan. Pastikan backend Laravel aktif di jaringan yang sama.';
        });
      }
    } catch (e) {
      if (!mounted) return;
      setState(() {
        _isLoading = false;
        _hasCalculated = true;
        _errorMessage = 'Gagal reset koneksi: $e';
      });
    }
  }

  Future<void> _calculateSAW() async {
    if (_totalBobot != 100) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('Total bobot harus 100%! Saat ini: $_totalBobot%'),
          backgroundColor: Colors.red,
        ),
      );
      return;
    }

    // Validate location for laundry
    if (widget.category == 'laundry' && _userLatitude == null) {
      // Auto-detect location first, then re-calculate
      await _detectUserLocation();
      if (!mounted) return;
      // If still no location after detection attempt, warn and stop
      if (_userLatitude == null || _userLongitude == null) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text(
              'Lokasi belum terdeteksi. Aktifkan GPS dan coba lagi.',
            ),
            backgroundColor: Colors.orange,
          ),
        );
        return;
      }
    }

    setState(() {
      _isLoading = true;
      _errorMessage = null;
      _noData = false;
    });

    final endpoint = widget.category == 'kontrakan'
        ? '/saw/calculate/kontrakan'
        : '/saw/calculate/laundry';

    try {
      final bodyParams = <String, dynamic>{};
      bodyParams['bobot_harga'] = _bobotHarga;
      bodyParams['bobot_jarak'] = _bobotJarak;

      if (widget.category == 'kontrakan') {
        bodyParams['bobot_jumlah_kamar'] = _bobotKriteria3;
        bodyParams['bobot_fasilitas'] = _bobotKriteria4;
        // CRITICAL: Send selected facilities to API for filtering
        bodyParams['selected_facilities'] = _selectedFacilities.toList();
      } else {
        final hasAntarJemput = _selectedFacilities.any(
          (f) => f.toLowerCase().contains('antar'),
        );
        bodyParams['bobot_kecepatan'] = _bobotKriteria3;
        bodyParams['bobot_layanan'] = _bobotKriteria4;
        // Choose selected jenis_layanan, or fall back to a sensible default
        final preferredJenis = _availableJenisLayanan.firstWhere(
          (e) => e.toLowerCase().contains('cuci'),
          orElse: () => _availableJenisLayanan.isNotEmpty ? _availableJenisLayanan.first : 'Cuci Baju');
        bodyParams['jenis_layanan'] = _selectedJenisLayanan.isNotEmpty ? _selectedJenisLayanan : preferredJenis;
        // optional: send selected facilities for laundry (e.g., express, antar)
        bodyParams['selected_facilities'] = _selectedFacilities.toList();
        // send preset and antar/jemput preferences
        bodyParams['preset'] = _selectedPreset;
        bodyParams['antar_jemput'] = hasAntarJemput ? 1 : 0;
        // rating filter removed
      }

      if (widget.category == 'laundry' &&
          _userLatitude != null &&
          _userLongitude != null) {
        bodyParams['user_lat'] = _userLatitude;
        bodyParams['user_lng'] = _userLongitude;
      }

      final response = await http
          .post(
            Uri.parse('${AppConfig.baseUrl}$endpoint'),
            headers: {
              'Content-Type': 'application/json',
              'Accept': 'application/json',
            },
            body: json.encode(bodyParams),
          )
          .timeout(const Duration(seconds: 15));

      if (!mounted) return;

      if (response.statusCode == 200) {
        final data = json.decode(response.body);
        if (data['success'] == true) {
          setState(() {
            _recommendations = data['data']['hasil'] ?? [];
            _hasCalculated = true;
          });
        } else {
          setState(() {
            _errorMessage = data['message'] ?? 'Terjadi kesalahan';
            _hasCalculated = true;
          });
        }
      } else if (response.statusCode == 404) {
        final data = json.decode(response.body);
        setState(() {
          _errorMessage = data['message'] ?? 'Tidak ada data ditemukan';
          _noData = data['no_data'] == true;
          _recommendations = [];
          _hasCalculated = true;
        });
      } else {
        setState(() {
          _errorMessage = 'Gagal memuat data (${response.statusCode})';
          _hasCalculated = true;
        });
      }
    } catch (e) {
      debugPrint('SAW API Error: $e');
      debugPrint('URL: ${AppConfig.baseUrl}$endpoint');
      if (!mounted) return;
      final canReset = _isConnectivityError(e);
      setState(() {
        _errorMessage = canReset
            ? 'Tidak dapat terhubung ke server (${AppConfig.baseUrl}). Silakan tekan tombol Reset Koneksi.\n\nDetail: $e'
            : 'Tidak dapat terhubung ke server (${AppConfig.baseUrl}). Periksa koneksi internet Anda dan coba lagi.\n\nDetail: $e';
        _hasCalculated = true;
      });
    } finally {
      if (mounted) {
        setState(() {
          _isLoading = false;
        });
      }
    }
  }

  Future<void> _detectUserLocation() async {
    // Guard: prevent re-entrant / duplicate calls
    if (_isDetectingLocation) return;

    setState(() => _isDetectingLocation = true);
    try {
      bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
      if (!serviceEnabled) {
        if (!mounted) return;
        // Offer user to open location settings
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: const Text('GPS mati. Buka pengaturan lokasi?'),
            action: SnackBarAction(
              label: 'Buka',
              onPressed: () => Geolocator.openLocationSettings(),
            ),
            backgroundColor: Colors.red,
          ),
        );
        setState(() => _isDetectingLocation = false);
        return;
      }

      LocationPermission permission = await Geolocator.checkPermission();
      if (permission == LocationPermission.denied) {
        permission = await Geolocator.requestPermission();
        if (permission == LocationPermission.denied) {
          if (!mounted) return;
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(
              content: Text('Izin lokasi ditolak'),
              backgroundColor: Colors.red,
            ),
          );
          setState(() => _isDetectingLocation = false);
          return;
        }
      }

      if (permission == LocationPermission.deniedForever) {
        if (!mounted) return;
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text('Izin lokasi ditolak permanen. Ubah di pengaturan.'),
            backgroundColor: Colors.red,
          ),
        );
        setState(() => _isDetectingLocation = false);
        return;
      }

      // Primary attempt: get current position with timeout
      Position? position;
      try {
        position = await Geolocator.getCurrentPosition(
          desiredAccuracy: LocationAccuracy.high,
        ).timeout(
          const Duration(seconds: 15),
          onTimeout: () => throw TimeoutException('Deteksi lokasi timeout'),
        );
      } catch (e) {
        debugPrint('getCurrentPosition failed: $e');
      }

      // Fallback: try last known position
      if (position == null) {
        try {
          position = await Geolocator.getLastKnownPosition();
          debugPrint('getLastKnownPosition result: $position');
        } catch (e) {
          debugPrint('getLastKnownPosition failed: $e');
        }
      }

      // Further fallback: subscribe briefly to position stream
      if (position == null) {
        try {
          final stream = Geolocator.getPositionStream(
            locationSettings: const LocationSettings(
              accuracy: LocationAccuracy.high,
              distanceFilter: 10,
            ),
          );
          position = await stream.first.timeout(const Duration(seconds: 10));
          debugPrint('getPositionStream first: $position');
        } catch (e) {
          debugPrint('getPositionStream failed: $e');
        }
      }

      if (position == null) {
        if (!mounted) return;
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text('Gagal mendapatkan lokasi. Pastikan GPS dan izin sudah aktif.'),
            backgroundColor: Colors.red,
          ),
        );
        setState(() => _isDetectingLocation = false);
        return;
      }

      if (!mounted) return;
      setState(() {
        _userLatitude = position!.latitude;
        _userLongitude = position!.longitude;
        _isDetectingLocation = false;
      });

      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('Lokasi berhasil dideteksi!'),
          backgroundColor: Colors.green,
          duration: Duration(seconds: 2),
        ),
      );
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(
            'Gagal mendeteksi lokasi: ${e.toString().replaceAll('Exception: ', '')}',
          ),
          backgroundColor: Colors.red,
        ),
      );
      setState(() => _isDetectingLocation = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    final categoryTitle = widget.category == 'kontrakan'
        ? 'Rekomendasi Kontrakan'
        : 'Rekomendasi Laundry';

    // Show questionnaire first for kontrakan and laundry (only before calculation)
    if ((widget.category == 'kontrakan' || widget.category == 'laundry') && _showQuestionnaire && !_hasCalculated) {
      return _buildQuestionnaireView(categoryTitle);
    }

    return Scaffold(
      backgroundColor: const Color(0xFFF3F7FB),
      appBar: AppBar(
        backgroundColor: _categoryColor,
        foregroundColor: Colors.white,
        elevation: 0,
        title: Text(
          categoryTitle,
          style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
        ),
        actions: [
          if (_hasCalculated)
            IconButton(
              icon: const Icon(Icons.refresh),
              tooltip: 'Hitung Ulang',
              onPressed: () => setState(() {
                _hasCalculated = false;
                _recommendations = [];
                _errorMessage = null;
                _noData = false;
              }),
            ),
        ],
      ),
      body: _hasCalculated ? _buildResultView() : _buildInputView(),
    );
  }

  /// ============================================================================
  /// QUESTIONNAIRE VIEW (Smart Questions untuk mahasiswa)
  /// ============================================================================
  /// ============================================================================
  /// DROPDOWN BUILDERS FOR QUESTIONNAIRE
  /// ============================================================================

  Widget _buildBudgetDropdown() {
    final range = (_hargaMax - _hargaMin).clamp(0, 100000000);
    final step = (range / 5).ceil().clamp(1, 100000000);
    List<double> budgetOptions = [];
    for (int i = 0; i <= 5; i++) {
      final value = _hargaMin + (i * step);
      budgetOptions.add(value.toDouble());
    }

    final label = _budgetSelected == null
        ? 'Pilih Budget...'
        : _formatCurrency(_budgetSelected!.toInt());

    return GestureDetector(
      onTap: () => _showBudgetModal(budgetOptions),
      child: Container(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
        decoration: BoxDecoration(
          border: Border.all(color: const Color(0xFFBDBDBD)),
          borderRadius: BorderRadius.circular(4),
          color: Colors.white,
        ),
        child: Row(
          children: [
            Expanded(child: Text(label, style: TextStyle(color: _budgetSelected == null ? const Color(0xFF999999) : Colors.black))),
            const SizedBox(width: 8),
            Icon(Icons.arrow_drop_down, color: Colors.grey[600]),
          ],
        ),
      ),
    );
  }

  Widget _buildFacilitiesDropdown() {
    if (_availableFasilitas.isEmpty) {
      return Padding(
        padding: const EdgeInsets.all(10),
        child: Text(
          'Fasilitas tidak tersedia',
          style: TextStyle(color: Colors.grey[600]),
        ),
      );
    }

    // Show as a single-line select field that opens a modal multi-select
    final placeholder = widget.category == 'laundry'
      ? 'Pilih Fasilitas (termasuk antar jemput)'
      : 'Pilih Fasilitas...';

    final summary = _selectedFacilities.isEmpty
      ? placeholder
      : _selectedFacilities.join(', ');

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        GestureDetector(
          onTap: _showFacilitiesModal,
          child: Container(
            padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
            decoration: BoxDecoration(
              border: Border.all(color: const Color(0xFFBDBDBD)),
              borderRadius: BorderRadius.circular(4),
              color: Colors.white,
            ),
            child: Row(
              children: [
                Expanded(
                  child: Text(
                    summary,
                    style: TextStyle(
                      color: _selectedFacilities.isEmpty
                          ? const Color(0xFF999999)
                          : Colors.black,
                    ),
                    maxLines: 2,
                    overflow: TextOverflow.ellipsis,
                  ),
                ),
                const SizedBox(width: 8),
                Icon(Icons.arrow_drop_down, color: Colors.grey[600]),
              ],
            ),
          ),
        ),
        if (_selectedFacilities.isNotEmpty) ...[
          const SizedBox(height: 12),
          Wrap(
            spacing: 8,
            runSpacing: 8,
            children: _selectedFacilities.map((facility) {
              return Chip(
                label: Text(facility, style: const TextStyle(fontSize: 12)),
                onDeleted: () {
                  setState(() => _selectedFacilities.remove(facility));
                },
                backgroundColor: _categoryColor.withOpacity(0.2),
                deleteIconColor: _categoryColor,
              );
            }).toList(),
          ),
        ],
      ],
    );
  }

  Widget _buildDistanceDropdown() {
    final distanceOptions = [
      {'label': 'Dekat (< 2km)', 'value': 'dekat'},
      {'label': 'Sedang (2-5km)', 'value': 'sedang'},
      {'label': 'Jauh OK (> 5km)', 'value': 'jauh_ok'},
      {'label': 'Tidak Peduli', 'value': 'tidak_peduli'},
    ];

    final label = distanceOptions
            .firstWhere((o) => o['value'] == _distancePreference, orElse: () => distanceOptions[1])['label'] ??
        'Pilih Jarak...';

    return GestureDetector(
      onTap: () => _showSingleChoiceModal('Pilih Jarak', distanceOptions,
          _distancePreference, (val) => setState(() => _distancePreference = val)),
      child: Container(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
        decoration: BoxDecoration(
          border: Border.all(color: const Color(0xFFBDBDBD)),
          borderRadius: BorderRadius.circular(4),
          color: Colors.white,
        ),
        child: Row(
          children: [
            Expanded(child: Text(label)),
            const SizedBox(width: 8),
            Icon(Icons.arrow_drop_down, color: Colors.grey[600]),
          ],
        ),
      ),
    );
  }

  Widget _buildRoomDropdown() {
    final roomOptions = [
      {'label': '1 Kamar (Hemat)', 'value': '1_kamar'},
      {'label': '2-3 Kamar (Sedang)', 'value': '2_3_kamar'},
      {'label': '4+ Kamar (Luas)', 'value': '4_plus_kamar'},
      {'label': 'Tidak Peduli', 'value': 'tidak_peduli'},
    ];

    final label = roomOptions
            .firstWhere((o) => o['value'] == _roomPreference, orElse: () => roomOptions[3])['label'] ??
        'Pilih Jumlah Kamar...';

    return GestureDetector(
      onTap: () => _showSingleChoiceModal('Pilih Jumlah Kamar', roomOptions,
          _roomPreference, (val) => setState(() => _roomPreference = val)),
      child: Container(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
        decoration: BoxDecoration(
          border: Border.all(color: const Color(0xFFBDBDBD)),
          borderRadius: BorderRadius.circular(4),
          color: Colors.white,
        ),
        child: Row(
          children: [
            Expanded(child: Text(label)),
            const SizedBox(width: 8),
            Icon(Icons.arrow_drop_down, color: Colors.grey[600]),
          ],
        ),
      ),
    );
  }

  Widget _buildJenisLaundryDropdown() {
    if (_availableJenisLayanan.isEmpty) {
      return Padding(
        padding: const EdgeInsets.all(10),
        child: Text(
          'Jenis layanan tidak tersedia',
          style: TextStyle(color: Colors.grey[600]),
        ),
      );
    }
    // Prefer a sensible default: any option containing 'cuci' (e.g., 'Cuci Baju')
    final preferred = _availableJenisLayanan.firstWhere(
        (e) => e.toLowerCase().contains('cuci'),
        orElse: () => _availableJenisLayanan.isNotEmpty ? _availableJenisLayanan.first : 'Cuci Baju');

    final displayValue = _selectedJenisLayanan.isNotEmpty ? _selectedJenisLayanan : preferred;

    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
      decoration: BoxDecoration(
        border: Border.all(color: const Color(0xFFBDBDBD)),
        borderRadius: BorderRadius.circular(4),
        color: Colors.white,
      ),
      child: Row(
        children: [
          Expanded(child: Text(displayValue, style: TextStyle(color: _selectedJenisLayanan.isEmpty ? const Color(0xFF666666) : Colors.black))),
          const SizedBox(width: 8),
          // Small edit affordance instead of full dropdown to keep default simple
          IconButton(
            padding: EdgeInsets.zero,
            constraints: const BoxConstraints(),
            icon: Icon(Icons.edit, color: Colors.grey[600]),
            onPressed: () => _showSingleChoiceModal('Pilih Jenis Layanan',
                _availableJenisLayanan.map((e) => {'label': e, 'value': e}).toList(), _selectedJenisLayanan,
                (val) => setState(() => _selectedJenisLayanan = val)),
          ),
        ],
      ),
    );
  }

  // rating UI removed per UX feedback

  Widget _buildLaundryPresets() {
    final presets = ['Normal', 'Cepat (Express)', 'Hemat'];
    return Row(
      children: presets.map((p) {
        final isSel = _selectedPreset == p;
        return Padding(
          padding: const EdgeInsets.only(right: 8),
          child: ChoiceChip(
            label: Text(p),
            selected: isSel,
            onSelected: (_) => setState(() => _selectedPreset = p),
            selectedColor: _categoryColor,
          ),
        );
      }).toList(),
    );
  }

  Widget _buildAntarJemputToggle() {
    return Row(
      children: [
        Switch(
          value: _antarJemput,
          onChanged: (v) => setState(() => _antarJemput = v),
          activeColor: _categoryColor,
        ),
        const SizedBox(width: 8),
        Text(_antarJemput ? 'Aktif' : 'Mati'),
      ],
    );
  }

  // Show a modal bottom sheet for multi-select facilities
  void _showFacilitiesModal() async {
    final selected = Set<String>.from(_selectedFacilities);

    await showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      builder: (ctx) {
        return StatefulBuilder(builder: (ctx2, setInner) {
          return Padding(
            padding: EdgeInsets.only(
                bottom: MediaQuery.of(ctx).viewInsets.bottom),
            child: Container(
              padding: const EdgeInsets.all(16),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      const Text('Pilih Fasilitas', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
                      TextButton(
                        onPressed: () {
                          setState(() {
                            _selectedFacilities = selected;
                          });
                          Navigator.of(ctx).pop();
                        },
                        child: const Text('Selesai'),
                      )
                    ],
                  ),
                  const SizedBox(height: 8),
                  Flexible(
                    child: SingleChildScrollView(
                      child: Column(
                        children: _availableFasilitas.map((f) {
                          final isSel = selected.contains(f);
                          return CheckboxListTile(
                            title: Text(f),
                            value: isSel,
                            onChanged: (v) => setInner(() => v == true ? selected.add(f) : selected.remove(f)),
                          );
                        }).toList(),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          );
        });
      },
    );
  }

  // Show a single-choice modal and call onSelected with chosen value
  void _showSingleChoiceModal(String title, List<Map<String, String>> options, String currentValue, Function(String) onSelected) async {
    String sel = currentValue;
    await showModalBottomSheet(
      context: context,
      builder: (ctx) {
        return StatefulBuilder(builder: (ctx2, setInner) {
          return Container(
            padding: const EdgeInsets.all(16),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(title, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
                    TextButton(
                      onPressed: () {
                        onSelected(sel);
                        Navigator.of(ctx).pop();
                      },
                      child: const Text('OK'),
                    )
                  ],
                ),
                const SizedBox(height: 8),
                ...options.map((o) {
                  final v = o['value'] ?? '';
                  final label = o['label'] ?? v;
                  return RadioListTile<String>(
                    value: v,
                    groupValue: sel,
                    title: Text(label),
                    onChanged: (val) => setInner(() => sel = val ?? sel),
                  );
                }).toList(),
              ],
            ),
          );
        });
      },
    );
  }

  // Show budget modal with radio-like quick-picker and option list
  void _showBudgetModal(List<double> options) async {
    double sel = _budgetSelected ?? (options.isNotEmpty ? options[(options.length / 2).floor()] : 0);

    await showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      builder: (ctx) {
        return StatefulBuilder(builder: (ctx2, setInner) {
          return Padding(
            padding: EdgeInsets.only(bottom: MediaQuery.of(ctx).viewInsets.bottom),
            child: Container(
              padding: const EdgeInsets.all(16),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      const Text('Pilih Budget', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
                      TextButton(
                        onPressed: () {
                          setState(() => _budgetSelected = sel);
                          Navigator.of(ctx).pop();
                        },
                        child: const Text('Selesai'),
                      )
                    ],
                  ),
                  const SizedBox(height: 12),
                  Wrap(
                    spacing: 8,
                    runSpacing: 8,
                    children: options.map((v) {
                      final label = _formatCurrency(v.toInt());
                      final isSel = sel == v;
                      return GestureDetector(
                        onTap: () => setInner(() => sel = v),
                        child: Container(
                          padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
                          decoration: BoxDecoration(
                            color: isSel ? _categoryColor : Colors.white,
                            borderRadius: BorderRadius.circular(8),
                            border: Border.all(color: isSel ? _categoryColor : const Color(0xFFE4EDF7)),
                          ),
                          child: Text(
                            label,
                            style: TextStyle(color: isSel ? Colors.white : Colors.black),
                          ),
                        ),
                      );
                    }).toList(),
                  ),
                  const SizedBox(height: 12),
                  // Also show full list as radio options for accessibility
                  ...options.map((v) {
                    return RadioListTile<double>(
                      value: v,
                      groupValue: sel,
                      title: Text(_formatCurrency(v.toInt())),
                      onChanged: (val) => setInner(() => sel = val ?? sel),
                    );
                  }).toList(),
                ],
              ),
            ),
          );
        });
      },
    );
  }

  /// ============================================================================
  /// QUESTIONNAIRE VIEW
  /// ============================================================================

  Widget _buildQuestionnaireView(String categoryTitle) {
    // Show loading state while fetching range data
    if (_loadingRange) {
      return Scaffold(
        backgroundColor: const Color(0xFFF3F7FB),
        appBar: AppBar(
          backgroundColor: _categoryColor,
          foregroundColor: Colors.white,
          elevation: 0,
          title: Text(
            categoryTitle,
            style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
          ),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              CircularProgressIndicator(color: _categoryColor),
              const SizedBox(height: 16),
              const Text(
                'Mempersiapkan pertanyaan...',
                style: TextStyle(fontSize: 14, color: Colors.black54),
              ),
            ],
          ),
        ),
      );
    }

    return Scaffold(
      backgroundColor: const Color(0xFFF3F7FB),
      appBar: AppBar(
        backgroundColor: _categoryColor,
        foregroundColor: Colors.white,
        elevation: 0,
        title: Text(
          categoryTitle,
          style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
        ),
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // Header
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(14),
                border: Border.all(color: const Color(0xFFE4EDF7)),
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Row(
                    children: [
                      Icon(
                        Icons.lightbulb_rounded,
                        size: 20,
                        color: _categoryColor,
                      ),
                      const SizedBox(width: 8),
                      const Expanded(
                        child: Text(
                          'Ceritakan Kebutuhan Mu',
                          style: TextStyle(
                            fontSize: 16,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 8),
                  Text(
                    widget.category == 'kontrakan'
                        ? 'Kami akan cari kontrakan terbaik sesuai budget & kebutuhan mu'
                        : 'Kami akan cari laundry terbaik sesuai budget & kebutuhan mu',
                    style: TextStyle(
                      fontSize: 13,
                      color: Colors.black.withOpacity(0.6),
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 20),
            // Questionnaire for kontrakan vs laundry
            if (widget.category == 'kontrakan') ...[
              _buildQuestionCard(
                title: '💰 Berapa Budget?',
                child: _buildBudgetDropdown(),
              ),
              const SizedBox(height: 16),
              _buildQuestionCard(
                title: '⭐ Fasilitas Wajib Ada?',
                child: _buildFacilitiesDropdown(),
              ),
              const SizedBox(height: 16),
              _buildQuestionCard(
                title: '📍 Jarak ke Kampus?',
                child: _buildDistanceDropdown(),
              ),
              const SizedBox(height: 16),
              _buildQuestionCard(
                title: '🛏️ Jumlah Kamar?',
                child: _buildRoomDropdown(),
              ),
            ] else ...[
              _buildQuestionCard(
                title: '🧾 Jenis Layanan',
                child: _buildJenisLaundryDropdown(),
              ),
              const SizedBox(height: 12),
              _buildQuestionCard(
                title: '⚡ Preset Cepat',
                child: _buildLaundryPresets(),
              ),
              const SizedBox(height: 12),
              _buildQuestionCard(
                title: '💰 Berapa Budget?',
                child: _buildBudgetDropdown(),
              ),
              const SizedBox(height: 16),
              _buildQuestionCard(
                title: '📍 Jarak ke Lokasi?',
                child: _buildDistanceDropdown(),
              ),
              const SizedBox(height: 16),
              // rating removed per UX feedback
              _buildQuestionCard(
                title: '🔸 Fasilitas (termasuk antar jemput)',
                child: _buildFacilitiesDropdown(),
              ),
            ],
            const SizedBox(height: 24),

            // Submit Button
            SizedBox(
              width: double.infinity,
              child: ElevatedButton(
                style: ElevatedButton.styleFrom(
                  backgroundColor: _categoryColor,
                  padding: const EdgeInsets.symmetric(vertical: 14),
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(10),
                  ),
                  disabledBackgroundColor: Colors.grey,
                ),
                onPressed: _isQuestionnaireComplete()
                    ? () {
                        _calculateBobotFromQuestionnaire();
                        setState(() => _hasCalculated = true);
                        // CRITICAL: Call API SAW to get recommendations with calculated bobot
                        _calculateSAW();
                      }
                    : null,
                child: Text(
                  widget.category == 'kontrakan' ? 'TEMUKAN KONTRAKAN' : 'TEMUKAN LAUNDRY',
                  style: TextStyle(
                    fontSize: 14,
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                    letterSpacing: 0.5,
                  ),
                ),
              ),
            ),
            const SizedBox(height: 24),
          ],
        ),
      ),
    );
  }

  // Helper widgets untuk questionnaire
  Widget _buildQuestionCard({required String title, required Widget child}) {
    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(14),
        border: Border.all(color: const Color(0xFFE4EDF7)),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            title,
            style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 14),
          child,
        ],
      ),
    );
  }

  /// Helper: Format currency to readable format
  String _formatCurrency(int value) {
    if (value >= 1000000) {
      return 'Rp ${(value / 1000000).toStringAsFixed(1)}jt';
    } else if (value >= 1000) {
      return 'Rp ${(value / 1000).toStringAsFixed(0)}rb';
    } else {
      return 'Rp $value';
    }
  }

  // ===================== INPUT VIEW =====================
  Widget _buildInputView() {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          _buildUserInfoCard(),
          const SizedBox(height: 16),
          _buildSimpleStepCard(),
          const SizedBox(height: 16),
          _buildMethodInfoCard(),
          const SizedBox(height: 16),
          if (widget.category == 'laundry') ...[
            _buildJenisLayananSection(),
            const SizedBox(height: 16),
          ],
          _buildBobotSection(),
          const SizedBox(height: 16),
          if (widget.category == 'laundry') ...[
            _buildLocationSection(),
            const SizedBox(height: 16),
          ],
          _buildCalculateButton(),
          const SizedBox(height: 24),
        ],
      ),
    );
  }

  Widget _buildSimpleStepCard() {
    return Container(
      padding: const EdgeInsets.all(14),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(14),
        border: Border.all(color: const Color(0xFFE4EDF7)),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              Icon(Icons.route_rounded, size: 18, color: _categoryColor),
              const SizedBox(width: 8),
              const Text(
                'Langkah Cepat',
                style: TextStyle(fontSize: 14, fontWeight: FontWeight.w700),
              ),
            ],
          ),
          const SizedBox(height: 10),
          _buildStepLine(
            '1',
            'Pilih prioritas yang paling penting untuk Anda.',
          ),
          const SizedBox(height: 6),
          _buildStepLine('2', 'Pastikan total prioritas 100%.'),
          const SizedBox(height: 6),
          _buildStepLine('3', 'Tekan Hitung, lalu pilih hasil teratas.'),
        ],
      ),
    );
  }

  Widget _buildStepLine(String number, String text) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Container(
          width: 20,
          height: 20,
          decoration: BoxDecoration(
            color: _categoryColor.withOpacity(0.12),
            shape: BoxShape.circle,
          ),
          child: Center(
            child: Text(
              number,
              style: TextStyle(
                fontSize: 11,
                fontWeight: FontWeight.w700,
                color: _categoryColor,
              ),
            ),
          ),
        ),
        const SizedBox(width: 8),
        Expanded(
          child: Text(
            text,
            style: TextStyle(
              fontSize: 12,
              color: Colors.grey[700],
              height: 1.35,
            ),
          ),
        ),
      ],
    );
  }

  Widget _buildUserInfoCard() {
    final name = _currentUser?.name ?? '';
    final email = _currentUser?.email ?? '';
    final initials = name.isEmpty
        ? 'U'
        : name.trim().split(' ').length >= 2
        ? '${name.trim().split(' ')[0][0]}${name.trim().split(' ')[1][0]}'
              .toUpperCase()
        : name.trim()[0].toUpperCase();

    final hour = DateTime.now().hour;
    final greeting = hour < 11
        ? 'Selamat Pagi'
        : hour < 15
        ? 'Selamat Siang'
        : hour < 18
        ? 'Selamat Sore'
        : 'Selamat Malam';

    final categoryLabel = widget.category == 'kontrakan'
        ? 'kontrakan'
        : 'laundry';

    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(16),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withValues(alpha: 0.04),
            blurRadius: 10,
            offset: const Offset(0, 3),
          ),
        ],
      ),
      child: Row(
        children: [
          // Avatar
          Container(
            width: 52,
            height: 52,
            decoration: BoxDecoration(
              gradient: LinearGradient(
                colors: [_categoryColor, _categoryColor.withValues(alpha: 0.7)],
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
              ),
              shape: BoxShape.circle,
              boxShadow: [
                BoxShadow(
                  color: _categoryColor.withValues(alpha: 0.3),
                  blurRadius: 8,
                  offset: const Offset(0, 3),
                ),
              ],
            ),
            child: Center(
              child: Text(
                initials,
                style: const TextStyle(
                  fontSize: 20,
                  fontWeight: FontWeight.w800,
                  color: Colors.white,
                ),
              ),
            ),
          ),
          const SizedBox(width: 14),
          // Info
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  '$greeting,',
                  style: TextStyle(
                    fontSize: 12,
                    color: Colors.grey.shade500,
                    fontWeight: FontWeight.w500,
                  ),
                ),
                const SizedBox(height: 2),
                Text(
                  name.isEmpty ? 'Pengguna' : name,
                  style: const TextStyle(
                    fontSize: 17,
                    fontWeight: FontWeight.w800,
                    color: Color(0xFF1A1A2E),
                  ),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
                if (email.isNotEmpty) ...[
                  const SizedBox(height: 2),
                  Text(
                    email,
                    style: TextStyle(fontSize: 12, color: Colors.grey.shade400),
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                  ),
                ],
              ],
            ),
          ),
          // Category badge
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
            decoration: BoxDecoration(
              color: _categoryColor.withValues(alpha: 0.1),
              borderRadius: BorderRadius.circular(20),
            ),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                Icon(
                  widget.category == 'kontrakan'
                      ? Icons.home_work_rounded
                      : Icons.local_laundry_service_rounded,
                  size: 14,
                  color: _categoryColor,
                ),
                const SizedBox(width: 5),
                Text(
                  categoryLabel,
                  style: TextStyle(
                    fontSize: 12,
                    fontWeight: FontWeight.w700,
                    color: _categoryColor,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildMethodInfoCard() {
    final kriteria3 = widget.category == 'kontrakan'
        ? 'jumlah kamar'
        : 'kecepatan layanan';
    final kriteria4 = 'fasilitas';

    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        gradient: LinearGradient(
          colors: [_categoryColor, _categoryColor.withValues(alpha: 0.8)],
        ),
        borderRadius: BorderRadius.circular(16),
        boxShadow: [
          BoxShadow(
            color: _categoryColor.withOpacity(0.3),
            blurRadius: 12,
            offset: const Offset(0, 4),
          ),
        ],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const Row(
            children: [
              Icon(Icons.analytics, color: Colors.white, size: 24),
              SizedBox(width: 8),
              Text(
                'Cara Rekomendasi Bekerja',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 18,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ],
          ),
          const SizedBox(height: 8),
          Text(
            'Pilih mana yang paling penting untuk Anda. Sistem akan mengurutkan hasil dari yang paling cocok.',
            style: TextStyle(
              color: Colors.white.withOpacity(0.9),
              fontSize: 13,
            ),
          ),
          const SizedBox(height: 8),
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
            decoration: BoxDecoration(
              color: Colors.white.withOpacity(0.2),
              borderRadius: BorderRadius.circular(8),
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  children: [
                    const Icon(Icons.adjust, size: 14, color: Colors.white),
                    const SizedBox(width: 6),
                    Expanded(
                      child: Text(
                        '1. Atur prioritas harga, jarak, $kriteria3, dan $kriteria4.',
                        style: TextStyle(
                          color: Colors.white.withOpacity(0.95),
                          fontSize: 12,
                          fontWeight: FontWeight.w500,
                        ),
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 6),
                Row(
                  children: [
                    const Icon(Icons.adjust, size: 14, color: Colors.white),
                    const SizedBox(width: 6),
                    Expanded(
                      child: Text(
                        '2. Total bobot harus 100% (otomatis diseimbangkan).',
                        style: TextStyle(
                          color: Colors.white.withOpacity(0.95),
                          fontSize: 12,
                          fontWeight: FontWeight.w500,
                        ),
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 6),
                Row(
                  children: [
                    const Icon(Icons.adjust, size: 14, color: Colors.white),
                    const SizedBox(width: 6),
                    Expanded(
                      child: Text(
                        '3. Lihat urutan hasil, lalu pilih yang paling sesuai.',
                        style: TextStyle(
                          color: Colors.white.withOpacity(0.95),
                          fontSize: 12,
                          fontWeight: FontWeight.w500,
                        ),
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
          const SizedBox(height: 8),
          Text(
            'Tips: Fokuskan 1-2 prioritas utama agar hasil lebih akurat dan mudah dipilih.',
            style: TextStyle(
              color: Colors.white.withOpacity(0.9),
              fontSize: 12,
              fontStyle: FontStyle.italic,
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildJenisLayananSection() {
    final jenisOptions = [
      {
        'value': 'harian',
        'label': 'Harian',
        'icon': Icons.today,
        'desc': 'Paket selesai harian dengan biaya lebih hemat',
      },
      {
        'value': 'jam',
        'label': 'Jam',
        'icon': Icons.schedule,
        'desc': 'Paket selesai dalam hitungan jam (lebih cepat)',
      },
    ];

    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(16),
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.1),
            blurRadius: 8,
            offset: const Offset(0, 2),
          ),
        ],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              Icon(
                Icons.local_laundry_service_outlined,
                color: _categoryColor,
                size: 20,
              ),
              const SizedBox(width: 8),
              Text(
                'Jenis Layanan',
                style: TextStyle(
                  fontSize: 15,
                  fontWeight: FontWeight.bold,
                  color: Colors.grey[800],
                ),
              ),
            ],
          ),
          const SizedBox(height: 4),
          Text(
            'Pilih jenis layanan laundry yang ingin dibandingkan',
            style: TextStyle(fontSize: 12, color: Colors.grey[500]),
          ),
          const SizedBox(height: 12),
          ...jenisOptions.map((opt) {
            final isSelected = _selectedJenisLayanan == opt['value'];
            return Padding(
              padding: const EdgeInsets.only(bottom: 8),
              child: InkWell(
                onTap: () => setState(
                  () => _selectedJenisLayanan = opt['value'] as String,
                ),
                borderRadius: BorderRadius.circular(12),
                child: Container(
                  padding: const EdgeInsets.symmetric(
                    vertical: 12,
                    horizontal: 14,
                  ),
                  decoration: BoxDecoration(
                    color: isSelected
                        ? _categoryColor.withOpacity(0.1)
                        : Colors.grey[50],
                    borderRadius: BorderRadius.circular(12),
                    border: Border.all(
                      color: isSelected ? _categoryColor : Colors.grey[300]!,
                      width: isSelected ? 2 : 1,
                    ),
                  ),
                  child: Row(
                    children: [
                      Icon(
                        opt['icon'] as IconData,
                        size: 22,
                        color: isSelected ? _categoryColor : Colors.grey[500],
                      ),
                      const SizedBox(width: 12),
                      Expanded(
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              opt['label'] as String,
                              style: TextStyle(
                                fontSize: 14,
                                fontWeight: isSelected
                                    ? FontWeight.bold
                                    : FontWeight.w500,
                                color: isSelected
                                    ? _categoryColor
                                    : Colors.grey[800],
                              ),
                            ),
                            const SizedBox(height: 2),
                            Text(
                              opt['desc'] as String,
                              style: TextStyle(
                                fontSize: 11,
                                color: Colors.grey[500],
                              ),
                            ),
                          ],
                        ),
                      ),
                      if (isSelected)
                        Icon(
                          Icons.check_circle,
                          color: _categoryColor,
                          size: 20,
                        ),
                    ],
                  ),
                ),
              ),
            );
          }).toList(),
        ],
      ),
    );
  }

  Widget _buildBobotSection() {
    final isValid = _totalBobot == 100;
    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(16),
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.1),
            blurRadius: 8,
            offset: const Offset(0, 2),
          ),
        ],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              Icon(Icons.tune, color: _categoryColor, size: 20),
              const SizedBox(width: 8),
              Text(
                'Bobot Kriteria',
                style: TextStyle(
                  fontSize: 15,
                  fontWeight: FontWeight.bold,
                  color: Colors.grey[800],
                ),
              ),
              const Spacer(),
              Container(
                padding: const EdgeInsets.symmetric(
                  horizontal: 10,
                  vertical: 4,
                ),
                decoration: BoxDecoration(
                  color: isValid
                      ? Colors.green.withOpacity(0.1)
                      : Colors.red.withOpacity(0.1),
                  borderRadius: BorderRadius.circular(20),
                  border: Border.all(
                    color: isValid
                        ? Colors.green.withOpacity(0.5)
                        : Colors.red.withOpacity(0.5),
                  ),
                ),
                child: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Icon(
                      isValid ? Icons.check_circle : Icons.warning,
                      size: 14,
                      color: isValid ? Colors.green : Colors.red,
                    ),
                    const SizedBox(width: 4),
                    Text(
                      'Total: $_totalBobot%',
                      style: TextStyle(
                        fontSize: 12,
                        fontWeight: FontWeight.bold,
                        color: isValid ? Colors.green[700] : Colors.red[700],
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
          const SizedBox(height: 4),
          Text(
            'Tap salah satu kriteria untuk mengubah bobot. Total akan disesuaikan otomatis menjadi 100%.',
            style: TextStyle(fontSize: 11, color: Colors.grey[500]),
          ),
          const SizedBox(height: 12),
          _buildBobotStackedBar(),
          const SizedBox(height: 12),
          _buildBobotRows(),
          if (!isValid) ...[
            const SizedBox(height: 12),
            Container(
              padding: const EdgeInsets.all(10),
              decoration: BoxDecoration(
                color: Colors.red[50],
                borderRadius: BorderRadius.circular(8),
                border: Border.all(color: Colors.red[200]!),
              ),
              child: Row(
                children: [
                  const Icon(Icons.info_outline, color: Colors.red, size: 16),
                  const SizedBox(width: 8),
                  Expanded(
                    child: Text(
                      _totalBobot > 100
                          ? 'Total bobot kelebihan ${_totalBobot - 100}%. Kurangi salah satu bobot.'
                          : 'Total bobot kurang ${100 - _totalBobot}%. Tambah salah satu bobot.',
                      style: TextStyle(fontSize: 12, color: Colors.red[700]),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ],
      ),
    );
  }


  Widget _buildLocationSection() {
    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(16),
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.1),
            blurRadius: 8,
            offset: const Offset(0, 2),
          ),
        ],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              Icon(Icons.my_location, color: _categoryColor, size: 20),
              const SizedBox(width: 8),
              Expanded(
                child: Text(
                  'Lokasi Saya',
                  style: TextStyle(
                    fontSize: 15,
                    fontWeight: FontWeight.bold,
                    color: Colors.grey[800],
                  ),
                ),
              ),
              if (_userLatitude != null && !_isDetectingLocation)
                InkWell(
                  onTap: _detectUserLocation,
                  borderRadius: BorderRadius.circular(12),
                  child: Padding(
                    padding: const EdgeInsets.all(4),
                    child: Icon(Icons.refresh, size: 18, color: _categoryColor),
                  ),
                ),
            ],
          ),
          const SizedBox(height: 4),
          Text(
            'Jarak dihitung dari lokasi Anda saat ini',
            style: TextStyle(fontSize: 12, color: Colors.grey[500]),
          ),
          const SizedBox(height: 12),
          if (_isDetectingLocation)
            Container(
              padding: const EdgeInsets.all(10),
              decoration: BoxDecoration(
                color: Colors.blue[50],
                borderRadius: BorderRadius.circular(8),
              ),
              child: const Row(
                children: [
                  SizedBox(
                    width: 16,
                    height: 16,
                    child: CircularProgressIndicator(strokeWidth: 2),
                  ),
                  SizedBox(width: 10),
                  Text('Mendeteksi lokasi...', style: TextStyle(fontSize: 12)),
                ],
              ),
            )
          else if (_userLatitude != null && _userLongitude != null)
            Container(
              padding: const EdgeInsets.all(10),
              decoration: BoxDecoration(
                color: Colors.green[50],
                borderRadius: BorderRadius.circular(8),
                border: Border.all(color: Colors.green[200]!),
              ),
              child: Row(
                children: [
                  const Icon(Icons.check_circle, size: 16, color: Colors.green),
                  const SizedBox(width: 8),
                  Expanded(
                    child: Text(
                      'Lokasi terdeteksi: ${_userLatitude!.toStringAsFixed(6)}, ${_userLongitude!.toStringAsFixed(6)}',
                      style: TextStyle(fontSize: 11, color: Colors.green[700]),
                    ),
                  ),
                ],
              ),
            )
          else
            Container(
              padding: const EdgeInsets.all(10),
              decoration: BoxDecoration(
                color: Colors.orange[50],
                borderRadius: BorderRadius.circular(8),
              ),
              child: Row(
                children: [
                  const Icon(Icons.warning, size: 16, color: Colors.orange),
                  const SizedBox(width: 8),
                  const Expanded(
                    child: Text(
                      'Lokasi belum terdeteksi',
                      style: TextStyle(fontSize: 12),
                    ),
                  ),
                  TextButton(
                    onPressed: _detectUserLocation,
                    child: const Text(
                      'Deteksi',
                      style: TextStyle(fontSize: 12),
                    ),
                  ),
                ],
              ),
            ),
        ],
      ),
    );
  }

  Widget _buildCalculateButton() {
    final isValid = _totalBobot == 100;
    return SizedBox(
      width: double.infinity,
      child: ElevatedButton(
        onPressed: isValid && !_isLoading ? _calculateSAW : null,
        style: ElevatedButton.styleFrom(
          backgroundColor: _categoryColor,
          disabledBackgroundColor: Colors.grey[300],
          padding: const EdgeInsets.symmetric(vertical: 16),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(16),
          ),
          elevation: isValid ? 4 : 0,
          shadowColor: _categoryColor.withOpacity(0.4),
        ),
        child: _isLoading
            ? const Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  SizedBox(
                    width: 20,
                    height: 20,
                    child: CircularProgressIndicator(
                      strokeWidth: 2,
                      color: Colors.white,
                    ),
                  ),
                  SizedBox(width: 12),
                  Text(
                    'Menyiapkan rekomendasi...',
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 16,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ],
              )
            : const Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(Icons.calculate, color: Colors.white, size: 22),
                  SizedBox(width: 10),
                  Text(
                    'Hitung Rekomendasi',
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 16,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ],
              ),
      ),
    );
  }

  // ===================== RESULT VIEW =====================
  Widget _buildResultView() {
    return Column(
      children: [
        _buildBobotSummary(),
        if (widget.category == 'laundry' && _userLatitude != null)
          Container(
            width: double.infinity,
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            color: Colors.green[50],
            child: Row(
              children: [
                Icon(Icons.location_on, size: 16, color: Colors.green[700]),
                const SizedBox(width: 8),
                Text(
                  'Jarak dihitung dari lokasi Anda',
                  style: TextStyle(fontSize: 12, color: Colors.green[700]),
                ),
              ],
            ),
          ),
        Expanded(child: _buildResultContent()),
      ],
    );
  }

  Widget _buildBobotSummary() {
    return Container(
      padding: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        gradient: LinearGradient(
          colors: [_categoryColor.withOpacity(0.05), Colors.white],
        ),
        border: Border(bottom: BorderSide(color: Colors.grey[200]!)),
      ),
      child: Column(
        children: [
          Row(
            children: [
              Icon(Icons.tune, size: 14, color: _categoryColor),
              const SizedBox(width: 6),
              Text(
                'Bobot yang digunakan:',
                style: TextStyle(
                  fontSize: 12,
                  fontWeight: FontWeight.w600,
                  color: Colors.grey[700],
                ),
              ),
              if (widget.category == 'laundry') ...[
                const SizedBox(width: 8),
                Container(
                  padding: const EdgeInsets.symmetric(
                    horizontal: 8,
                    vertical: 2,
                  ),
                  decoration: BoxDecoration(
                    color: _categoryColor.withOpacity(0.1),
                    borderRadius: BorderRadius.circular(10),
                  ),
                  child: Text(
                    _getJenisLayananLabel(_selectedJenisLayanan),
                    style: TextStyle(
                      fontSize: 10,
                      fontWeight: FontWeight.bold,
                      color: _categoryColor,
                    ),
                  ),
                ),
              ],
              const Spacer(),
              InkWell(
                onTap: () => setState(() {
                  _hasCalculated = false;
                  _recommendations = [];
                  _errorMessage = null;
                  _noData = false;
                }),
                child: Row(
                  children: [
                    Icon(Icons.edit, size: 14, color: _categoryColor),
                    const SizedBox(width: 4),
                    Text(
                      'Ubah',
                      style: TextStyle(
                        fontSize: 12,
                        color: _categoryColor,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
          const SizedBox(height: 8),
          Row(
            children: [
              _buildBobotMiniChip('Harga', _bobotHarga, true),
              const SizedBox(width: 6),
              _buildBobotMiniChip('Jarak', _bobotJarak, true),
              const SizedBox(width: 6),
              _buildBobotMiniChip(_kriteria3Label, _bobotKriteria3, false),
              const SizedBox(width: 6),
              _buildBobotMiniChip(_kriteria4Label, _bobotKriteria4, false),
            ],
          ),
        ],
      ),
    );
  }

  Widget _buildBobotMiniChip(String label, int value, bool isCost) {
    return Expanded(
      child: Container(
        padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 4),
        decoration: BoxDecoration(
          color: isCost
              ? Colors.orange.withOpacity(0.08)
              : Colors.green.withOpacity(0.08),
          borderRadius: BorderRadius.circular(8),
          border: Border.all(
            color: isCost
                ? Colors.orange.withOpacity(0.2)
                : Colors.green.withOpacity(0.2),
          ),
        ),
        child: Column(
          children: [
            Text(
              label,
              style: TextStyle(fontSize: 9, color: Colors.grey[600]),
              textAlign: TextAlign.center,
              overflow: TextOverflow.ellipsis,
            ),
            const SizedBox(height: 2),
            Text(
              '$value%',
              style: TextStyle(
                fontSize: 13,
                fontWeight: FontWeight.bold,
                color: isCost ? Colors.orange[700] : Colors.green[700],
              ),
            ),
          ],
        ),
      ),
    );
  }

  String _getJenisLayananLabel(String key) {
    switch (key) {
      case 'harian':
        return 'Harian';
      case 'jam':
        return 'Jam';
      case 'reguler':
        return 'Harian';
      case 'express':
        return 'Jam';
      default:
        return key;
    }
  }

  Widget _buildResultContent() {
    if (_isLoading) {
      return const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            CircularProgressIndicator(),
            SizedBox(height: 16),
            Text('Sedang menyiapkan rekomendasi terbaik...'),
          ],
        ),
      );
    }

    if (_errorMessage != null && _recommendations.isEmpty) {
      return Center(
        child: Padding(
          padding: const EdgeInsets.all(32),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(
                _noData
                    ? (widget.category == 'kontrakan'
                          ? Icons.home_outlined
                          : Icons.local_laundry_service_outlined)
                    : Icons.search_off,
                size: 64,
                color: Colors.grey[400],
              ),
              const SizedBox(height: 16),
              Text(
                _noData
                    ? (widget.category == 'kontrakan'
                          ? 'Belum Ada Kontrakan Tersedia'
                          : 'Belum Ada Laundry Tersedia')
                    : 'Belum Ada Hasil yang Cocok',
                style: TextStyle(
                  fontSize: 18,
                  fontWeight: FontWeight.bold,
                  color: Colors.grey[700],
                ),
              ),
              const SizedBox(height: 8),
              Text(
                _errorMessage!,
                textAlign: TextAlign.center,
                style: TextStyle(color: Colors.grey[500], fontSize: 13),
              ),
              const SizedBox(height: 24),
              if (!_noData)
                Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    ElevatedButton.icon(
                      onPressed: () => setState(() {
                        _hasCalculated = false;
                        _errorMessage = null;
                        _noData = false;
                      }),
                      icon: const Icon(Icons.tune),
                      label: const Text('Atur Prioritas Lagi'),
                      style: ElevatedButton.styleFrom(
                        backgroundColor: _categoryColor,
                        foregroundColor: Colors.white,
                      ),
                    ),
                    if (_errorMessage != null &&
                        (_errorMessage!.toLowerCase().contains(
                              'tidak dapat terhubung ke server',
                            ) ||
                            _errorMessage!.toLowerCase().contains('timeout')))
                      Padding(
                        padding: const EdgeInsets.only(top: 10),
                        child: OutlinedButton.icon(
                          onPressed: _resetConnectionAndRetry,
                          icon: const Icon(Icons.restart_alt),
                          label: const Text('Reset Koneksi'),
                          style: OutlinedButton.styleFrom(
                            foregroundColor: _categoryColor,
                            side: BorderSide(color: _categoryColor),
                          ),
                        ),
                      ),
                  ],
                )
              else
                OutlinedButton.icon(
                  onPressed: () => setState(() {
                    _hasCalculated = false;
                    _errorMessage = null;
                    _noData = false;
                  }),
                  icon: const Icon(Icons.refresh),
                  label: const Text('Coba Lagi'),
                  style: OutlinedButton.styleFrom(
                    foregroundColor: _categoryColor,
                    side: BorderSide(color: _categoryColor),
                  ),
                ),
            ],
          ),
        ),
      );
    }

    if (_recommendations.isEmpty) {
      return Center(
        child: Padding(
          padding: const EdgeInsets.all(32),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(
                widget.category == 'kontrakan'
                    ? Icons.home_outlined
                    : Icons.local_laundry_service_outlined,
                size: 64,
                color: Colors.grey[400],
              ),
              const SizedBox(height: 16),
              Text(
                'Tidak ada hasil',
                style: TextStyle(
                  fontSize: 18,
                  fontWeight: FontWeight.bold,
                  color: Colors.grey[700],
                ),
              ),
            ],
          ),
        ),
      );
    }

    return RefreshIndicator(
      onRefresh: _calculateSAW,
      child: ListView.builder(
        padding: const EdgeInsets.all(16),
        itemCount: _recommendations.length,
        itemBuilder: (context, index) {
          final item = _recommendations[index];
          return _buildResultCard(item, index);
        },
      ),
    );
  }

  Widget _buildResultCard(Map<String, dynamic> item, int index) {
    final ranking = item['ranking'] ?? (index + 1);
    final skor = (item['skor'] ?? item['skor_akhir'] ?? 0).toDouble();
    final normalisasi = item['normalisasi'] != null
        ? Map<String, dynamic>.from(item['normalisasi'])
        : <String, dynamic>{};
    final nilai = item['nilai'] != null
        ? Map<String, dynamic>.from(item['nilai'])
        : <String, dynamic>{};
    final itemData = item['data'] ?? item;

    return Container(
      margin: const EdgeInsets.only(bottom: 16),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(16),
        boxShadow: [
          BoxShadow(
            color: ranking <= 3
                ? _getRankingColor(ranking).withOpacity(0.2)
                : Colors.grey.withOpacity(0.1),
            blurRadius: 8,
            offset: const Offset(0, 2),
          ),
        ],
        border: ranking <= 3
            ? Border.all(
                color: _getRankingColor(ranking).withOpacity(0.3),
                width: 1.5,
              )
            : null,
      ),
      child: Column(
        children: [
          // Ranking Header
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
            decoration: BoxDecoration(
              gradient: LinearGradient(
                colors: [
                  _getRankingColor(ranking).withOpacity(0.1),
                  Colors.transparent,
                ],
              ),
              borderRadius: const BorderRadius.vertical(
                top: Radius.circular(16),
              ),
            ),
            child: Row(
              children: [
                Container(
                  width: 36,
                  height: 36,
                  decoration: BoxDecoration(
                    color: _getRankingColor(ranking),
                    shape: BoxShape.circle,
                    boxShadow: [
                      BoxShadow(
                        color: _getRankingColor(ranking).withOpacity(0.4),
                        blurRadius: 6,
                        offset: const Offset(0, 2),
                      ),
                    ],
                  ),
                  child: Center(
                    child: ranking <= 3
                        ? Icon(
                            _getRankingIcon(ranking),
                            color: Colors.white,
                            size: 18,
                          )
                        : Text(
                            '#$ranking',
                            style: const TextStyle(
                              color: Colors.white,
                              fontSize: 12,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                  ),
                ),
                const SizedBox(width: 12),
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        item['nama'] ?? 'N/A',
                        style: TextStyle(
                          fontSize: 14,
                          fontWeight: FontWeight.bold,
                          color: Colors.grey[800],
                        ),
                      ),
                      Text(
                        'Peringkat $ranking',
                        style: TextStyle(fontSize: 11, color: Colors.grey[500]),
                      ),
                    ],
                  ),
                ),
                Container(
                  padding: const EdgeInsets.symmetric(
                    horizontal: 12,
                    vertical: 6,
                  ),
                  decoration: BoxDecoration(
                    gradient: LinearGradient(
                      colors: [_categoryColor, _categoryColor.withOpacity(0.8)],
                    ),
                    borderRadius: BorderRadius.circular(20),
                  ),
                  child: Text(
                    'Skor: ${skor.toStringAsFixed(4)}',
                    style: const TextStyle(
                      color: Colors.white,
                      fontSize: 12,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
              ],
            ),
          ),

          // SAW Detail
          if (normalisasi.isNotEmpty)
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
              child: _buildNormalizationDetail(normalisasi, nilai),
            ),

          // Score Progress Bar
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(
                      'Skor Akhir (Vi)',
                      style: TextStyle(
                        fontSize: 11,
                        color: Colors.grey[600],
                        fontWeight: FontWeight.w500,
                      ),
                    ),
                    Text(
                      '${(skor * 100).toStringAsFixed(2)}%',
                      style: TextStyle(
                        fontSize: 11,
                        fontWeight: FontWeight.bold,
                        color: _categoryColor,
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 4),
                ClipRRect(
                  borderRadius: BorderRadius.circular(4),
                  child: LinearProgressIndicator(
                    value: skor.clamp(0.0, 1.0),
                    backgroundColor: Colors.grey[200],
                    valueColor: AlwaysStoppedAnimation<Color>(_categoryColor),
                    minHeight: 6,
                  ),
                ),
              ],
            ),
          ),

          const SizedBox(height: 8),
          const Divider(height: 1),

          // Item Card
          Padding(
            padding: const EdgeInsets.all(8),
            child: widget.category == 'kontrakan'
                ? KontrakanCard(kontrakan: Kontrakan.fromJson(itemData))
                : LaundryCard(
                    laundry: Laundry.fromJson(itemData),
                    userLatitude: _userLatitude,
                    userLongitude: _userLongitude,
                  ),
          ),
        ],
      ),
    );
  }

  Widget _buildNormalizationDetail(
    Map<String, dynamic> normalisasi,
    Map<String, dynamic> nilai,
  ) {
    return ExpansionTile(
      title: Row(
        children: [
          Icon(Icons.table_chart, size: 16, color: _categoryColor),
          const SizedBox(width: 8),
          Text(
            'Detail Perhitungan SAW',
            style: TextStyle(
              fontSize: 12,
              fontWeight: FontWeight.w600,
              color: Colors.grey[700],
            ),
          ),
        ],
      ),
      tilePadding: EdgeInsets.zero,
      childrenPadding: EdgeInsets.zero,
      initiallyExpanded: false,
      children: [
        Container(
          decoration: BoxDecoration(
            color: Colors.grey[50],
            borderRadius: BorderRadius.circular(8),
          ),
          child: Table(
            border: TableBorder.all(
              color: Colors.grey[300]!,
              width: 0.5,
              borderRadius: BorderRadius.circular(8),
            ),
            columnWidths: const {
              0: FlexColumnWidth(2.5),
              1: FlexColumnWidth(1.5),
              2: FlexColumnWidth(1.5),
              3: FlexColumnWidth(1.5),
            },
            children: [
              TableRow(
                decoration: BoxDecoration(
                  color: _categoryColor.withOpacity(0.1),
                  borderRadius: const BorderRadius.vertical(
                    top: Radius.circular(8),
                  ),
                ),
                children: [
                  _tableHeader('Kriteria'),
                  _tableHeader('Nilai'),
                  _tableHeader('Normalisasi'),
                  _tableHeader('Bobot'),
                ],
              ),
              ...normalisasi.entries.map((entry) {
                final key = entry.key;
                final norm = (entry.value is num)
                    ? entry.value.toDouble()
                    : 0.0;
                final nilaiVal = nilai[key] ?? 0;
                final bobot = _getBobotForKey(key);
                return TableRow(
                  children: [
                    _tableCell(_getKriteriaDisplayName(key)),
                    _tableCell(
                      nilaiVal is double
                          ? nilaiVal.toStringAsFixed(2)
                          : nilaiVal.toString(),
                    ),
                    _tableCell(
                      norm is double
                          ? norm.toStringAsFixed(4)
                          : norm.toString(),
                    ),
                    _tableCell('${(bobot * 100).toInt()}%'),
                  ],
                );
              }),
            ],
          ),
        ),
      ],
    );
  }

  Widget _tableHeader(String text) => Padding(
    padding: const EdgeInsets.all(6),
    child: Text(
      text,
      style: TextStyle(
        fontSize: 10,
        fontWeight: FontWeight.bold,
        color: _categoryColor,
      ),
      textAlign: TextAlign.center,
    ),
  );
  Widget _tableCell(String text) => Padding(
    padding: const EdgeInsets.all(6),
    child: Text(
      text,
      style: TextStyle(fontSize: 10, color: Colors.grey[700]),
      textAlign: TextAlign.center,
    ),
  );

  String _getKriteriaDisplayName(String key) {
    switch (key) {
      case 'harga':
        return 'Harga';
      case 'jarak':
        return 'Jarak';
      case 'jumlah_kamar':
        return 'Jml Kamar';
      case 'fasilitas_count':
        return 'Fasilitas';
      case 'kecepatan_layanan':
        return 'Kecepatan';
      case 'layanan':
        return 'Layanan';
      default:
        return key;
    }
  }

  double _getBobotForKey(String key) {
    switch (key) {
      case 'harga':
        return _bobotHarga / 100;
      case 'jarak':
        return _bobotJarak / 100;
      case 'jumlah_kamar':
      case 'kecepatan_layanan':
        return _bobotKriteria3 / 100;
      case 'fasilitas_count':
      case 'layanan':
        return _bobotKriteria4 / 100;
      default:
        return 0;
    }
  }

  Color _getRankingColor(int rank) {
    switch (rank) {
      case 1:
        return const Color(0xFFFFD700);
      case 2:
        return const Color(0xFFC0C0C0);
      case 3:
        return const Color(0xFFCD7F32);
      default:
        return _categoryColor;
    }
  }

  IconData _getRankingIcon(int rank) {
    switch (rank) {
      case 1:
        return Icons.emoji_events;
      case 2:
        return Icons.workspace_premium;
      case 3:
        return Icons.military_tech;
      default:
        return Icons.star;
    }
  }
}
