"""HeadMetric — running correction counters per concept (#114 observability).

Earned auto-apply fires graduated heads; to TUNE it we need to know how often a
head's auto-applied tag was wrong (the operator removed it = a MISFIRE) and how
often the operator had to add a tag a head exists for by hand (an UNDER-FIRE,
the head missed it). image_tag.source is lost when a row is deleted, so these
are captured as durable cumulative counters at correction time — they survive
head retrain/prune (keyed by tag, not by the head row). The daily snapshot reads
them into the time-series.
"""

from datetime import datetime

from sqlalchemy import DateTime, ForeignKey, Integer, func
from sqlalchemy.orm import Mapped, mapped_column

from .base import Base


class HeadMetric(Base):
    __tablename__ = "head_metric"

    tag_id: Mapped[int] = mapped_column(
        ForeignKey("tag.id", ondelete="CASCADE"), primary_key=True
    )
    # An auto-applied (source='head_auto') tag the operator later REMOVED.
    n_misfires: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    # A tag with a head that the operator added by HAND (the head missed it).
    n_underfires: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False, server_default=func.now()
    )
