"""Read-only SQLModel mirrors of Better Auth-managed tables.

These tables (`organization`, `member`, `team`, `team_member`, `session`,
`invitation`, `account`, `verification`, `jwks`) are owned by Better Auth.
Their schema is created and evolved by `pnpm dlx auth migrate`, NOT by
Alembic. This module exposes minimal Python bindings so the backend can:
- read membership/role data for tenant resolution
- enforce access rules (sole-owner deletion check, etc.)
- emit join queries that include team / org context

DO NOT add columns or evolve the schema here. Treat these classes as
read-only views of BA's tables.

Naming: BA uses camelCase column names (`activeOrganizationId`, `userId`,
`emailVerified`, etc.). The Python attributes use snake_case; the mapping
is done by passing `sa_column=Column("camelCase", ...)`.
"""

from datetime import datetime
from typing import Any, cast

from sqlalchemy import Column
from sqlalchemy.dialects.postgresql import JSONB, TIMESTAMP
from sqlmodel import Field, SQLModel

_BA_MANAGED = {"info": {"managed_by": "better-auth"}}


def _ts_column(name: str, *, nullable: bool = False) -> Any:
    return Column(name, TIMESTAMP(timezone=True), nullable=nullable)


class Organization(SQLModel, table=True):
    __tablename__ = cast(Any, "organization")
    __table_args__ = _BA_MANAGED

    id: str = Field(primary_key=True)
    name: str = Field(nullable=False)
    slug: str = Field(unique=True, nullable=False)
    logo: str | None = Field(default=None)
    # JSON metadata blob — subscription plan lives here under .plan
    metadata_: dict[str, Any] | None = Field(
        default=None,
        sa_column=Column("metadata", JSONB),
    )
    created_at: datetime = Field(sa_column=_ts_column("createdAt"))


class Member(SQLModel, table=True):
    __tablename__ = cast(Any, "member")
    __table_args__ = _BA_MANAGED

    id: str = Field(primary_key=True)
    user_id: str = Field(
        foreign_key="user.id",
        sa_column_kwargs={"name": "userId"},
        nullable=False,
    )
    organization_id: str = Field(
        foreign_key="organization.id",
        sa_column_kwargs={"name": "organizationId"},
        nullable=False,
    )
    role: str = Field(nullable=False)
    created_at: datetime = Field(sa_column=_ts_column("createdAt"))


class Team(SQLModel, table=True):
    __tablename__ = cast(Any, "team")
    __table_args__ = _BA_MANAGED

    id: str = Field(primary_key=True)
    name: str = Field(nullable=False)
    organization_id: str = Field(
        foreign_key="organization.id",
        sa_column_kwargs={"name": "organizationId"},
        nullable=False,
    )
    created_at: datetime = Field(sa_column=_ts_column("createdAt"))
    updated_at: datetime | None = Field(
        default=None, sa_column=_ts_column("updatedAt", nullable=True)
    )


class TeamMember(SQLModel, table=True):
    __tablename__ = cast(Any, "teamMember")
    __table_args__ = _BA_MANAGED

    id: str = Field(primary_key=True)
    team_id: str = Field(
        foreign_key="team.id",
        sa_column_kwargs={"name": "teamId"},
        nullable=False,
    )
    user_id: str = Field(
        foreign_key="user.id",
        sa_column_kwargs={"name": "userId"},
        nullable=False,
    )
    created_at: datetime | None = Field(
        default=None, sa_column=_ts_column("createdAt", nullable=True)
    )


class Session(SQLModel, table=True):
    __tablename__ = cast(Any, "session")
    __table_args__ = _BA_MANAGED

    id: str = Field(primary_key=True)
    token: str = Field(unique=True, nullable=False)
    user_id: str = Field(
        foreign_key="user.id",
        sa_column_kwargs={"name": "userId"},
        nullable=False,
    )
    expires_at: datetime = Field(sa_column=_ts_column("expiresAt"))
    ip_address: str | None = Field(
        default=None,
        sa_column_kwargs={"name": "ipAddress"},
    )
    user_agent: str | None = Field(
        default=None,
        sa_column_kwargs={"name": "userAgent"},
    )
    active_organization_id: str | None = Field(
        default=None,
        sa_column_kwargs={"name": "activeOrganizationId"},
    )
    active_team_id: str | None = Field(
        default=None,
        sa_column_kwargs={"name": "activeTeamId"},
    )
    created_at: datetime = Field(sa_column=_ts_column("createdAt"))
    updated_at: datetime = Field(sa_column=_ts_column("updatedAt"))


class Invitation(SQLModel, table=True):
    """BA-managed organization invitation (in-org join). NOT to be confused
    with our custom `invitation_token` table that gates platform sign-up."""

    __tablename__ = cast(Any, "invitation")
    __table_args__ = _BA_MANAGED

    id: str = Field(primary_key=True)
    email: str = Field(nullable=False)
    inviter_id: str = Field(
        foreign_key="user.id",
        sa_column_kwargs={"name": "inviterId"},
        nullable=False,
    )
    organization_id: str = Field(
        foreign_key="organization.id",
        sa_column_kwargs={"name": "organizationId"},
        nullable=False,
    )
    role: str | None = Field(default=None)
    team_id: str | None = Field(
        default=None,
        foreign_key="team.id",
        sa_column_kwargs={"name": "teamId"},
    )
    status: str = Field(nullable=False)
    created_at: datetime = Field(sa_column=_ts_column("createdAt"))
    expires_at: datetime = Field(sa_column=_ts_column("expiresAt"))
