"""用户表。

登录方式有两种,但都映射到同一行 user:
  - 极光一键登录 → phone 唯一索引
  - 短信验证码登录(mock 阶段)  → 也是 phone 唯一索引
注册即登录:phone 不存在则 insert,存在则更新 last_login_at。

后续如果加微信/Apple 登录,新增 oauth_account 表,这张表不动。
"""
from __future__ import annotations

from datetime import datetime, timezone

from sqlalchemy import Boolean, DateTime, Integer, String, false, func
from sqlalchemy.orm import Mapped, mapped_column

from app.db.base import Base


def _utcnow() -> datetime:
    return datetime.now(timezone.utc)


class User(Base):
    __tablename__ = "user"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    phone: Mapped[str] = mapped_column(String(20), unique=True, index=True, nullable=False)

    # 对外展示的账号 ID:11 位纯数字、首位非 1(与手机号天然区分——手机号都以 1 开头)、全局唯一、
    # 创建时随机生成、不可变、不参与登录(登录仍走 phone)。生成见 repositories/user._gen_username。
    username: Mapped[str] = mapped_column(String(11), unique=True, index=True, nullable=False)

    # 注册渠道:jverify / sms。后续加 wechat / apple 时扩
    register_channel: Mapped[str] = mapped_column(String(20), nullable=False, default="jverify")

    nickname: Mapped[str | None] = mapped_column(String(64), nullable=True)
    avatar_url: Mapped[str | None] = mapped_column(String(512), nullable=True)

    # 邀请码:每个用户一个稳定短码(懒生成,见 repositories/invite.ensure_code),
    # 分享链接 / 二维码里带它。unique 允许多个 NULL(未生成的用户)。
    invite_code: Mapped[str | None] = mapped_column(
        String(16), unique=True, index=True, nullable=True
    )

    # 微信开放平台 openid(微信登录绑定后存,提现转账到零钱用)。同一 appid 下唯一;
    # unique 索引保证一个微信只能绑一个账号(nullable,允许多个 NULL=未绑定)。
    wechat_openid: Mapped[str | None] = mapped_column(
        String(64), unique=True, index=True, nullable=True
    )
    # 微信昵称/头像(绑定时从 sns/userinfo 拉,展示在提现绑定卡)。与上面通用 nickname/avatar_url 分开,不互相覆盖。
    wechat_nickname: Mapped[str | None] = mapped_column(String(64), nullable=True)
    wechat_avatar_url: Mapped[str | None] = mapped_column(String(512), nullable=True)

    # 账号状态:active / disabled / deleted
    status: Mapped[str] = mapped_column(String(20), nullable=False, default="active")

    # 调试链接权限:开了的用户在比价完成弹窗 + 比价记录页能看到「复制调试链接」按钮
    # (复制 price.shaguabijia.com 的 trace 链接发给开发排障)。运营后台按用户配置;
    # /me 与登录响应里带出给前端做条件渲染。默认 false。
    debug_trace_enabled: Mapped[bool] = mapped_column(
        Boolean, nullable=False, default=False, server_default=false()
    )

    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), server_default=func.now(), nullable=False
    )
    last_login_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), default=_utcnow, nullable=False
    )

    def __repr__(self) -> str:  # pragma: no cover
        return f"<User id={self.id} phone={self.phone}>"
