from datetime import datetime, timedelta
from typing import Any, Dict, Iterable, List, Optional, Tuple

from django.db.models import Q

from staff.person.models import Staff
from staff.person.notifications import send_password_reminder_mails

NIAGARA_DAYS = timedelta(days=3)


def expiration_q(now: datetime, weeks: int) -> Q:
    return Q(
        ad_information__password_expires_at__gt=now + timedelta(days=7 * weeks - 7),
        ad_information__password_expires_at__lte=now + timedelta(days=7 * weeks),
    )


def get_persons_to_remind(
    person_logins: List[str] = None,
    now: Optional[datetime] = None,
) -> Iterable[Tuple[str, Dict[str, Any]]]:
    now = now or datetime.now()

    dates_filter = expiration_q(now, weeks=1)
    if now.weekday() in (0, 2, 4):
        dates_filter |= expiration_q(now, weeks=2)
    if now.weekday() in (1, 3):
        dates_filter |= expiration_q(now, weeks=3)
    if now.weekday() == 2:
        dates_filter |= expiration_q(now, weeks=4)

    persons = (
        Staff.objects
        .filter(is_dismissed=False, is_robot=False)
        .filter(dates_filter)
        .values('work_email', 'login', 'ad_information__password_expires_at')
    )

    if person_logins:
        persons = persons.filter(login__in=person_logins)

    for person in persons:
        person['expire_date'] = person['ad_information__password_expires_at']
        person['day_rest'] = (person['ad_information__password_expires_at'].date() - now.date()).days
        person['niagara_date'] = person['expire_date'] - NIAGARA_DAYS
        yield person['work_email'], person


def password_reminder(person_logins=None):
    send_password_reminder_mails(get_persons_to_remind(person_logins=person_logins))
