from __future__ import annotations

import uuid
from datetime import datetime

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

from app.db.base_class import Base


class Tenant(Base):
    """可信租户注册表；业务代码不得用任意字符串替代这里的记录。"""

    __tablename__ = "tenants"
    __table_args__ = (
        CheckConstraint(
            "status IN ('active', 'suspended', 'disabled')",
            name="ck_tenants_status",
        ),
        CheckConstraint(
            "length(trim(tenant_id)) > 0 AND length(trim(tenant_code)) > 0 "
            "AND length(trim(name)) > 0",
            name="ck_tenants_identity",
        ),
        Index("ix_tenants_status", "status"),
    )

    tenant_id: Mapped[str] = mapped_column(String(64), primary_key=True)
    tenant_code: Mapped[str] = mapped_column(String(64), unique=True, nullable=False)
    name: Mapped[str] = mapped_column(String(160), nullable=False)
    status: Mapped[str] = mapped_column(String(20), nullable=False, default="active")
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        nullable=False,
        server_default=func.now(),
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        nullable=False,
        server_default=func.now(),
        onupdate=func.now(),
    )

    memberships = relationship(
        "TenantMembership",
        back_populates="tenant",
        cascade="all, delete-orphan",
        overlaps="employee,tenant_memberships",
    )


class TenantMembership(Base):
    """员工在租户中的可认证成员资格。"""

    __tablename__ = "tenant_memberships"
    __table_args__ = (
        UniqueConstraint(
            "tenant_id",
            "employee_id",
            name="uq_tenant_memberships_tenant_employee",
        ),
        ForeignKeyConstraint(
            ["tenant_id", "employee_id"],
            ["employees.tenant_id", "employees.id"],
            name="fk_tenant_memberships_tenant_employee",
            ondelete="CASCADE",
        ),
        CheckConstraint(
            "status IN ('active', 'inactive')",
            name="ck_tenant_memberships_status",
        ),
        Index(
            "ix_tenant_memberships_employee_active",
            "employee_id",
            "status",
        ),
        Index(
            "ix_tenant_memberships_tenant_active",
            "tenant_id",
            "status",
        ),
    )

    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,
    )
    employee_id: Mapped[str] = mapped_column(String(36), nullable=False)
    status: Mapped[str] = mapped_column(String(20), nullable=False, default="active")
    is_primary: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        nullable=False,
        server_default=func.now(),
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        nullable=False,
        server_default=func.now(),
        onupdate=func.now(),
    )

    tenant = relationship(
        "Tenant",
        back_populates="memberships",
        overlaps="employee,tenant_memberships",
    )
    employee = relationship(
        "Employee",
        back_populates="tenant_memberships",
        overlaps="memberships,tenant",
    )
