from __future__ import annotations
from datetime import datetime
from typing import Optional
from sqlmodel import Session, select
from .timezone_utils import is_within_hours
from ..model_defs.routing_models import RoutingPool, PoolMember, PoolState


def _reset_if_new_day(state: PoolState) -> None:
    today_key = datetime.utcnow().strftime("%Y-%m-%d")
    if state.date_key != today_key:
        state.assigned_today = {}
        state.date_key = today_key


def _is_member_available(member: PoolMember, state: PoolState) -> bool:
    now = datetime.utcnow()
    if member.ooo_from and member.ooo_to and member.ooo_from <= now <= member.ooo_to:
        return False
    if member.work_hours and not is_within_hours(now, member.work_hours):
        return False
    if member.daily_cap:
        used = (state.assigned_today or {}).get(member.user_id, 0)
        if used >= member.daily_cap:
            return False
    return member.enabled


def _fair_sort_key(
    member: PoolMember, state: PoolState, last_user_id: Optional[str]
) -> tuple:
    used = (state.assigned_today or {}).get(member.user_id, 0)
    is_last = 0 if member.user_id != last_user_id else 1
    return (used, is_last)


def next_user(session: Session, pool_id) -> Optional[str]:
    pool = session.get(RoutingPool, pool_id)
    if not pool or not pool.enabled:
        return None
    state = session.get(PoolState, pool_id)
    if not state:
        state = PoolState(pool_id=pool_id)
        session.add(state)
        session.commit()
        session.refresh(state)

    _reset_if_new_day(state)

    members = session.exec(
        select(PoolMember).where(
            PoolMember.pool_id == pool_id, PoolMember.enabled == True
        )
    ).all()
    available = [m for m in members if _is_member_available(m, state)]
    if not available:
        return None

    available.sort(key=lambda m: _fair_sort_key(m, state, state.last_user_id))
    chosen = available[0]

    used = state.assigned_today.get(chosen.user_id, 0)
    state.assigned_today[chosen.user_id] = used + 1
    state.last_user_id = chosen.user_id
    state.updated_at = datetime.utcnow()
    session.add(state)
    session.commit()
    return chosen.user_id
