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

import '../../constant/links.dart';
import '../../print.dart';
import '../functions/crud.dart';

class StaticController extends GetxController {
  // --- Date & State Management ---
  DateTime? startDate = DateTime(DateTime.now().year, DateTime.now().month, 1);
  DateTime? endDate =
      DateTime(DateTime.now().year, DateTime.now().month + 1, 0);

  DateTime? compareStartDate;
  DateTime? compareEndDate;

  bool isComparing = false;
  bool isLoading = false;

  // --- Daily Notes State ---
  bool isLoadingNotes = false;
  List<dynamic> dailyNotesList = [];

  // --- Chart Data (Current Range) ---
  List<FlSpot> chartDataPassengers = [];
  List<FlSpot> chartDataDrivers = [];
  List<FlSpot> chartDataRides = [];
  List<FlSpot> chartDataDriversMatchingNotes = [];

  // Employee Data (Notes/General Stats)
  List<FlSpot> chartDataEmployeerama1 = [];
  List<FlSpot> chartDataEmployeeshahd = [];
  List<FlSpot> chartDataEmployeeRama2 = [];
  List<FlSpot> chartDataEmployeeSefer4 = [];

  // Employee Data (Calls/Activations Stats)
  List<FlSpot> chartDataCallsrama1 = [];
  List<FlSpot> chartDataCallsShahd = [];
  List<FlSpot> chartDataCallsRama2 = [];
  List<FlSpot> chartDataCallsSefer4 = [];

  // --- Chart Data (Comparison Range) ---
  List<FlSpot> chartDataPassengersCompare = [];
  List<FlSpot> chartDataDriversCompare = [];
  List<FlSpot> chartDataRidesCompare = [];
  List<FlSpot> chartDataDriversMatchingNotesCompare = [];

  // Employee Comparison (Notes)
  List<FlSpot> chartDataEmployeerama1Compare = [];
  List<FlSpot> chartDataEmployeeshahdCompare = [];
  List<FlSpot> chartDataEmployeeRama2Compare = [];
  List<FlSpot> chartDataEmployeeSefer4Compare = [];

  // Employee Comparison (Calls/Activations)
  List<FlSpot> chartDataCallsrama1Compare = [];
  List<FlSpot> chartDataCallsShahdCompare = [];
  List<FlSpot> chartDataCallsRama2Compare = [];
  List<FlSpot> chartDataCallsSefer4Compare = [];

  // --- Totals ---
  String totalMonthlyPassengers = '0';
  String totalMonthlyRides = '0';
  String totalMonthlyDrivers = '0';

  // --- Raw Lists ---
  List staticList = [];

  // --- Employment Type Stats List (Simple Count) ---
  List<Map<String, dynamic>> employmentStatsList = [];

  @override
  void onInit() {
    super.onInit();
    getAll();
  }

  // --- Helpers for View ---
  double get daysInPeriod {
    if (startDate == null || endDate == null) return 31;
    return endDate!.difference(startDate!).inDays + 1.0;
  }

  String get currentDateString {
    if (startDate == null || endDate == null) return "";
    return "${DateFormat('yyyy-MM-dd').format(startDate!)} : ${DateFormat('yyyy-MM-dd').format(endDate!)}";
  }

  // --- Date Actions ---
  void updateDateRange(DateTime start, DateTime end) {
    startDate = start;
    endDate = end;
    if (isComparing) _calculateCompareDates();
    getAll();
    update();
  }

  void _calculateCompareDates() {
    if (startDate == null || endDate == null) return;
    Duration duration = endDate!.difference(startDate!);
    compareEndDate = startDate!.subtract(const Duration(days: 1));
    compareStartDate = compareEndDate!.subtract(duration);
  }

  Future<void> toggleComparison() async {
    isComparing = !isComparing;
    if (isComparing) {
      _calculateCompareDates();
    } else {
      compareStartDate = null;
      compareEndDate = null;
      _clearComparisonData();
    }
    await getAll();
  }

  void _clearComparisonData() {
    chartDataPassengersCompare.clear();
    chartDataDriversCompare.clear();
    chartDataRidesCompare.clear();
    chartDataDriversMatchingNotesCompare.clear();

    chartDataEmployeerama1Compare.clear();
    chartDataEmployeeshahdCompare.clear();
    chartDataEmployeeRama2Compare.clear();
    chartDataEmployeeSefer4Compare.clear();

    chartDataCallsrama1Compare.clear();
    chartDataCallsShahdCompare.clear();
    chartDataCallsRama2Compare.clear();
    chartDataCallsSefer4Compare.clear();
  }

  Map<String, dynamic> _getPayload(DateTime start, DateTime end) {
    return {
      "start_date": DateFormat('yyyy-MM-dd').format(start),
      "end_date": DateFormat('yyyy-MM-dd').format(end),
      "month": start.month.toString(),
      "year": start.year.toString(),
    };
  }

  // --- Main Fetch Logic ---
  Future getAll() async {
    if (startDate == null || endDate == null) return;

    isLoading = true;
    update();

    await Future.wait([
      fetchPassengers(isCompare: false),
      fetchRides(isCompare: false),
      fetchDrivers(isCompare: false),
      fetchEmployee(isCompare: false),
      fetchEditorCalls(isCompare: false),
      fetchEmploymentStats(),
    ]);

    if (isComparing && compareStartDate != null && compareEndDate != null) {
      await Future.wait([
        fetchPassengers(isCompare: true),
        fetchRides(isCompare: true),
        fetchDrivers(isCompare: true),
        fetchEmployee(isCompare: true),
        fetchEditorCalls(isCompare: true),
      ]);
    }

    isLoading = false;
    update();
  }

  // ... (Existing Functions _generateSpots, fetchPassengers, etc.) ...
  List<FlSpot> _generateSpots(List<dynamic> data, String dateKey,
      String valueKey, DateTime startOfRange) {
    List<FlSpot> spots = [];
    Map<String, double> dataMap = {};
    for (var item in data) {
      String dateStr = item[dateKey].toString();
      double val = double.tryParse(item[valueKey].toString()) ?? 0.0;
      dataMap[dateStr] = val;
    }
    DateTime rangeEnd =
        (startOfRange == startDate) ? endDate! : compareEndDate!;
    int totalDays = rangeEnd.difference(startOfRange).inDays + 1;
    for (int i = 0; i < totalDays; i++) {
      DateTime currentDate = startOfRange.add(Duration(days: i));
      String dateKeyStr = DateFormat('yyyy-MM-dd').format(currentDate);
      double value = dataMap[dateKeyStr] ?? 0.0;
      spots.add(FlSpot((i + 1).toDouble(), value));
    }
    return spots;
  }

  Future<void> fetchPassengers({bool isCompare = false}) async {
    DateTime start = isCompare ? compareStartDate! : startDate!;
    DateTime end = isCompare ? compareEndDate! : endDate!;
    var res = await CRUD().get(
        link: AppLink.getPassengersStatic, payload: _getPayload(start, end));
    var jsonResponse = jsonDecode(res);
    if (jsonResponse['status'] == 'failure') return;
    final List<dynamic> jsonData = jsonResponse['message'];
    if (!isCompare &&
        jsonData.isNotEmpty &&
        jsonData[0]['totalMonthly'] != null) {
      totalMonthlyPassengers = jsonData[0]['totalMonthly'].toString();
    }
    List<FlSpot> spots =
        _generateSpots(jsonData, 'day', 'totalPassengers', start);
    if (isCompare)
      chartDataPassengersCompare = spots;
    else
      chartDataPassengers = spots;
  }

  Future<void> fetchRides({bool isCompare = false}) async {
    DateTime start = isCompare ? compareStartDate! : startDate!;
    DateTime end = isCompare ? compareEndDate! : endDate!;
    var res = await CRUD()
        .get(link: AppLink.getRidesStatic, payload: _getPayload(start, end));
    var jsonResponse = jsonDecode(res);
    if (jsonResponse['status'] == 'failure') return;
    final List<dynamic> jsonData = jsonResponse['message'];
    if (!isCompare &&
        jsonData.isNotEmpty &&
        jsonData[0]['totalMonthly'] != null) {
      totalMonthlyRides = jsonData[0]['totalMonthly'].toString();
    }
    List<FlSpot> spots = _generateSpots(jsonData, 'day', 'totalRides', start);
    if (isCompare)
      chartDataRidesCompare = spots;
    else
      chartDataRides = spots;
  }

  Future<void> fetchDrivers({bool isCompare = false}) async {
    DateTime start = isCompare ? compareStartDate! : startDate!;
    DateTime end = isCompare ? compareEndDate! : endDate!;
    var res = await CRUD().get(
        link: AppLink.getdriverstotalMonthly, payload: _getPayload(start, end));
    var jsonResponse = jsonDecode(res);
    if (jsonResponse['status'] == 'failure') return;
    final List<dynamic> jsonData = jsonResponse['message'];
    if (!isCompare &&
        jsonData.isNotEmpty &&
        jsonData[0]['totalMonthlyDrivers'] != null) {
      totalMonthlyDrivers = jsonData[0]['totalMonthlyDrivers'].toString();
    }
    if (!isCompare) {
      staticList = jsonData;
    }

    List<FlSpot> spotsDrivers =
        _generateSpots(jsonData, 'day', 'dailyTotalDrivers', start);
    List<FlSpot> spotsNotes =
        _generateSpots(jsonData, 'day', 'dailyMatchingNotes', start);
    if (isCompare) {
      chartDataDriversCompare = spotsDrivers;
      chartDataDriversMatchingNotesCompare = spotsNotes;
    } else {
      chartDataDrivers = spotsDrivers;
      chartDataDriversMatchingNotes = spotsNotes;
    }
  }

  Future<void> fetchEmployee({bool isCompare = false}) async {
    try {
      DateTime start = isCompare ? compareStartDate! : startDate!;
      DateTime end = isCompare ? compareEndDate! : endDate!;
      var res = await CRUD().get(
          link: AppLink.getEmployeeStatic, payload: _getPayload(start, end));

      if (isCompare) {
        chartDataEmployeerama1Compare = [];
        chartDataEmployeeshahdCompare = [];
        chartDataEmployeeRama2Compare = [];
        chartDataEmployeeSefer4Compare = [];
      } else {
        chartDataEmployeerama1 = [];
        chartDataEmployeeshahd = [];
        chartDataEmployeeRama2 = [];
        chartDataEmployeeSefer4 = [];
      }

      if (res == 'failure') return;
      var jsonResponse = jsonDecode(res) as Map<String, dynamic>;
      if (jsonResponse['status'] == 'failure') return;
      final List<dynamic> jsonData = jsonResponse['message'];
      if (jsonData.isEmpty) return;

      Map<String, Map<String, double>> dateNameMap = {};
      for (var item in jsonData) {
        String dateKeyStr = item['date'] ?? item['day'];
        String name = item['NAME'].toString().toLowerCase().trim();
        double count = double.tryParse(item['count'].toString()) ?? 0.0;
        if (!dateNameMap.containsKey(dateKeyStr)) dateNameMap[dateKeyStr] = {};
        if (dateNameMap[dateKeyStr]!.containsKey(name)) {
          dateNameMap[dateKeyStr]![name] =
              dateNameMap[dateKeyStr]![name]! + count;
        } else {
          dateNameMap[dateKeyStr]![name] = count;
        }
      }

      final targetLists = isCompare
          ? {
              'rama1': chartDataEmployeerama1Compare,
              'shahd': chartDataEmployeeshahdCompare,
              'rama2': chartDataEmployeeRama2Compare,
              'mayar': chartDataEmployeeSefer4Compare
            }
          : {
              'rama1': chartDataEmployeerama1,
              'shahd': chartDataEmployeeshahd,
              'rama2': chartDataEmployeeRama2,
              'mayar': chartDataEmployeeSefer4
            };

      int totalDays = end.difference(start).inDays + 1;
      targetLists.forEach((key, listToFill) {
        for (int i = 0; i < totalDays; i++) {
          DateTime currentDate = start.add(Duration(days: i));
          String currentDateStr = DateFormat('yyyy-MM-dd').format(currentDate);
          double value = 0;
          Map<String, double>? dayData = dateNameMap[currentDateStr];
          if (dayData != null) {
            // if (key == 'mayar') {
            //   value = (dayData['mayar'] ?? 0) +
            //       (dayData['rama1'] ?? 0) +
            //       (dayData['sefer4'] ?? 0);
            // } else {
            value = dayData[key] ?? 0;
            // }
          }
          listToFill.add(FlSpot((i + 1).toDouble(), value));
        }
      });
    } catch (e) {
      Log.print('Error in fetchEmployee: $e');
    }
  }

  Future<void> fetchEditorCalls({bool isCompare = false}) async {
    try {
      DateTime start = isCompare ? compareStartDate! : startDate!;
      DateTime end = isCompare ? compareEndDate! : endDate!;

      var res = await CRUD().get(
          link: AppLink.getEditorStatsCalls, payload: _getPayload(start, end));

      if (isCompare) {
        chartDataCallsrama1Compare = [];
        chartDataCallsShahdCompare = [];
        chartDataCallsRama2Compare = [];
        chartDataCallsSefer4Compare = [];
      } else {
        chartDataCallsrama1 = [];
        chartDataCallsShahd = [];
        chartDataCallsRama2 = [];
        chartDataCallsSefer4 = [];
      }

      if (res == 'failure') return;

      var jsonResponse = jsonDecode(res) as Map<String, dynamic>;
      if (jsonResponse['status'] == 'failure') return;

      final List<dynamic> jsonData = jsonResponse['message'];
      if (jsonData.isEmpty) return;

      Map<String, Map<String, double>> dateNameMap = {};

      for (var item in jsonData) {
        String dateKeyStr = item['date'] ?? item['day'];
        String name = item['NAME'].toString().toLowerCase().trim();
        double count = double.tryParse(item['count'].toString()) ?? 0.0;

        if (!dateNameMap.containsKey(dateKeyStr)) {
          dateNameMap[dateKeyStr] = {};
        }

        if (dateNameMap[dateKeyStr]!.containsKey(name)) {
          dateNameMap[dateKeyStr]![name] =
              dateNameMap[dateKeyStr]![name]! + count;
        } else {
          dateNameMap[dateKeyStr]![name] = count;
        }
      }

      final targetLists = isCompare
          ? {
              'rama1': chartDataCallsrama1Compare,
              'shahd': chartDataCallsShahdCompare,
              'rama2': chartDataCallsRama2Compare,
              'mayar': chartDataCallsSefer4Compare,
            }
          : {
              'rama1': chartDataCallsrama1,
              'shahd': chartDataCallsShahd,
              'rama2': chartDataCallsRama2,
              'mayar': chartDataCallsSefer4,
            };

      int totalDays = end.difference(start).inDays + 1;

      targetLists.forEach((key, listToFill) {
        for (int i = 0; i < totalDays; i++) {
          DateTime currentDate = start.add(Duration(days: i));
          String currentDateStr = DateFormat('yyyy-MM-dd').format(currentDate);

          double value = 0;
          Map<String, double>? dayData = dateNameMap[currentDateStr];

          if (dayData != null) {
            // if (key == 'mayar_group') {
            //   value = (dayData['mayar'] ?? 0) +
            //       (dayData['rama1'] ?? 0) +
            //       (dayData['sefer4'] ?? 0);
            // } else {
            value = dayData[key] ?? 0;
            // }
          }
          listToFill.add(FlSpot((i + 1).toDouble(), value));
        }
      });
    } catch (e) {
      Log.print('Error in fetchEditorCalls: $e');
    }
  }

  // --- 🔴 FIXED: Fetch Employment Stats with Unique Check ---
  Future<void> fetchEmploymentStats() async {
    try {
      // لا نستخدم .clear() هنا، سنقوم باستبدال القائمة بالكامل في النهاية

      var res = await CRUD().get(
          link: AppLink.getEmployeeDriverAfterCallingRegister,
          payload: _getPayload(startDate!, endDate!));

      if (res == 'failure') return;

      var jsonResponse = jsonDecode(res);
      if (jsonResponse['status'] == 'success') {
        if (jsonResponse['message'] != null &&
            jsonResponse['message']['data'] != null) {
          List<dynamic> data = jsonResponse['message']['data'];

          List<String> allowedNames = ['shahd', 'mayar', 'rama1', 'rama2'];

          // استخدام Map لضمان عدم تكرار الأسماء (تجميع القيم)
          Map<String, int> uniqueMap = {};

          for (var item in data) {
            String name =
                item['employmentType'].toString().toLowerCase().trim();
            int count = int.tryParse(item['count'].toString()) ?? 0;

            if (allowedNames.contains(name)) {
              if (uniqueMap.containsKey(name)) {
                uniqueMap[name] = uniqueMap[name]! + count;
              } else {
                uniqueMap[name] = count;
              }
            }
          }

          // تحويل الـ Map إلى القائمة النهائية
          List<Map<String, dynamic>> tempList = [];
          uniqueMap.forEach((key, value) {
            tempList.add({'name': key, 'count': value});
          });

          // استبدال القائمة القديمة بالقائمة الجديدة النظيفة
          employmentStatsList = tempList;
        }
      }
    } catch (e) {
      Log.print("Error fetchEmploymentStats: $e");
    }
  }

  // --- Fetch Daily Notes Log ---
  Future<void> fetchDailyNotes(DateTime date) async {
    try {
      isLoadingNotes = true;
      dailyNotesList.clear();
      update();

      var res = await CRUD().post(
          link: AppLink.getNotesForEmployee,
          payload: {"date": DateFormat('yyyy-MM-dd').format(date)});

      if (res != 'failure') {
        var jsonResponse = (res);
        if (jsonResponse['status'] == 'success') {
          dailyNotesList = jsonResponse['message'];
        }
      }
    } catch (e) {
      Log.print("Error fetchDailyNotes: $e");
    } finally {
      isLoadingNotes = false;
      update();
    }
  }
}
