from datetime import date

from sqlalchemy import func, select
from sqlalchemy.orm import Session

from app.db.models import Child
from app.schemas.models import ChildCreateRequest, ChildUpdateRequest


def calc_age(birthday: date) -> int:
    today = date.today()
    age = today.year - birthday.year
    if (today.month, today.day) < (birthday.month, birthday.day):
        age -= 1
    return age


def child_to_dict(child: Child) -> dict:
    return {
        "id": child.id,
        "name": child.name,
        "birthday": child.birthday.isoformat(),
        "age": calc_age(child.birthday),
        "height": float(child.height) if child.height is not None else None,
        "weight": float(child.weight) if child.weight is not None else None,
        "status": child.status,
    }


def list_children(db: Session, parent_user_id: int, page: int, page_size: int) -> tuple[list[Child], int]:
    filters = (Child.parent_user_id == parent_user_id, Child.status != "archived")
    total = db.scalar(select(func.count()).select_from(Child).where(*filters)) or 0
    items = db.scalars(
        select(Child)
        .where(*filters)
        .order_by(Child.id.desc())
        .offset((page - 1) * page_size)
        .limit(page_size)
    ).all()
    return items, total


def get_child(db: Session, parent_user_id: int, child_id: int) -> Child | None:
    return db.scalar(
        select(Child).where(
            Child.id == child_id,
            Child.parent_user_id == parent_user_id,
            Child.status != "archived",
        )
    )


def create_child(db: Session, parent_user_id: int, tenant_id: int | None, body: ChildCreateRequest) -> Child:
    child = Child(
        parent_user_id=parent_user_id,
        tenant_id=tenant_id,
        name=body.name,
        birthday=body.birthday,
        gender=body.gender.value,
        height=body.height,
        weight=body.weight,
        contraindications=body.contraindications,
        status="active",
    )
    db.add(child)
    db.commit()
    db.refresh(child)
    return child


def update_child(db: Session, child: Child, body: ChildUpdateRequest) -> Child:
    child.name = body.name
    child.birthday = body.birthday
    child.gender = body.gender.value
    child.height = body.height
    child.weight = body.weight
    child.contraindications = body.contraindications
    db.commit()
    db.refresh(child)
    return child


def archive_child(db: Session, child: Child) -> None:
    from datetime import datetime, timezone

    child.status = "archived"
    child.deleted_at = datetime.now(timezone.utc)
    db.commit()
