import random
from datetime import datetime, timedelta

# Define the list of persons
primary_persons = ["NTALAMPEKOU", "MAFOUNI", "MEMIS", "RAISAKIS", "ENECHELIDOU", "DIMADIS"]
secondary_persons = ["SACHANIDOU", "VASILIADIS", "PAPAGEORGIOU", "KARAISKOS", "TSIPLAKIS", "SPANTIDAKIS", "PAPADOPOULOS"]

# Define the days they can't be on duty
unavailable_days = {
    "NTALAMPEKOU": ["2024-08-12", "2024-08-13", "2024-08-14", "2024-08-15", "2024-08-16", "2024-08-17", "2024-08-18", "2024-08-19"],
    "MAFOUNI": ["2024-08-20", "2024-08-21", "2024-08-22", "2024-08-23", "2024-08-24", "2024-08-25"],
    "MEMIS": ["2024-08-01", "2024-08-02", "2024-08-03", "2024-08-04", "2024-08-05", "2024-08-06", "2024-08-07"],
    "RAISAKIS": ["2024-08-10", "2024-08-11", "2024-08-12", "2024-08-13", "2024-08-15", "2024-08-16", "2024-08-17"],
    "ENECHELIDOU": ["2024-08-12", "2024-08-13", "2024-08-14", "2024-08-15", "2024-08-16", "2024-08-17"],
    "DIMADIS": ["2024-08-05", "2024-08-06", "2024-08-07"],
    "SACHANIDOU": ["2024-08-21", "2024-08-22", "2024-08-23", "2024-08-24", "2024-08-25"],
    "VASILIADIS": ["2024-08-10", "2024-08-11", "2024-08-12", "2024-08-13", "2024-08-14", "2024-08-15"],
    "PAPAGEORGIOU": ["2024-08-01", "2024-08-02", "2024-08-03", "2024-08-04", "2024-08-05", "2024-08-07"],
    "KARAISKOS": ["2024-08-11", "2024-08-12", "2024-08-13", "2024-08-14", "2024-08-15"],
    "TSIPLAKIS": ["2024-08-15"],
    "SPANTIDAKIS": ["2024-08-14", "2024-08-15", "2024-08-16"],
    "PAPADOPOULOS": ["2024-08-12", "2024-08-13", "2024-08-14", "2024-08-15"]
}

# Define the history of previous months based on the table
previous_duties = {
    "NTALAMPEKOU": 24,
    "MAFOUNI": 22,
    "MEMIS": 22,
    "RAISAKIS": 24,
    "ENECHELIDOU": 0,
    "DIMADIS": 27,
    "SACHANIDOU": 9,
    "VASILIADIS": 12,
    "PAPAGEORGIOU": 11,
    "KARAISKOS": 11,
    "TSIPLAKIS": 8,
    "SPANTIDAKIS": 11,
    "PAPADOPOULOS": 22
}

# Define the history of duties on specific days of the week
weekly_duties = {
    "NTALAMPEKOU": {"Monday": 3, "Tuesday": 4, "Wednesday": 5, "Thursday": 5, "Friday": 1, "Saturday": 3, "Sunday": 3},
    "MAFOUNI": {"Monday": 2, "Tuesday": 5, "Wednesday": 5, "Thursday": 4, "Friday": 2, "Saturday": 2, "Sunday": 2},
    "MEMIS": {"Monday": 5, "Tuesday": 1, "Wednesday": 2, "Thursday": 2, "Friday": 4, "Saturday": 4, "Sunday": 4},
    "RAISAKIS": {"Monday": 2, "Tuesday": 3, "Wednesday": 6, "Thursday": 4, "Friday": 3, "Saturday": 4, "Sunday": 2},
    "ENECHELIDOU": {"Monday": 0, "Tuesday": 0, "Wednesday": 0, "Thursday": 0, "Friday": 0, "Saturday": 0, "Sunday": 0},
    "DIMADIS": {"Monday": 5, "Tuesday": 3, "Wednesday": 1, "Thursday": 3, "Friday": 5, "Saturday": 3, "Sunday": 7},
    "SACHANIDOU": {"Monday": 1, "Tuesday": 2, "Wednesday": 3, "Thursday": 0, "Friday": 1, "Saturday": 1, "Sunday": 1},
    "VASILIADIS": {"Monday": 1, "Tuesday": 2, "Wednesday": 0, "Thursday": 4, "Friday": 2, "Saturday": 1, "Sunday": 2},
    "PAPAGEORGIOU": {"Monday": 1, "Tuesday": 1, "Wednesday": 1, "Thursday": 2, "Friday": 2, "Saturday": 3, "Sunday": 1},
    "KARAISKOS": {"Monday": 1, "Tuesday": 3, "Wednesday": 2, "Thursday": 0, "Friday": 2, "Saturday": 2, "Sunday": 1},
    "TSIPLAKIS": {"Monday": 2, "Tuesday": 0, "Wednesday": 0, "Thursday": 1, "Friday": 2, "Saturday": 1, "Sunday": 2},
    "SPANTIDAKIS": {"Monday": 1, "Tuesday": 2, "Wednesday": 0, "Thursday": 2, "Friday": 3, "Saturday": 2, "Sunday": 1},
    "PAPADOPOULOS": {"Monday": 3, "Tuesday": 4, "Wednesday": 4, "Thursday": 3, "Friday": 2, "Saturday": 3, "Sunday": 3}
}

# Predefined duty days
predefined_duties = {
    "SACHANIDOU": ["2024-08-21"],
    "MEMIS": ["2024-08-23"],
    "NTALAMPEKOU": ["2024-08-25"],
    "RAISAKIS": ["2024-08-18"],
    "MAFOUNI": ["2024-08-15"]
}

# Function to check availability
def is_available(person, date):
    return date not in unavailable_days.get(person, []) and date not in predefined_duties.get(person, [])

# Generate the schedule
def generate_schedule(month, year):
    schedule = {}
    date = datetime(year, month, 1)
    primary_duties = {p: 0 for p in primary_persons}
    secondary_duties = {p: 0 for p in secondary_persons}
    
    # Assign predefined duties
    for person, dates in predefined_duties.items():
        for duty_date in dates:
            schedule[duty_date] = person
            primary_duties[person] += 1
            previous_duties[person] += 1
            day_of_week = datetime.strptime(duty_date, "%Y-%m-%d").strftime("%A")
            weekly_duties[person][day_of_week] += 1
    
    # Assign one Saturday or Sunday to each primary person
    weekends = [date + timedelta(days=i) for i in range((5 - date.weekday()) % 7, 31, 7)] + [date + timedelta(days=i) for i in range((6 - date.weekday()) % 7, 31, 7)]
    random.shuffle(weekends)
    for person in primary_persons:
        for weekend in weekends:
            if is_available(person, weekend.strftime("%Y-%m-%d")):
                schedule[weekend.strftime("%Y-%m-%d")] = person
                primary_duties[person] += 1
                previous_duties[person] += 1
                day_of_week = weekend.strftime("%A")
                weekly_duties[person][day_of_week] += 1
                weekends.remove(weekend)
                break
    
    while date.month == month:
        day_of_week = date.strftime("%A")
        date_str = date.strftime("%Y-%m-%d")
        
        if date_str not in schedule:
            available_primary = [p for p in primary_persons if is_available(p, date_str) and primary_duties[p] < 3]
            available_secondary = [p for p in secondary_persons if is_available(p, date_str) and and secondary_duties[p] < 2]
            
            if available_primary:
                available_primary.sort(key=lambda p: (previous_duties.get(p, 0), weekly_duties[p][day_of_week]))
                person = available_primary[0]
                primary_duties[person] += 1
            elif available_secondary:
                available_secondary.sort(key=lambda p: (previous_duties.get(p, 0), weekly_duties[p][day_of_week]))
                person = available_secondary[0]
                secondary_duties[person] += 1
            
            schedule[date_str] = person
        
        date += timedelta(days=1)
    
    return schedule

# Example usage
schedule = generate_schedule(8, 2024)
for day, person in schedule.items():
    print(f"{day}: {person}")