import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/dashboard_api_client.dart';
import 'package:mohem_flutter_app/api/offers_and_discounts_api_client.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/dashboard/drawer_menu_item_model.dart';
import 'package:mohem_flutter_app/models/dashboard/get_accrual_balances_list_model.dart';
import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart';
import 'package:mohem_flutter_app/models/dashboard/get_open_notifications_list.dart';
import 'package:mohem_flutter_app/models/dashboard/itg_forms_model.dart';
import 'package:mohem_flutter_app/models/dashboard/list_menu.dart';
import 'package:mohem_flutter_app/models/dashboard/menu_entries.dart';
import 'package:mohem_flutter_app/models/dashboard/menus.dart';
import 'package:mohem_flutter_app/models/dashboard/mohemm_itg_pending_task_responseitem.dart';
import 'package:mohem_flutter_app/models/generic_response_model.dart';
import 'package:mohem_flutter_app/models/itg/itg_response_model.dart';
import 'package:mohem_flutter_app/models/offers_and_discounts/get_offers_list.dart';
import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart';
import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart';

/// Mix-in [DiagnosticableTreeMixin] to have access to [debugFillProperties] for the devtool
// ignore: prefer_mixin
class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
  //Attendance Tracking
  bool isAttendanceTrackingLoading = true;
  int endTime = 0, isTimeRemainingInSeconds = 0;
  double progress = 0.0;
  GetAttendanceTracking? attendanceTracking;

  //Work List
  bool isWorkListLoading = true;
  int workListCounter = 0;



  //Misssing Swipe
  bool isMissingSwipeLoading = true;
  int missingSwipeCounter = 0;

  //Leave and Ticket Balance
  bool isLeaveTicketBalanceLoading = true;
  List<GetAccrualBalancesList>? accrualList;
  GetAccrualBalancesList? leaveBalanceAccrual;

  double get leaveBalance => leaveBalanceAccrual?.accrualNetEntitlement ?? 0;
  double ticketBalance = 0;

  //Menu Entries
  bool isServicesMenusLoading = true;
  List<Menus>? homeMenus;
  List<GetMenuEntriesList>? getMenuEntriesList;

  //Offers And Discounts
  bool isOffersLoading = true;
  List<OffersListModel> getOffersList = [];

  //Attendance Tracking API's & Methods
  Future<bool> fetchAttendanceTracking(context) async {
    try {
      attendanceTracking = await DashboardApiClient().getAttendanceTracking();
      isAttendanceTrackingLoading = false;
      // isTimeRemainingInSeconds = calculateSeconds( "00:00:00");
      if (attendanceTracking?.pSwipeIn != null) {
        isTimeRemainingInSeconds = calculateSeconds(attendanceTracking!.pRemainingHours ?? "00:00:00");
        int totalShiftTimeInSeconds = calculateSeconds(attendanceTracking!.pScheduledHours ?? "00:00:00");
        progress = (isTimeRemainingInSeconds / totalShiftTimeInSeconds);
        endTime = DateTime.now().millisecondsSinceEpoch + Duration(seconds: isTimeRemainingInSeconds).inMilliseconds;
      }
      notifyListeners();
    } catch (ex) {
      Utils.handleException(ex, context, null);
    }
    return true;
  }

  void initProvider() {
    isAttendanceTrackingLoading = true;
    endTime = 0;
    isTimeRemainingInSeconds = 0;
    progress = 0.0;
    attendanceTracking = null;

    isWorkListLoading = true;
    workListCounter = 0;

    isMissingSwipeLoading = true;
    missingSwipeCounter = 0;

    isLeaveTicketBalanceLoading = true;
    accrualList = null;
    leaveBalanceAccrual = null;


    ticketBalance = 0;
    isServicesMenusLoading = true;
    homeMenus = null;
    getMenuEntriesList = null;
    isOffersLoading = true;
    getOffersList = [];

    drawerMenuItemList = [
      DrawerMenuItem("assets/images/drawer/my_profile.svg", LocaleKeys.myProfile.tr(), AppRoutes.profile),
      DrawerMenuItem("assets/images/drawer/performance_evaluation.svg", LocaleKeys.performanceEvaluation.tr(), AppRoutes.performanceEvaluation),
      DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.mowadhafhi.tr(), AppRoutes.mowadhafhi),
      DrawerMenuItem("assets/images/drawer/pending_trasactions.svg", LocaleKeys.pendingTransactions.tr(), AppRoutes.pendingTransactions),
      DrawerMenuItem("assets/images/drawer/drawer_marathon.svg", LocaleKeys.brainMarathon.tr(), AppRoutes.marathonIntroScreen),
      DrawerMenuItem("assets/images/drawer/change_password.svg", LocaleKeys.changePassword.tr(), AppRoutes.changePassword),
    ];

    notifyListeners();
  }

  int calculateSeconds(String time) {
    int hour = int.parse(time.split(":")[0]);
    int mints = int.parse(time.split(":")[1]);
    int seconds = int.parse(time.split(":")[2]);
    return ((hour * 60 * 60) + (mints * 60) + seconds);
  }

  void update(context) {
    fetchAttendanceTracking(context);
  }

  ItgFormsModel? itgFormsModel;
  List<GetOpenNotificationsList>? getOpenNotificationsList;
  MohemmITGPendingTaskResponseItem? cocCount;
  int cocFinalCount = 0;

  //Work List API's & Methods
  Future fetchWorkListCounter(context, {bool showLoading = false}) async {
    try {
      if (showLoading) Utils.showLoading(context);
      GenericResponseModel? genericResponseModel = await DashboardApiClient().getOpenNotifications();

      isWorkListLoading = false;
      getOpenNotificationsList = genericResponseModel?.getOpenNotificationsList;

      workListCounter = genericResponseModel?.pOPENNTFNUMBER ?? 0;

      itgFormsModel = await DashboardApiClient().getItgFormsPendingTask();
      workListCounter = workListCounter + (itgFormsModel?.totalCount ?? 0);
      GenericResponseModel? cocGenericResponseModel = await DashboardApiClient().getCOCNotifications();
      cocCount = cocGenericResponseModel?.mohemmITGPendingTaskResponseItem;
      if (cocCount != null) {
        cocFinalCount = (cocCount?.escalation ?? 0) + (cocCount?.waitingToClose ?? 0) + (cocCount?.waitingForAcceptance ?? 0) + (cocCount?.extendTATRequest ?? 0);
        workListCounter += cocFinalCount;
      }
      if (showLoading) Utils.hideLoading(context);
      notifyListeners();
    } catch (ex) {
      isWorkListLoading = false;
      logger.wtf(ex);
      if (showLoading) Utils.hideLoading(context);
      notifyListeners();
      Utils.handleException(ex, context, (err) {
        Utils.hideLoading(context);
        showDialog(
          context: context,
          builder: (cxt) => ConfirmDialog(
            message: err,
            onTap: () {
              Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.login, (Route<dynamic> route) => false);
            },
          ),
        );
      });
    }
  }

  //Missing Siwpe API's & Methods
  Future fetchMissingSwipe(context) async {
    try {
      GenericResponseModel? genericResponseModel = await DashboardApiClient().getOpenMissingSwipes();
      isMissingSwipeLoading = false;
      missingSwipeCounter = genericResponseModel!.getOpenMissingSwipesList!.pOpenMissingSwipes ?? 0;
      notifyListeners();
    } catch (ex) {
      isMissingSwipeLoading = false;
      logger.wtf(ex);
      notifyListeners();
      Utils.handleException(ex, context, null);
    }
  }

  //Leave and Ticket Balance API's & Methods
  Future fetchLeaveTicketBalance(context, DateTime date) async {
    try {
      accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(date));
      isLeaveTicketBalanceLoading = false;
      leaveBalanceAccrual = accrualList![0];
      ticketBalance = (accrualList![1].accrualNetEntitlement ?? 0.0) + (accrualList![2].accrualNetEntitlement ?? 0.0);
      notifyListeners();
    } catch (ex) {
      isLeaveTicketBalanceLoading = false;
      logger.wtf(ex);
      notifyListeners();
      Utils.handleException(ex, context, null);
    }
  }

  //List Menu API's & Methods

  List<DrawerMenuItem> drawerMenuItemList = [];

  void fetchListMenu() async {
    try {
      List<ListMenu> menuList = await DashboardApiClient().getListMenu();
      List findMyRequest = menuList.where((element) => element.menuType == "E").toList();
      if (findMyRequest.isNotEmpty) {
        drawerMenuItemList.insert(3, DrawerMenuItem("assets/images/drawer/my_requests.svg", LocaleKeys.myRequest.tr(), AppRoutes.myRequests));
      }
      List findMyTeam = menuList.where((element) => element.menuType == "M").toList();
      if (findMyTeam.isNotEmpty) {
        drawerMenuItemList.insert(2, DrawerMenuItem("assets/images/drawer/my_team.svg", LocaleKeys.myTeamMembers.tr(), AppRoutes.myTeam));
      }
    } catch (ex) {
      logger.wtf(ex);
      Utils.handleException(ex, null, null);
    }
  }

  //Menu Entries API's & Methods
  void fetchMenuEntries() async {
    try {
      GenericResponseModel? genericResponseModel = await DashboardApiClient().getGetMenuEntries();
      getMenuEntriesList = genericResponseModel!.getMenuEntriesList;
      homeMenus = parseMenus(getMenuEntriesList ?? []);
      if (homeMenus!.isNotEmpty) {
        homeMenus!.first.menuEntiesList.insert(0, GetMenuEntriesList(requestType: "MONTHLY_ATTENDANCE", prompt: LocaleKeys.monthlyAttendance.tr()));
        homeMenus!.first.menuEntiesList.add(GetMenuEntriesList(requestType: "VACATION_RULE", prompt: LocaleKeys.vacationRule.tr()));
      }
      isServicesMenusLoading = false;
      notifyListeners();
    } catch (ex) {
      logger.wtf(ex);
      notifyListeners();
      Utils.handleException(ex, null, null);
    }
  }

  void getCategoryOffersListAPI(BuildContext context) async {
    try {
      // Utils.showLoading(context);
      getOffersList = await OffersAndDiscountsApiClient().getOffersList(0, 6);
      isOffersLoading = false;
      notifyListeners();
    } catch (ex) {
      // Utils.hideLoading(context);
      notifyListeners();
      Utils.handleException(ex, context, null);
    }
  }

  List<Menus> parseMenus(List<GetMenuEntriesList> getMenuEntriesList) {
    List<Menus> menus = [];
    for (int i = 0; i < getMenuEntriesList.length; i++) {
      if (getMenuEntriesList[i].parentMenuName!.isEmpty) {
        menus.add(Menus(getMenuEntriesList[i], getMenuEntriesList.where((element) => getMenuEntriesList[i].menuName == element.parentMenuName).toList()));
      }
    }
    return menus;
  }

  Future<MohemmItgResponseItem?> getITGNotification() async {
    MohemmItgResponseItem? res = await DashboardApiClient().getITGPageNotification();
    return res;
  }
  void notify() {
    notifyListeners();
  }
}
