import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import "package:http/http.dart" as http;
import 'package:shared_preferences/shared_preferences.dart';
import '../../../data/providers/services.dart';

class DropdownSearchController extends GetxController
    with GetSingleTickerProviderStateMixin {
  TextEditingController searchController = TextEditingController();
  var searchResultsBM25F = <String>[].obs;
  var searchResultsVSM = <String>[].obs;
  var menuResults = <Map<String, dynamic>>[].obs;
  var isLoading = false.obs;
  var isDropdownVisible = false.obs;
  var selectedTabIndex = 0.obs; // 0 = BM25F, 1 = VSM
  Timer? debounce;
  late TabController tabController;
  var hasFetchedMenus = false.obs;

  @override
  void onInit() {
    super.onInit();
    tabController = TabController(length: 2, vsync: this);
    tabController.addListener(() {
      selectedTabIndex.value = tabController.index;
      searchDropdown(searchController.text);
    });

    if (!hasFetchedMenus.value) {
      fetchAllMenus();
      hasFetchedMenus.value = true;
    }
  }

  @override
  void onClose() {
    debounce?.cancel();
    searchController.dispose();
    tabController.dispose();
    super.onClose();
  }

  Future<void> fetchAllMenus() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String? token = prefs.getString('token');

    try {
      isLoading(true);
      final response = await http.get(
        Uri.parse(Api.semua),
        headers: {'Authorization': 'Bearer $token'},
      );
      if (response.statusCode == 200) {
        final data = json.decode(response.body);
        menuResults.assignAll(List<Map<String, dynamic>>.from(data['data']));
      }
    } catch (e) {
      print('Error fetching all menus: $e');
    } finally {
      isLoading(false);
    }
  }

  Future<void> searchDropdown(String keyword) async {
    if (keyword.isEmpty) {
      searchResultsBM25F.clear();
      searchResultsVSM.clear();
      isDropdownVisible(false);
      return;
    }

    debounce?.cancel();
    debounce = Timer(Duration(milliseconds: 500), () async {
      try {
        isLoading(true);
        SharedPreferences prefs = await SharedPreferences.getInstance();
        String? token = prefs.getString('token');

        String url = selectedTabIndex.value == 0
            ? Api.bm25fSearch + keyword // BM25F
            : Api.vsmSearch + keyword; // VSM

        final response = await http
            .get(Uri.parse(url), headers: {'Authorization': 'Bearer $token'});

        if (response.statusCode == 200) {
          final data = json.decode(response.body);
          List<String> results = (data['data'] as List)
              .map((item) => item['nama'].toString())
              .toList();

          if (selectedTabIndex.value == 0) {
            searchResultsBM25F.assignAll(results);
          } else {
            searchResultsVSM.assignAll(results);
          }

          isDropdownVisible(results.isNotEmpty);
        } else {
          searchResultsBM25F.clear();
          searchResultsVSM.clear();
          isDropdownVisible(false);
        }
      } catch (e) {
        print('Error during search: $e');
        searchResultsBM25F.clear();
        searchResultsVSM.clear();
        isDropdownVisible(false);
      } finally {
        isLoading(false);
      }
    });
  }

  Future<void> searchMenu() async {
    String keyword = searchController.text.trim();
    if (keyword.isEmpty) return;

    debounce?.cancel();
    debounce = Timer(Duration(milliseconds: 500), () async {
      try {
        isLoading(true);
        SharedPreferences prefs = await SharedPreferences.getInstance();
        String? token = prefs.getString('token');

        final response = await http.get(Uri.parse(Api.semua + keyword),
            headers: {'Authorization': 'Bearer $token'});

        if (response.statusCode == 200) {
          final data = json.decode(response.body);
          menuResults.assignAll(List<Map<String, dynamic>>.from(data['data']));
        } else {
          menuResults.clear();
        }
      } catch (e) {
        print('Error during search: $e');
        menuResults.clear();
      } finally {
        isLoading(false);
      }
    });
  }

  void onSelectMenu(String selectedMenu) {
    searchController.text = selectedMenu;
    searchResultsBM25F.clear();
    searchResultsVSM.clear();
    isDropdownVisible(false);
    searchMenu();
  }
}
