from __future__ import annotations

import uuid
from datetime import datetime
from typing import Any

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

from app.db.base_class import Base


class EmployeeBehaviorProfileSnapshot(Base):
    __tablename__ = "employee_behavior_profile_snapshots"
    __table_args__ = (
        UniqueConstraint(
            "tenant_id",
            "id",
            name="uq_employee_behavior_profiles_tenant_id",
        ),
        ForeignKeyConstraint(
            ["tenant_id", "subject_id"],
            ["employees.tenant_id", "employees.id"],
            name="fk_employee_behavior_profiles_tenant_employee",
            ondelete="CASCADE",
        ),
        Index(
            "ix_employee_behavior_profile_latest",
            "tenant_id",
            "subject_id",
            "profile_type",
            "window_days",
            "expense_type_scope",
            "calculated_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",
        index=True,
    )
    subject_type: Mapped[str] = mapped_column(String(30), default="employee", index=True)
    subject_id: Mapped[str] = mapped_column(String(100), index=True)
    subject_name: Mapped[str] = mapped_column(String(100), index=True)
    department_id: Mapped[str | None] = mapped_column(String(100), nullable=True, index=True)
    department_name: Mapped[str | None] = mapped_column(String(100), nullable=True, index=True)
    position: Mapped[str | None] = mapped_column(String(100), nullable=True)
    grade: Mapped[str | None] = mapped_column(String(30), nullable=True, index=True)

    profile_type: Mapped[str] = mapped_column(String(50), index=True)
    window_days: Mapped[int] = mapped_column(Integer, index=True)
    expense_type_scope: Mapped[str] = mapped_column(String(50), default="overall", index=True)
    peer_group_key: Mapped[str] = mapped_column(String(255), default="")
    peer_group_fallback_level: Mapped[int] = mapped_column(Integer, default=0)

    profile_score: Mapped[int] = mapped_column(Integer, default=0)
    profile_level: Mapped[str] = mapped_column(String(30), default="normal", index=True)
    metrics_json: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict)
    basis_codes_json: Mapped[list[Any]] = mapped_column(JSON, default=list)
    source_task_type: Mapped[str] = mapped_column(
        String(80), default="employee_behavior_profile_scan"
    )
    source_task_log_id: Mapped[str | None] = mapped_column(
        ForeignKey("hermes_task_execution_logs.id"),
        nullable=True,
        index=True,
    )
    algorithm_version: Mapped[str] = mapped_column(
        String(80), default="employee_behavior_profile.v1"
    )
    calculated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), server_default=func.now(), index=True
    )
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())

    source_task_log = relationship("HermesTaskExecutionLog")
