"""Intake: notes, files, and links an admin gathers from the client."""

from sqlalchemy import select
from sqlalchemy.orm import Session

from app.constants import MaterialKind
from app.models.material import Material
from app.services import storage


def list_for_project(db: Session, project_id: int) -> list[Material]:
    stmt = (
        select(Material)
        .where(Material.project_id == project_id)
        .order_by(Material.created_at.desc(), Material.id.desc())
    )
    return list(db.scalars(stmt))


def get(db: Session, project_id: int, material_id: int) -> Material | None:
    material = db.get(Material, material_id)
    if material is None or material.project_id != project_id:
        return None
    return material


def add_note(db: Session, project_id: int, *, title: str, body: str, added_by: str) -> Material:
    material = Material(
        project_id=project_id,
        kind=MaterialKind.NOTE,
        title=title.strip(),
        body=body.strip(),
        added_by=added_by,
    )
    db.add(material)
    db.commit()
    db.refresh(material)
    return material


def add_link(db: Session, project_id: int, *, title: str, url: str, added_by: str) -> Material:
    material = Material(
        project_id=project_id,
        kind=MaterialKind.LINK,
        title=title.strip(),
        url=url.strip(),
        added_by=added_by,
    )
    db.add(material)
    db.commit()
    db.refresh(material)
    return material


def add_file(
    db: Session,
    project_id: int,
    *,
    title: str,
    filename: str,
    content: bytes,
    mime: str,
    added_by: str,
) -> Material:
    """Validates against the D13 rules (extension allowlist, size cap), stores
    under a UUID name, and keeps the original filename as metadata only."""
    storage.validate_upload(filename, len(content))
    relative_path = storage.store_bytes(f"projects/{project_id}/materials", filename, content)
    material = Material(
        project_id=project_id,
        kind=MaterialKind.FILE,
        title=title.strip() or filename,
        file_path=relative_path,
        file_name=filename,
        mime=mime or "application/octet-stream",
        size=len(content),
        added_by=added_by,
    )
    db.add(material)
    db.commit()
    db.refresh(material)
    return material


def delete(db: Session, material: Material) -> None:
    file_path = material.file_path
    db.delete(material)
    db.commit()
    storage.delete_file(file_path)
