from __future__ import annotations
from sqlalchemy import (
    Column,
    String,
    Integer,
    Boolean,
    DateTime,
    JSON,
    ForeignKey,
    Index,
    text,
)
from datetime import datetime
from typing import Optional, Dict, Any
from ..db import Base


# Pools
class RoutingPool(Base):  # table: routing_pools
    __tablename__ = "routing_pools"
    id: str = Column(String, primary_key=True)  # pool_id
    tenant_id: str = Column(String, index=True, nullable=False)
    name: str = Column(String, nullable=False)
    algo: str = Column(String, default="fair_rr")
    daily_cap: Optional[int] = Column(Integer, nullable=True)
    reset_at: Optional[datetime] = Column(DateTime, nullable=True)
    created_at: datetime = Column(DateTime, default=datetime.utcnow)


class RoutingPoolMember(Base):  # table: routing_pool_members
    __tablename__ = "routing_pool_members"
    id: str = Column(String, primary_key=True)  # pool_id:user_id
    pool_id: str = Column(String, ForeignKey("routing_pools.id"), index=True)
    tenant_id: str = Column(String, index=True, nullable=False)
    user_id: str = Column(String, nullable=False)
    weight: int = Column(Integer, default=1)

    __table_args__ = (
        Index("ix_pool_user_unique", "tenant_id", "pool_id", "user_id", unique=True),
    )


class RoutingPoolState(Base):  # table: routing_pool_state
    __tablename__ = "routing_pool_state"
    id: str = Column(String, primary_key=True)  # pool_id
    tenant_id: str = Column(String, index=True, nullable=False)
    assigned_today: Dict[str, Any] = Column(JSON, default=dict)  # {user_id: count}
    last_assigned_user_id: Optional[str] = Column(String, nullable=True)
    reset_at: datetime = Column(DateTime, default=datetime.utcnow)
    updated_at: datetime = Column(DateTime, default=datetime.utcnow)
    version: int = Column(
        Integer, nullable=False, server_default="0"
    )  # For optimistic locking
    tenant_timezone: str = Column(String(50), default="UTC")

    __mapper_args__ = {
        "version_id_col": version
    }  # Enable SQLAlchemy optimistic locking


# Rules
class RoutingRule(Base):  # table: routing_rules
    __tablename__ = "routing_rules"
    id: str = Column(String, primary_key=True)  # rule_id
    tenant_id: str = Column(String, index=True, nullable=False)
    name: str = Column(String, nullable=False)
    priority: int = Column(Integer, index=True)
    active: bool = Column(Boolean, default=True)
    condition: Dict[str, Any] = Column(JSON, default=dict)
    action: Dict[str, Any] = Column(JSON, default=dict)
    created_at: datetime = Column(DateTime, default=datetime.utcnow)
    updated_at: datetime = Column(DateTime, default=datetime.utcnow)

    __table_args__ = (Index("ix_rules_priority", "tenant_id", "priority"),)


# Decisions (audit trail)
class RoutingDecision(Base):  # table: routing_decisions
    __tablename__ = "routing_decisions"
    id: str = Column(
        String, primary_key=True, server_default=text("lower(hex(randomblob(16)))")
    )
    tenant_id: str = Column(String, index=True, nullable=False)
    lead_id: str = Column(String, index=True)
    decision: str = Column(
        String, nullable=False
    )  # assign_owner | pool_assign | no_match
    owner_id: Optional[str] = Column(String, nullable=True)
    pool_id: Optional[str] = Column(String, nullable=True)
    rule_id: Optional[str] = Column(String, nullable=True)
    reason: str = Column(String, nullable=False)
    context: Dict[str, Any] = Column(JSON, default=dict)
    created_at: datetime = Column(DateTime, default=datetime.utcnow)
    idempotency_key: Optional[str] = Column(
        String(64), nullable=True, index=True
    )  # For idempotent operations
    applied_at: Optional[datetime] = Column(
        DateTime, nullable=True
    )  # NULL = preview only, non-NULL = committed
    rolled_back_at: Optional[datetime] = Column(
        DateTime, nullable=True
    )  # Timestamp if decision was rolled back

    __table_args__ = (
        Index(
            "ix_routing_decisions_idempotency",
            "tenant_id",
            "idempotency_key",
            unique=True,
        ),
        Index("ix_routing_decisions_tenant_created", "tenant_id", "created_at"),
        Index(
            "ix_routing_decisions_active", "tenant_id", "applied_at", "rolled_back_at"
        ),
    )
