"""SQLAlchemy models for otelctx."""

from __future__ import annotations

from datetime import datetime

from sqlalchemy import DateTime, Float, ForeignKey, Integer, String, Text, func
from sqlalchemy.orm import Mapped, mapped_column, relationship

from common.db import Base


class Trace(Base):
    __tablename__ = "traces"

    id: Mapped[int] = mapped_column(primary_key=True)
    trace_id: Mapped[str] = mapped_column(String(128), unique=True, index=True)
    root_service_name: Mapped[str] = mapped_column(String(256), default="unknown", index=True)
    root_span_name: Mapped[str] = mapped_column(String(512), default="", index=True)
    status_code: Mapped[str] = mapped_column(String(64), default="UNSET", index=True)
    span_count: Mapped[int] = mapped_column(Integer, default=0)
    start_time: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    end_time: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    duration_ms: Mapped[float] = mapped_column(Float, default=0.0)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())

    spans: Mapped[list[Span]] = relationship(back_populates="trace", cascade="all, delete-orphan")


class Span(Base):
    __tablename__ = "spans"
    __mapper_args__ = {"confirm_deleted_rows": False}

    id: Mapped[int] = mapped_column(primary_key=True)
    trace_id: Mapped[int] = mapped_column(ForeignKey("traces.id", ondelete="CASCADE"), index=True)
    span_id: Mapped[str] = mapped_column(String(128), index=True)
    parent_span_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
    name: Mapped[str] = mapped_column(String(512), index=True)
    service_name: Mapped[str] = mapped_column(String(256), default="unknown", index=True)
    kind: Mapped[str] = mapped_column(String(64), default="INTERNAL")
    status_code: Mapped[str] = mapped_column(String(64), default="UNSET", index=True)
    start_time: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    end_time: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    duration_ms: Mapped[float] = mapped_column(Float, default=0.0)
    attributes_json: Mapped[str | None] = mapped_column(Text, nullable=True)

    trace: Mapped[Trace] = relationship(back_populates="spans")


class LogEntry(Base):
    __tablename__ = "logs"

    id: Mapped[int] = mapped_column(primary_key=True)
    timestamp: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, index=True)
    observed_time: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    service_name: Mapped[str] = mapped_column(String(256), default="unknown", index=True)
    severity_text: Mapped[str] = mapped_column(String(64), default="INFO", index=True)
    body: Mapped[str] = mapped_column(Text, default="")
    trace_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
    span_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
    attributes_json: Mapped[str | None] = mapped_column(Text, nullable=True)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())


class MetricPoint(Base):
    __tablename__ = "metric_points"

    id: Mapped[int] = mapped_column(primary_key=True)
    service_name: Mapped[str] = mapped_column(String(256), default="unknown", index=True)
    metric_name: Mapped[str] = mapped_column(String(512), index=True)
    metric_type: Mapped[str] = mapped_column(String(64), default="gauge", index=True)
    unit: Mapped[str | None] = mapped_column(String(64), nullable=True)
    temporality: Mapped[str | None] = mapped_column(String(64), nullable=True)
    start_time: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    time: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, index=True)
    value: Mapped[float] = mapped_column(Float, default=0.0)
    attributes_json: Mapped[str | None] = mapped_column(Text, nullable=True)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
