import schedule
import time
from datetime import timedelta
import datetime
from dotenv import load_dotenv # load env variables
import pymongo # for connecting to the db
import os

class MAIN():
    def __init__(self):
        load_dotenv()

        self.db_client : {} = pymongo.MongoClient(os.getenv("DB_URI"))
        self.log_dir : str = 'logs'
        self.log_file : str = 'scheduler.log'
        self.db_name = "Infinity"

    # statistics
    def save_this_week_overview_into_this_month(self):
        db = self.db_client[self.db_name]
        collection = db["statistics"]
        query , projection = {} , {"listsTracking.thisWeek" : 1}
        docs = collection.find(query , projection)

        # Get the current date
        current_date = datetime.date.today()
        day = current_date.day
        current_week_number = (day - 1) // 7 + 1

        # each doc is related to specific user
        for doc in docs:
            year , month , week , days = doc["listsTracking"]["thisWeek"]["year"] , doc["listsTracking"]["thisWeek"]["month"], doc["listsTracking"]["thisWeek"]["week"], doc["listsTracking"]["thisWeek"]["days"]

            this_month_exist = collection.find_one({"listsTracking.months.year": year , "listsTracking.months.month" : month})

            # push the week to the related month
            if not this_month_exist:

                month_obj = {
                    "year": year,
                    "month": month,
                    "weeks": []
                }

                collection.update_one({} , 
                    {
                        "$push": {
                            "listsTracking.months": month_obj
                        }
                    }
                )

                week_obj = {
                    "week": week,
                    "days": days,
                }

                collection.update_one({"listsTracking.months.month": month} , 
                    {
                        "$push": {
                            "listsTracking.months.$.weeks": week_obj
                        }
                    }
                )

            else : # the month exist & at least contain one week

                week_obj = {
                    "week": week,
                    "days": days,
                }

                collection.update_one({"listsTracking.months.month": month} , 
                    {
                        "$push": {
                            "listsTracking.months.$.weeks": week_obj
                        }
                    }
                )

            # reset the thisWeek data
            collection.update_one({} , {
                "$set" : {
                    "listsTracking.thisWeek": {
                        "year": year,
                        "month": datetime.datetime.today().month - 1,
                        "week": current_week_number,
                        "days" : {
                            "sat": {
                                'totalMembers': 0,
                                'totalActiveSubs': 0,
                                'totalUnActiveSubs': 0,
                                'totalMansMembers': 0,
                                'totalGirlsMembers': 0,
                            },
                            "sun": {
                                'totalMembers': 0,
                                'totalActiveSubs': 0,
                                'totalUnActiveSubs': 0,
                                'totalMansMembers': 0,
                                'totalGirlsMembers': 0,
                            },
                            "mon": {
                                'totalMembers': 0,
                                'totalActiveSubs': 0,
                                'totalUnActiveSubs': 0,
                                'totalMansMembers': 0,
                                'totalGirlsMembers': 0,
                            },
                            "tue": {
                                'totalMembers': 0,
                                'totalActiveSubs': 0,
                                'totalUnActiveSubs': 0,
                                'totalMansMembers': 0,
                                'totalGirlsMembers': 0,
                            },
                            "wed": {
                                'totalMembers': 0,
                                'totalActiveSubs': 0,
                                'totalUnActiveSubs': 0,
                                'totalMansMembers': 0,
                                'totalGirlsMembers': 0,
                            },
                            "thu": {
                                'totalMembers': 0,
                                'totalActiveSubs': 0,
                                'totalUnActiveSubs': 0,
                                'totalMansMembers': 0,
                                'totalGirlsMembers': 0,
                            },
                            "fri": {
                                'totalMembers': 0,
                                'totalActiveSubs': 0,
                                'totalUnActiveSubs': 0,
                                'totalMansMembers': 0,
                                'totalGirlsMembers': 0,
                            }
                        }
                    }
                }
            })

        # save to the log file
        log_line = '----------------------------------------' + '\n' + 'The week ' + str(week) + ' has been saved into the month ' + str(month) + '\n' + '----------------------------------------' + '\n' 
        with open(self.log_dir+'/'+self.log_file , 'a') as f:
            f.write(log_line)

    def save_this_month_overview_into_this_year(self):
        current_month = datetime.datetime.now().month
        db = self.db_client[self.db_name]
        collection = db["statistics"]
        query , projection = {"listsTracking.months.month" : current_month} , {"listsTracking.months.$" : 1}
        docs = collection.find(query , projection)

        for doc in docs:
            year , month , weeks = doc['listsTracking']['months'][0]['year'] , doc['listsTracking']['months'][0]['month'] , doc['listsTracking']['months'][0]['weeks']
            year_doc = collection.find_one({'listsTracking.years.year': year})
            if not year_doc:
                collection.update_one({} , {
                    '$push': {
                        'listsTracking.years': {
                            'year': year,
                            'months': []
                        }
                    }
                })
                collection.update_one({'listsTracking.years.year': year} , {
                    '$push': {
                        'listsTracking.years.$.months': doc['listsTracking']['months'][0]
                    }
                })

            elif year_doc:
                collection.update_one({'listsTracking.years.year': year} , {
                    '$push': {
                        'listsTracking.years.$.months': doc['listsTracking']['months'][0]
                    }
                })

        # save to the log file
        log_line = '----------------------------------------' + '\n' + 'The month ' + str(month) + ' has been saved into the year ' + str(year) + '\n' + '----------------------------------------' + '\n' 
        with open(self.log_dir+'/'+self.log_file , 'a') as f:
            f.write(log_line)

    def save_this_day_members_overview(self):
        days_arr = ['sun','mon','tue','wed','thu','fri','sat']
        # set the coll
        db = self.db_client[self.db_name]
        members_coll = db["members"]
        statistics_coll = db["statistics"]
        # get all members
        members_doc = list(members_coll.find({}))
        # generate the report
        report = {
            'totalMembers': 0,
            'totalActiveSubs': 0,
            'totalUnActiveSubs': 0,
            'totalMansMembers': 0,
            'totalGirlsMembers': 0,
        }
        print(members_doc , "members_doc")
        # total members
        report["totalMembers"] = len(members_doc)
        # totalActiveSubs totalUnActiveSubs totalMansMembers totalGirlsMembers
        activeSubs = 0
        totalMans = 0
        for doc in members_doc:
            if doc["active"]:
                activeSubs = activeSubs + 1
            if doc["gendre"] == 'm':
                totalMans = totalMans + 1
        report["totalActiveSubs"] = activeSubs
        report["totalUnActiveSubs"] = len(members_doc) - activeSubs
        report["totalMansMembers"] = totalMans
        report["totalGirlsMembers"] = len(members_doc) - totalMans
        # save the report
        statistics_coll.update_one({} , {
            '$set': {
                'listsTracking.thisWeek.days.{}'.format(days_arr[int(datetime.datetime.today().strftime('%w'))]) : report
            }
        })

    def core(self):
        schedule.every().saturday.at("23:59").do(self.save_this_week_overview_into_this_month) 
        schedule.every().day.at("01:00").do(self.save_this_day_members_overview)
        # Check if today is the last day of the month
        now = datetime.datetime.now()
        last_day_of_month = (now + timedelta(days=32 - now.day)).replace(day=1) - timedelta(days=1)

        if now == last_day_of_month:
            self.save_this_month_overview_into_this_year()


if __name__ == '__main__':
    main = MAIN()
    main.core()
    # Run the scheduled tasks in a loop
    while True:
        schedule.run_pending()
        time.sleep(10)