import datetime
import logging
from sqlalchemy.orm import (
    Session,
    Query,
    joinedload,
)
from watcher.logic.timezone import now
from watcher.config import settings
from watcher.db import (
    Notification,
    Shift,
    Schedule,
)
from watcher.enums import (
    NotificationState,
    NotificationType,
    ShiftStatus,
)

logger = logging.getLogger(__name__)

NOTIFY_QUERY = '''
select sh.id, sh.staff_id
from shift sh where
sh.status = '{}'
and sh.staff_id is not null
and sh.schedule_id in (
    select id from schedule
    where days_for_notify_of_begin is not null
)
and sh.start::date in (
    select CURRENT_DATE + extract(days from c.elem)::int from (
    select unnest(s.days_for_notify_of_begin) as elem from schedule s
    where s.id = sh.schedule_id) c where extract(days from c.elem)::int != 0 --по сменам начинающимся сегодня отправит start_shift
)
and not exists (
    select * from shift sh1
    where sh1.replacement_for_id = sh.id
)
'''.format(ShiftStatus.scheduled)


def query_unsend_notifications(db: Session) -> Query:
    return db.query(Notification).filter(
        Notification.state == NotificationState.new,
        Notification.send_at <= now(),
    ).options(
        joinedload(Notification.staff),
        (joinedload(Notification.shift)
         .joinedload(Shift.schedule)
         .joinedload(Schedule.service)),
    )


def create_shift_starting_now_notification(db: Session, shift: Shift) -> None:
    if shift.schedule.days_for_notify_of_begin and datetime.timedelta(days=0) in shift.schedule.days_for_notify_of_begin:
        action = 'Creating'
        notification = Notification(
            valid_to=shift.start + datetime.timedelta(minutes=settings.START_NOTIFY_VALID),
            shift_id=shift.id,
            type=NotificationType.start_shift,
            staff_id=shift.staff_id,
            send_at=shift.start,
        )
        db.add(notification)
    else:
        action = 'Skipping'
    logger.info(f'{action} notification about starting now shift: {shift.id}')


def get_shifts_for_notify_start_soon(db: Session) -> list:
    shifts_query = db.execute(NOTIFY_QUERY)
    return [
        {
            'shift_id': shift_id,
            'staff_id': staff_id,
        }
        for shift_id, staff_id,
        in shifts_query
    ]
