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

class Atteendacehistorynotifier with ChangeNotifier {
  // Private State
  DateTime _month = DateTime.now();
  late int _monthNo;
  late DateTime _presentMonth = DateTime.now();

  int _presentDays = 0;
  int _absentDays = 0;
  int _holidays = 0;
  int _latePenalties = 0;

  String _date = "";
  String _intime = "";
  String _outtime = "";
  String _inlocation = "";
  String _outlocation = "";
  String _penalties = "";
  String _selectedDate = "";
  int? _selectedIndex;
  int? _currentDayIndex;
  bool _initialRenderDone = true;
  bool _isLoading = true;

  List<Map<String, dynamic>> _dateArrayList = [];
  List<Map<String, dynamic>> _penaltyArrayList = [];

  String? _empId;
  String? _sessionId;
  String _year = "";

  String? _firstKey;
  dynamic _firstValue;
  int _startingIndex = 0;

  // Public Getters
  DateTime get month => _month;

  int get presentDays => _presentDays;

  int get absentDays => _absentDays;

  int get holidays => _holidays;

  int get latePenalties => _latePenalties;

  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;

  int? get selectedIndex => _selectedIndex;

  int? get currentDayIndex => _currentDayIndex;

  bool get initialRenderDone => _initialRenderDone;

  bool get isLoading => _isLoading;

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

  List<Map<String, dynamic>> get penaltyArrayList => _penaltyArrayList;

  int get startingIndex => _startingIndex;

  AttendanceProvider() {
    _init();
  }

  Future<void> _init() async {
    _month = DateTime.now();
    _presentMonth = _month;
    await _getMonth(DateFormat('MMMM').format(_month));
    await dateWiseAttendance(DateFormat('yyyy-MM-dd').format(DateTime.now()));
    notifyListeners();
  }

  Future<void> refresh() async {
    _isLoading = true;
    _dateArrayList = [];
    _penaltyArrayList = [];
    _initialRenderDone = true;

    _month = DateTime.now();
    _presentMonth = _month;
    await _getMonth(DateFormat('MMMM').format(_month));
    await dateWiseAttendance(DateFormat('yyyy-MM-dd').format(DateTime.now()));
    notifyListeners();
  }

  void setPreviousMonth() async {
    _month = DateTime(_month.year, _month.month - 1);
    _resetForNewMonth();

    if (DateFormat('MMMM yyyy').format(_presentMonth) ==
        DateFormat('MMMM yyyy').format(_month)) {
      _initialRenderDone = true;
      _month = _presentMonth;
    }

    await _getMonth(DateFormat('MMMM').format(_month));
  }

  void setNextMonth() async {
    _month = DateTime(_month.year, _month.month + 1);
    _resetForNewMonth();

    if (DateFormat('MMMM yyyy').format(_presentMonth) ==
        DateFormat('MMMM yyyy').format(_month)) {
      _initialRenderDone = true;
      _month = _presentMonth;
    }

    await _getMonth(DateFormat('MMMM').format(_month));
  }

  void _resetForNewMonth() {
    _dateArrayList = [];
    _penaltyArrayList = [];
    _selectedIndex = 0;
    _currentDayIndex = 0;
    _isLoading = true;
    _date = _intime = _outtime = _inlocation = _outlocation = _penalties = "";
    notifyListeners();
  }

  Future<void> _getMonth(String monthName) async {
    _empId = await SharedpreferencesService().getString("UserId");
    _sessionId = await SharedpreferencesService().getString("Session_id");

    _monthNo = DateFormat('MMMM').parse(monthName).month;
    _year = DateFormat('yyyy').format(_month);

    await _loadAttendanceDetails();
  }

  Future<void> _loadAttendanceDetails() async {
    try {
      final data = await ApiCalling.LoadAttendanceDetails(
        _empId,
        _sessionId,
        _monthNo,
        _year,
      );
      if (data != null) {
        final decoded = jsonDecode(data);

        _presentDays = decoded['present_days'] ?? 0;
        _absentDays = decoded['absent_days'] ?? 0;
        _holidays = decoded['holidays'] ?? 0;
        _latePenalties = decoded['late_penalties'] ?? 0;

        Map<String, dynamic>? dateArray = decoded['date_array'];
        Map<String, dynamic>? penaltyArray = decoded['late_penalty_array'];

        if (dateArray != null) {
          _firstKey = dateArray.keys.first;
          _firstValue = dateArray[_firstKey];
          _dateArrayList =
              dateArray.entries.map((e) {
                final parts = e.key.split("-");
                final date = parts[2];
                return {date: e.value};
              }).toList();

          if (_firstKey != null) {
            final parsedDate = DateTime.tryParse(_firstKey!);
            if (parsedDate != null) {
              List<String> weekdays = [
                'Sunday',
                'Monday',
                'Tuesday',
                'Wednesday',
                'Thursday',
                'Friday',
                'Saturday',
              ];
              final dayOfWeek = DateFormat('EEEE').format(parsedDate);
              _startingIndex = weekdays.indexOf(dayOfWeek);
            }
          }
        }

        if (penaltyArray != null) {
          _penaltyArrayList =
              penaltyArray.entries.map((e) => {e.key: e.value}).toList();
        }

        _isLoading = false;
        notifyListeners();
      }
    } catch (e) {
      print("Error loading attendance: $e");
    }
  }

  Future<void> dateWiseAttendance(String selected) async {
    _empId = await SharedpreferencesService().getString("UserId");
    _sessionId = await SharedpreferencesService().getString("Session_id");

    try {
      final data = await ApiCalling.DateWiseAttendanceApi(
        _empId,
        _sessionId,
        selected,
      );
      if (data != null) {
        _date = data.date!;
        _intime = data.intime!;
        _outtime = data.outtime!;
        _inlocation = data.inlocation!;
        _outlocation = data.outlocation!;
        _penalties = data.latePenalties!;
        notifyListeners();
      }
    } catch (e) {
      print("DateWiseAttendance error: $e");
    }
  }

  void selectDate(int index, String selected, String? penaltyKey) {
    _selectedIndex = index;
    _initialRenderDone = false;
    _selectedDate = selected;
    if (penaltyKey != null) {
      dateWiseAttendance(penaltyKey);
    }
    notifyListeners();
  }
}
