import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:generp/Utils/SharedpreferencesService.dart';
import 'package:generp/screens/LoginScreen.dart';
import 'package:generp/services/api_calling.dart';
import 'package:intl/intl.dart';

import '../Models/AttendanceListResponse.dart';
import '../Utils/commonServices.dart';

class AttendanceNotifier extends ChangeNotifier {
  List<dynamic> _attHistory = [];
  int _attendanceStatus = 0;
  bool _isLoading = false;
  String _date = "";
  String _intime = "";
  String _outtime = "";
  String _inlocation = "";
  String _outlocation = "";
  String _penalties = "";
  String _selectedDate = "";
  DateTime _month = DateTime.now();
  late int _monthNo;
  DateTime _present_month = DateTime.now();
  String _year = "";
  dynamic _presentDays = 0;
  dynamic _absentDays = 0;
  dynamic _holidays = 0;
  dynamic _latePenalties = 0;

  int? _selectedIndex;
  int? _currentDayIndex;
  bool _initialRenderDone = true;
  String? _dateColor;
  List<Map<String, dynamic>> _dateArrayList = [];
  List<Map<String, dynamic>> _penalityArrayList = [];

  List<dynamic> get attendanceHistory => _attHistory;

  int get attendanceStatus => _attendanceStatus;

  bool get isLoading => _isLoading;

  String get date => _date;

  String get intime => _intime;

  String get outtime => _outtime;

  String get inlocation => _inlocation;

  String get outlocation => _outlocation;

  String get penalties => _penalties;

  String get selectedDate => _selectedDate;

  dynamic get presentDays => _presentDays;

  dynamic get absentDays => _absentDays;

  dynamic get holidays => _holidays;

  dynamic get latePenalties => _latePenalties;

  DateTime get month => _month;

  DateTime get present_month => _present_month;

  String get year => _year;

  int get monthNo => _monthNo;

  String? get dateColor => _dateColor;

  int? get selectedIndex => _selectedIndex;

  int? get currentDayIndex => _currentDayIndex;

  bool get initialRenderDone => _initialRenderDone;

  List<Map<String, dynamic>> get dateArrayList => _dateArrayList;

  List<Map<String, dynamic>> get penalityArrayList => _penalityArrayList;

  set currentDayIndex(int? value) {
    _currentDayIndex = value;
  }

  set selectedDate(value) {
    _selectedDate = value;
  }

  Future<void> init(homeprov, context) async {
    _month = DateTime.now();
    _present_month = _month;
    await getMonth(DateFormat('MMMM').format(_month), homeprov, context);
    String formattedDate = DateFormat('yyyy-MM-dd').format(DateTime.now());
    dateWiseAttendance(homeprov, formattedDate, context);
  }

  Future<void> getAttendanceList(homeprov, BuildContext context) async {
    try {
      final data = await ApiCalling.AttendanceListApi(
        homeprov.empId,
        homeprov.session,
      );
      if (data != null) {
        if (data.sessionExists == 1) {
          // _attHistory = data.attHistory!;
          _attendanceStatus = data.attStatus!;
          _isLoading = false;
          notifyListeners();
        } else {
          _isLoading = true;
          // SharedpreferencesService().clearPreferences();
          // Navigator.push(
          //   context,
          //   MaterialPageRoute(builder: (context) => LoginScreen()),
          // );
        }
      } else {
        toast(context, "Something went wrong, Please try again.");
      }
    } on Exception catch (e) {
      print("$e");
    }
  }

  Future<void> dateWiseAttendance(
    homeprov,
    Selecteddate,
    BuildContext context,
  ) async {
    try {
      final data = await ApiCalling.DateWiseAttendanceApi(
        homeprov.empId,
        homeprov.session,
        Selecteddate,
      );
      if (data != null) {
        _date = data.date ?? "";
        _intime = data.intime ?? "";
        _outtime = data.outtime ?? "";
        _inlocation = data.inlocation ?? "";
        _outlocation = data.outlocation ?? "";
        _penalties = data.latePenalties ?? "";
        notifyListeners();
      } else {
        toast(context, "Something went wrong, Please try again.");
      }
    } on Exception catch (e) {
      print("$e");
    }
  }

  Future<void> loadAttendanceDetails(homeprov, BuildContext context) async {
    try {
      final data = await ApiCalling.LoadAttendanceDetails(
        homeprov.empId,
        homeprov.session,
        monthNo,
        year,
      );
      if (data != null) {
        final decodedResponse = jsonDecode(data);
        _presentDays = decodedResponse['present_days'] ?? 0;
        _absentDays = decodedResponse['absent_days'] ?? 0;
        _holidays = decodedResponse['holidays'] ?? 0;
        _latePenalties = decodedResponse['late_penalties'] ?? 0;
        Map<String, dynamic>? dateArray = decodedResponse['date_array'];
        Map<String, dynamic>? latePenaltyArray =
            decodedResponse['late_penalty_array'];

        _dateArrayList = [];
        _penalityArrayList = [];
        _attHistory = decodedResponse['att_history'];

        // Calculate the date range: 26th of previous month to 25th of current month
        DateTime startDate = DateTime(_month.year, _month.month - 1, 26);
        DateTime endDate = DateTime(_month.year, _month.month, 25);

        // Generate date and penalty arrays
        for (
          DateTime date = startDate;
          date.isBefore(endDate.add(Duration(days: 1)));
          date = date.add(Duration(days: 1))
        ) {
          String dayStr = date.day.toString();
          String dateKey = DateFormat('yyyy-MM-dd').format(date);
          String color =
              dateArray != null && dateArray.containsKey(dateKey)
                  ? dateArray[dateKey]
                  : '';
          _dateArrayList.add({dayStr: color});

          int penalty =
              latePenaltyArray != null && latePenaltyArray.containsKey(dateKey)
                  ? latePenaltyArray[dateKey]
                  : 0;
          _penalityArrayList.add({dateKey: penalty});
        }
        print(_dateArrayList);
        print(_penalityArrayList);

        _isLoading = false;
        notifyListeners();
      } else {
        toast(context, "Null response from server.");
      }
    } catch (e) {
      print("Exception: $e");
      toast(context, "Error loading attendance details.");
    }
  }

  Future<void> getMonth(String monthName, homeprov, context) async {
    switch (monthName) {
      case "January":
        _monthNo = 1;
        break;
      case "February":
        _monthNo = 2;
        break;
      case "March":
        _monthNo = 3;
        break;
      case "April":
        _monthNo = 4;
        break;
      case "May":
        _monthNo = 5;
        break;
      case "June":
        _monthNo = 6;
        break;
      case "July":
        _monthNo = 7;
        break;
      case "August":
        _monthNo = 8;
        break;
      case "September":
        _monthNo = 9;
        break;
      case "October":
        _monthNo = 10;
        break;
      case "November":
        _monthNo = 11;
        break;
      case "December":
        _monthNo = 12;
        break;
      default:
        _monthNo = 1;
        break;
    }

    _year = DateFormat('yyyy').format(month);
    notifyListeners();
    await loadAttendanceDetails(homeprov, context);
  }

  Future<void> refresh(homeprov, context) async {
    await Future.delayed(const Duration(seconds: 2));
    _isLoading = true;
    _dateArrayList = [];
    _penalityArrayList = [];
    _initialRenderDone = true;
    _month = DateTime.now();
    await getMonth(DateFormat('MMMM').format(_month), homeprov, context);
    String formattedDate = DateFormat('yyyy-MM-dd').format(DateTime.now());
    dateWiseAttendance(homeprov, formattedDate, context);
    _present_month = month;
    notifyListeners();
  }

  void setPreviousMonth(homeprov, context) {
    _month = DateTime(month.year, month.month - 1);
    resetForNewMonth();
    if (DateFormat('MMMM').format(_present_month) ==
            DateFormat('MMMM').format(_month) &&
        DateFormat('yyyy').format(_present_month) ==
            DateFormat('yyyy').format(_month)) {
      _initialRenderDone = true;
      _month = present_month;
    }
    getMonth(DateFormat('MMMM').format(_month), homeprov, context);
  }

  void setNextMonth(homeprov, context) {
    _month = DateTime(month.year, month.month + 1);
    resetForNewMonth();
    if (DateFormat('MMMM').format(_present_month) ==
            DateFormat('MMMM').format(_month) &&
        DateFormat('yyyy').format(_present_month) ==
            DateFormat('yyyy').format(_month)) {
      _initialRenderDone = true;
      _month = present_month;
    }
    getMonth(DateFormat('MMMM').format(_month), homeprov, context);
  }

  void resetForNewMonth() {
    _dateArrayList = [];
    _penalityArrayList = [];
    _selectedIndex = 0;
    _currentDayIndex = 0;
    _isLoading = true;
    _initialRenderDone = false;
    _date = _intime = _outtime = _inlocation = _outlocation = _penalties = "";
    notifyListeners();
  }
}
