from __future__ import annotations

import uuid
from datetime import datetime
from typing import Any

from sqlalchemy import (
    Boolean,
    DateTime,
    ForeignKey,
    ForeignKeyConstraint,
    Index,
    String,
    Text,
    UniqueConstraint,
    func,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.types import JSON

from app.db.base_class import Base


class HermesTaskConfig(Base):
    __tablename__ = "hermes_task_configs"
    __table_args__ = (
        UniqueConstraint("tenant_id", "id", name="uq_hermes_task_configs_tenant_id"),
        Index("ix_hermes_task_configs_tenant_enabled", "tenant_id", "is_enabled"),
    )

    id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    tenant_id: Mapped[str] = mapped_column(
        ForeignKey("tenants.tenant_id", ondelete="RESTRICT"),
        nullable=False,
        server_default="default",
    )
    task_type: Mapped[str] = mapped_column(String(50), index=True)
    cron_expression: Mapped[str] = mapped_column(String(100))
    is_enabled: Mapped[bool] = mapped_column(Boolean, default=True)
    payload_template: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict)

    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
    )

    execution_logs = relationship(
        "HermesTaskExecutionLog",
        back_populates="config",
        cascade="all, delete-orphan",
        order_by="desc(HermesTaskExecutionLog.started_at)",
    )


class HermesTaskExecutionLog(Base):
    __tablename__ = "hermes_task_execution_logs"
    __table_args__ = (
        UniqueConstraint(
            "tenant_id",
            "id",
            name="uq_hermes_task_execution_logs_tenant_id",
        ),
        ForeignKeyConstraint(
            ["tenant_id", "config_id"],
            ["hermes_task_configs.tenant_id", "hermes_task_configs.id"],
            name="fk_hermes_task_logs_tenant_config",
            ondelete="CASCADE",
        ),
        Index("ix_hermes_task_logs_tenant_started", "tenant_id", "started_at"),
    )

    id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    tenant_id: Mapped[str] = mapped_column(
        ForeignKey("tenants.tenant_id", ondelete="RESTRICT"),
        nullable=False,
        server_default="default",
    )
    config_id: Mapped[str] = mapped_column(String(36), index=True)
    status: Mapped[str] = mapped_column(String(30), index=True)
    result_summary: Mapped[str | None] = mapped_column(String(255), nullable=True)
    error_trace: Mapped[str | None] = mapped_column(Text(), nullable=True)

    started_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)

    config = relationship("HermesTaskConfig", back_populates="execution_logs")
