import 'dart:convert';

import 'package:fl_chart/fl_chart.dart';
import 'package:get/get.dart';

import '../../constant/links.dart';
import '../../models/model/passengers_model.dart';
import '../../print.dart';
import '../functions/crud.dart';

class StaticController extends GetxController {
  Map<String, dynamic> jsonData1 = {};
  Map<String, dynamic> jsonData2 = {};
  List staticList = [];
  var chartDataPassengers;
  var chartDataDrivers;
  var chartDataDriversCalling;
  var chartDataRides;
  var chartDataEmployee;
  var chartDataEmployeeMaryam;
  var chartDataEmployeeRawda;
  var chartDataEmployeeMena;
  var chartDataEmployeeSefer4;
  var chartDataDriversMatchingNotes;
  bool isLoading = false;
  String totalMonthlyPassengers = '';
  String totalMonthlyRides = '';
  String totalMonthlyEmployee = '';
  String totalMonthlyDrivers = '';
  late List<MonthlyPassengerInstall> passengersData;
  late List<MonthlyRidesInstall> ridesData;
  late List<MonthlyEmployeeData> employeeData;
  late List<MonthlyDriverInstall> driversData;

  Future<void> fetch() async {
    isLoading = true;
    update(); // Notify the observers about the loading state change

    var res = await CRUD().get(
      link: AppLink.getPassengersStatic,
      payload: {},
    );
    jsonData1 = jsonDecode(res);
    var jsonResponse = jsonDecode(res) as Map<String, dynamic>;
    isLoading = false;
    final List<dynamic> jsonData = jsonResponse['message'];
    totalMonthlyPassengers = jsonData[0]['totalMonthly'].toString();
    passengersData = jsonData.map<MonthlyPassengerInstall>((item) {
      return MonthlyPassengerInstall.fromJson(item);
    }).toList();
    final List<FlSpot> spots = passengersData
        .map((data) => FlSpot(
              data.day.toDouble(),
              data.totalPassengers.toDouble(),
            ))
        .toList();
    chartDataPassengers = spots;

    update(); // Notify the observers about the data and loading state change
  }

  Future<void> fetchRides() async {
    isLoading = true;
    update(); // Notify the observers about the loading state change

    var res = await CRUD().get(
      link: AppLink.getRidesStatic,
      payload: {},
    );
    jsonData1 = jsonDecode(res);
    var jsonResponse = jsonDecode(res) as Map<String, dynamic>;
    isLoading = false;
    final List<dynamic> jsonData = jsonResponse['message'];
    totalMonthlyRides = jsonData[0]['totalMonthly'].toString();
    ridesData = jsonData.map<MonthlyRidesInstall>((item) {
      return MonthlyRidesInstall.fromJson(item);
    }).toList();
    final List<FlSpot> spots = ridesData
        .map((data) => FlSpot(
              data.day.toDouble(),
              data.totalRides.toDouble(),
            ))
        .toList();
    chartDataRides = spots;

    update(); // Notify the observers about the data and loading state change
  }

  Future<void> fetchEmployee() async {
    try {
      isLoading = true;
      update();

      var res = await CRUD().get(link: AppLink.getEmployeeStatic, payload: {});

      // First check if the response is valid JSON
      if (res == 'failure') {
        throw FormatException('Invalid response: $res');
      }

      var jsonResponse = jsonDecode(res) as Map<String, dynamic>;

      // Initialize empty lists for all chart data
      chartDataEmployeeMaryam = <FlSpot>[];
      chartDataEmployeeRawda = <FlSpot>[];
      chartDataEmployeeMena = <FlSpot>[];
      chartDataEmployeeSefer4 = <FlSpot>[];
      totalMonthlyRides = '0';

      // Check for error response
      if (jsonResponse['status'] == 'failure') {
        isLoading = false;
        update();
        return;
      }

      final List<dynamic> jsonData = jsonResponse['message'];
      if (jsonData.isEmpty) {
        isLoading = false;
        update();
        return;
      }

      totalMonthlyRides = jsonData[0]['totalMonthly']?.toString() ?? '0';

      // Group data by employee
      Map<String, List<MonthlyEmployeeData>> employeeDataMap = {};

      for (var item in jsonData) {
        var employeeData = MonthlyEmployeeData.fromJson(item);
        if (!employeeDataMap.containsKey(employeeData.name)) {
          employeeDataMap[employeeData.name] = [];
        }
        employeeDataMap[employeeData.name]!.add(employeeData);
      }

      final today = DateTime.now().day;

      // Create data for each employee
      final employeeNames = {
        'maryam': chartDataEmployeeMaryam,
        'yasmine': chartDataEmployeeRawda,
        'mena': chartDataEmployeeMena,
        'ashjan': chartDataEmployeeSefer4,
      };

      employeeNames.forEach((name, chartData) {
        var spots = <FlSpot>[];
        for (int day = 1; day <= today; day++) {
          spots.add(FlSpot(
            day.toDouble(),
            employeeDataMap[name]
                    ?.firstWhere(
                      (e) => e.day == day,
                      orElse: () => MonthlyEmployeeData(
                        day: day,
                        totalEmployees: 0,
                        name: name,
                      ),
                    )
                    .totalEmployees
                    .toDouble() ??
                0,
          ));
        }

        // Explicitly cast to List<FlSpot>
        if (name == 'maryam')
          chartDataEmployeeMaryam = List<FlSpot>.from(spots);
        if (name == 'yasmine')
          chartDataEmployeeRawda = List<FlSpot>.from(spots);
        if (name == 'mena') chartDataEmployeeMena = List<FlSpot>.from(spots);
        if (name == 'ashjan')
          chartDataEmployeeSefer4 = List<FlSpot>.from(spots);
      });
    } catch (e) {
      Log.print('Error in fetchEmployee: $e');
      // Set empty FlSpot lists in case of error
      chartDataEmployeeMaryam = <FlSpot>[];
      chartDataEmployeeRawda = <FlSpot>[];
      chartDataEmployeeMena = <FlSpot>[];
      chartDataEmployeeSefer4 = <FlSpot>[];
      totalMonthlyRides = '0';
    } finally {
      isLoading = false;
      update();
    }
  }

  Future<void> fetchDrivers() async {
    isLoading = true;
    update(); // Notify the observers about the loading state change

    var res = await CRUD().get(
      link: AppLink.getdriverstotalMonthly,
      payload: {},
    );
    jsonData2 = jsonDecode(res);
    var jsonResponse = jsonDecode(res) as Map<String, dynamic>;
    isLoading = false;
    final List<dynamic> jsonData = jsonResponse['message'];
    staticList = jsonData;
    totalMonthlyDrivers = jsonData[0]['totalDrivers'].toString();
    driversData = jsonData.map<MonthlyDriverInstall>((item) {
      return MonthlyDriverInstall.fromJson(item);
    }).toList();
    final List<FlSpot> spots = driversData
        .map((data) => FlSpot(
              data.day.toDouble(),
              data.dailyTotalDrivers.toDouble(),
            ))
        .toList();
    chartDataDrivers = spots;
    final List<FlSpot> spotsCalling = driversData
        .map((data) => FlSpot(
              data.day.toDouble(),
              data.dailyTotalCallingDrivers.toDouble(),
            ))
        .toList();
    chartDataDriversCalling = spotsCalling;
    final List<FlSpot> spotsTotalMatchingNotes = driversData
        .map((data) => FlSpot(
              data.day.toDouble(),
              data.dailyMatchingNotes.toDouble(),
            ))
        .toList();
    chartDataDriversMatchingNotes = spotsTotalMatchingNotes;

    update(); // Notify the observers about the data and loading state change
  }

  Future getAll() async {
    await fetch();
    await fetchRides();
    await fetchDrivers();
    await fetchEmployee();
  }
}
