# -*- coding: utf-8 -*-
"""SQLAlchemy ORM 模型（auth/RBAC 域）+ Pydantic 请求/响应模型。

- ORM 模型对应 SQLite 各表（users/roles/permissions/organizations/regions/
  sessions/audit_logs/agents）。
- Pydantic 模型与 PineAgents 主后端 ``src/pineagents/app/routers/auth.py``
  中的请求/响应模型一一对应，转发层透传时不会丢字段。
"""
from __future__ import annotations

from pydantic import BaseModel, Field
from sqlalchemy import (
    Boolean,
    Float,
    ForeignKey,
    Integer,
    PrimaryKeyConstraint,
    String,
    Text,
)
from sqlalchemy.orm import Mapped, mapped_column

from .db import Base


# ===========================================================================
# SQLAlchemy ORM 模型
# ===========================================================================

class User(Base):
    __tablename__ = "users"
    __table_args__ = {"sqlite_autoincrement": True}

    id: Mapped[str] = mapped_column(String, primary_key=True)
    username: Mapped[str] = mapped_column(String, unique=True, nullable=False)
    password_hash: Mapped[str] = mapped_column(String, nullable=False)
    password_salt: Mapped[str] = mapped_column(String, nullable=False)
    # 统一登录：微信 openid（登录即建 opc_member 身份）；phone 与 username（手机号）对齐
    wx_openid: Mapped[str] = mapped_column(String, default="", index=True)
    phone: Mapped[str] = mapped_column(String, default="")
    nickname: Mapped[str] = mapped_column(String, default="")
    account: Mapped[str] = mapped_column(String, default="")
    company: Mapped[str] = mapped_column(String, default="")
    room: Mapped[str] = mapped_column(String, default="")
    avatar: Mapped[str] = mapped_column(String, default="")
    company_avatar: Mapped[str] = mapped_column(String, default="")
    # RBAC
    role: Mapped[str] = mapped_column(String, default="opc_member")  # 业务角色
    sub_role: Mapped[str] = mapped_column(String, nullable=True)     # 政务级/运营方内部
    org_id: Mapped[str | None] = mapped_column(ForeignKey("organizations.id"), nullable=True)
    region_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
    status: Mapped[str] = mapped_column(String, default="active")    # active | disabled
    token_version: Mapped[int] = mapped_column(Integer, default=0)   # revoke-all 递增
    created_at: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


class Role(Base):
    __tablename__ = "roles"

    id: Mapped[str] = mapped_column(String, primary_key=True)   # 角色码
    name: Mapped[str] = mapped_column(String, nullable=False)    # 展示名
    scope_type: Mapped[str] = mapped_column(String, default="business")  # business|operator-internal|government-level
    description: Mapped[str] = mapped_column(String, default="")


class Permission(Base):
    __tablename__ = "permissions"

    id: Mapped[str] = mapped_column(String, primary_key=True)    # 权限码 menu:xx / action:xx
    name: Mapped[str] = mapped_column(String, nullable=False)
    category: Mapped[str] = mapped_column(String, default="action")  # menu | action
    module: Mapped[str] = mapped_column(String, default="")       # admin|government|...
    description: Mapped[str] = mapped_column(String, default="")


class RolePermission(Base):
    __tablename__ = "role_permissions"

    role_id: Mapped[str] = mapped_column(
        ForeignKey("roles.id", ondelete="CASCADE"), primary_key=True,
    )
    permission_id: Mapped[str] = mapped_column(
        ForeignKey("permissions.id", ondelete="CASCADE"), primary_key=True,
    )


class Organization(Base):
    __tablename__ = "organizations"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    name: Mapped[str] = mapped_column(String, nullable=False)
    type: Mapped[str] = mapped_column(String, default="enterprise")  # enterprise|carrier|provider
    region_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
    parent_id: Mapped[str | None] = mapped_column(ForeignKey("organizations.id"), nullable=True)
    status: Mapped[str] = mapped_column(String, default="active")
    created_at: Mapped[str] = mapped_column(String, default="")


class OrganizationMember(Base):
    """机构成员（机构主账号 + 机构内子账号）：一个账号可挂多个机构。"""

    __tablename__ = "organization_members"

    org_id: Mapped[str] = mapped_column(
        ForeignKey("organizations.id", ondelete="CASCADE"), primary_key=True,
    )
    user_id: Mapped[str] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"), primary_key=True,
    )
    role: Mapped[str] = mapped_column(String, default="member")  # admin/finance/publisher/service_executor/service_deliverer/clerk/...
    is_admin: Mapped[bool] = mapped_column(Boolean, default=False)  # 机构主账号/管理员
    status: Mapped[str] = mapped_column(String, default="active")
    joined_at: Mapped[str] = mapped_column(String, default="")


class Region(Base):
    __tablename__ = "regions"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    name: Mapped[str] = mapped_column(String, nullable=False)
    level: Mapped[str] = mapped_column(String, default="district")  # province|city|district
    parent_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
    created_at: Mapped[str] = mapped_column(String, default="")


class SessionToken(Base):
    __tablename__ = "sessions"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    jti: Mapped[str] = mapped_column(String, unique=True, nullable=False)
    token: Mapped[str] = mapped_column(String, default="")  # 完整 JWT（调试用）
    user_id: Mapped[str] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
    username: Mapped[str] = mapped_column(String, default="")
    created_at: Mapped[str] = mapped_column(String, default="")
    expires_at: Mapped[str] = mapped_column(String, default="")
    revoked: Mapped[bool] = mapped_column(Boolean, default=False)


class AuditLog(Base):
    __tablename__ = "audit_logs"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    user_id: Mapped[str | None] = mapped_column(ForeignKey("users.id"), nullable=True)
    action: Mapped[str] = mapped_column(String, default="")   # login|role.assign|data.view|...
    resource: Mapped[str] = mapped_column(String, default="")  # user|role|enterprise|region|...
    resource_id: Mapped[str] = mapped_column(String, default="")
    detail: Mapped[str] = mapped_column(Text, default="")
    ip: Mapped[str] = mapped_column(String, default="")
    created_at: Mapped[str] = mapped_column(String, default="")


class Agent(Base):
    __tablename__ = "agents"
    # id + user_id + port 复合主键：每个用户在每个端口持有独立的默认/QA 智能体（多端口彻底隔离）
    __table_args__ = (PrimaryKeyConstraint("id", "user_id", "port"),)

    id: Mapped[str] = mapped_column(String)
    user_id: Mapped[str] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
    )
    port: Mapped[str] = mapped_column(String, default="opc")  # opc/operator/government/... 端口隔离
    name: Mapped[str] = mapped_column(String, default="")
    description: Mapped[str] = mapped_column(Text, default="")
    language: Mapped[str] = mapped_column(String, default="zh")
    model_name: Mapped[str] = mapped_column(String, default="")
    deletable: Mapped[bool] = mapped_column(Boolean, default=True)
    use_fixed_soul: Mapped[bool] = mapped_column(Boolean, default=False)
    created_at: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


# ── 运营端业务模型（平台运营/任务/服务商/内容/配置）────────────────────────

class Task(Base):
    """平台任务（运营端可审核/下架；后续各端口接入）。"""

    __tablename__ = "tasks"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    title: Mapped[str] = mapped_column(String, default="")
    category: Mapped[str] = mapped_column(String, default="")   # 设计创意/技术开发/...
    sub_category: Mapped[str] = mapped_column(String, default="")
    description: Mapped[str] = mapped_column(Text, default="")
    mode: Mapped[str] = mapped_column(String, default="grab")   # grab/bid/designated/dispatch
    budget_min: Mapped[int] = mapped_column(Integer, default=0)
    budget_max: Mapped[int] = mapped_column(Integer, default=0)
    deadline: Mapped[str] = mapped_column(String, default="")
    status: Mapped[str] = mapped_column(String, default="draft")  # draft/pending/review/published/completed/cancelled
    publisher_org_id: Mapped[str | None] = mapped_column(ForeignKey("organizations.id"), nullable=True)
    publisher_name: Mapped[str] = mapped_column(String, default="")
    created_at: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


class ServiceProvider(Base):
    """服务商（运营端审核/评级/考核）。"""

    __tablename__ = "service_providers"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    name: Mapped[str] = mapped_column(String, default="")
    category: Mapped[str] = mapped_column(String, default="")  # 财税/工商/法务/知识产权/云服务...
    org_id: Mapped[str | None] = mapped_column(ForeignKey("organizations.id"), nullable=True)
    level: Mapped[str] = mapped_column(String, default="certified")  # certified/premium/gold/official
    rating: Mapped[float] = mapped_column(Float, default=5.0)
    order_count: Mapped[int] = mapped_column(Integer, default=0)
    status: Mapped[str] = mapped_column(String, default="pending")  # pending/active/blacklisted
    contact: Mapped[str] = mapped_column(String, default="")
    created_at: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


class ContentItem(Base):
    """平台内容（政策/课程/资讯/公告/活动）。"""

    __tablename__ = "content_items"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    type: Mapped[str] = mapped_column(String, default="news")  # policy/course/news/notice/activity
    title: Mapped[str] = mapped_column(String, default="")
    summary: Mapped[str] = mapped_column(String, default="")
    body: Mapped[str] = mapped_column(Text, default="")
    publisher_id: Mapped[str | None] = mapped_column(ForeignKey("users.id"), nullable=True)
    status: Mapped[str] = mapped_column(String, default="draft")  # draft/published/offline
    created_at: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


class SystemConfig(Base):
    """平台系统配置（键值）。"""

    __tablename__ = "system_configs"

    key: Mapped[str] = mapped_column(String, primary_key=True)
    value: Mapped[str] = mapped_column(String, default="")
    description: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


class PortalDashboard(Base):
    """端口工作台聚合数据（按端口存 JSON 载荷，全部由服务端提供）。"""

    __tablename__ = "portal_dashboards"

    port: Mapped[str] = mapped_column(String, primary_key=True)
    payload: Mapped[str] = mapped_column(Text, default="{}")
    updated_at: Mapped[str] = mapped_column(String, default="")


class PortalPage(Base):
    """端口子页面数据（按 端口+页面 存 JSON 载荷，全部由服务端提供）。"""

    __tablename__ = "portal_pages"

    port: Mapped[str] = mapped_column(String, primary_key=True)
    page: Mapped[str] = mapped_column(String, primary_key=True)
    payload: Mapped[str] = mapped_column(Text, default="{}")
    updated_at: Mapped[str] = mapped_column(String, default="")


# ── 投资人端（投融资 · 路演 · 培训）──────────────────────────────────────

class InvestorPreference(Base):
    """投资人投资方向偏好。"""

    __tablename__ = "investor_preferences"

    user_id: Mapped[str] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"), primary_key=True,
    )
    industries: Mapped[str] = mapped_column(String, default="[]")   # JSON list
    stage: Mapped[str] = mapped_column(String, default="")          # seed/angel/series_a/...
    amount_min: Mapped[int] = mapped_column(Integer, default=0)
    amount_max: Mapped[int] = mapped_column(Integer, default=0)
    region_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
    updated_at: Mapped[str] = mapped_column(String, default="")


class Roadshow(Base):
    """投融资路演活动（线上/线下/混合），支持按发布主体与范围审核。"""

    __tablename__ = "roadshows"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    publisher_id: Mapped[str] = mapped_column(String, default="")
    publisher_role: Mapped[str] = mapped_column(String, default="investor")  # investor/government/operator/carrier/enterprise
    title: Mapped[str] = mapped_column(String, default="")
    summary: Mapped[str] = mapped_column(String, default="")
    activity_type: Mapped[str] = mapped_column(String, default="online")  # online/offline/hybrid
    scope_type: Mapped[str] = mapped_column(String, default="all")  # all/region/org
    region_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
    start_at: Mapped[str] = mapped_column(String, default="")
    end_at: Mapped[str] = mapped_column(String, default="")
    register_deadline: Mapped[str] = mapped_column(String, default="")
    quota: Mapped[int] = mapped_column(Integer, default=0)
    venue: Mapped[str] = mapped_column(String, default="")          # 线下地点/直播间
    live_url: Mapped[str] = mapped_column(String, default="")
    status: Mapped[str] = mapped_column(String, default="draft")    # draft/submitted/reviewing/published/registering/ongoing/ended/archived/rejected/cancelled
    review_comment: Mapped[str] = mapped_column(String, default="")
    need_review: Mapped[bool] = mapped_column(Boolean, default=True)
    created_at: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


class RoadshowRegistration(Base):
    """路演活动报名（项目方/投资人）。"""

    __tablename__ = "roadshow_registrations"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    roadshow_id: Mapped[str] = mapped_column(
        ForeignKey("roadshows.id", ondelete="CASCADE"), nullable=False,
    )
    user_id: Mapped[str] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
    )
    role: Mapped[str] = mapped_column(String, default="investor")  # investor/project
    status: Mapped[str] = mapped_column(String, default="applying")  # applying/approved/attended/absent
    note: Mapped[str] = mapped_column(String, default="")
    created_at: Mapped[str] = mapped_column(String, default="")


class InvestmentIntent(Base):
    """投资意向/约谈/尽调。"""

    __tablename__ = "investment_intents"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    investor_id: Mapped[str] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
    )
    project_id: Mapped[str] = mapped_column(String, default="")
    project_name: Mapped[str] = mapped_column(String, default="")
    status: Mapped[str] = mapped_column(String, default="interested")  # interested/contacted/meeting/term_sheet/invested/declined
    message: Mapped[str] = mapped_column(String, default="")
    created_at: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


class Bid(Base):
    """任务竞标（企业端竞标模式发标）。"""

    __tablename__ = "bids"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    task_id: Mapped[str] = mapped_column(
        ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False,
    )
    opc_id: Mapped[str] = mapped_column(String, default="")
    opc_name: Mapped[str] = mapped_column(String, default="")
    quote: Mapped[int] = mapped_column(Integer, default=0)
    plan: Mapped[str] = mapped_column(String, default="")
    status: Mapped[str] = mapped_column(String, default="submitted")  # submitted/win/lost
    created_at: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


class SubsidyApplication(Base):
    """补贴申报（政务三级审批：区县→市→省→发放）。"""

    __tablename__ = "subsidy_applications"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    opc_id: Mapped[str] = mapped_column(String, default="")
    opc_name: Mapped[str] = mapped_column(String, default="")
    title: Mapped[str] = mapped_column(String, default="")
    amount: Mapped[int] = mapped_column(Integer, default=0)
    region_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
    status: Mapped[str] = mapped_column(String, default="applying")  # applying/district_review/city_review/province_review/approved/paid/rejected
    comment: Mapped[str] = mapped_column(String, default="")
    created_at: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


class ServiceReferral(Base):
    """载体-服务商引荐（三方绑定：载体引荐服务商→服务园区内 OPC）。"""

    __tablename__ = "service_referrals"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    carrier_id: Mapped[str] = mapped_column(String, default="")
    provider_id: Mapped[str] = mapped_column(String, default="")
    provider_name: Mapped[str] = mapped_column(String, default="")
    opc_id: Mapped[str] = mapped_column(String, default="")
    opc_name: Mapped[str] = mapped_column(String, default="")
    status: Mapped[str] = mapped_column(String, default="referred")  # referred/accepted/completed/declined
    created_at: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


class TrainingEnrollment(Base):
    """投融资培训报名/证书。"""

    __tablename__ = "training_enrollments"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    training_id: Mapped[str] = mapped_column(String, default="")
    training_name: Mapped[str] = mapped_column(String, default="")
    user_id: Mapped[str] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
    )
    status: Mapped[str] = mapped_column(String, default="applying")  # applying/enrolled/completed/certificate
    created_at: Mapped[str] = mapped_column(String, default="")


# ── 横切能力：结算/合同/争议/评价/通知 ────────────────────────────────────

class Escrow(Base):
    """任务资金托管/结算。"""

    __tablename__ = "escrows"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    task_id: Mapped[str] = mapped_column(
        ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False,
    )
    task_title: Mapped[str] = mapped_column(String, default="")
    amount: Mapped[int] = mapped_column(Integer, default=0)
    commission: Mapped[int] = mapped_column(Integer, default=0)  # 平台佣金
    status: Mapped[str] = mapped_column(String, default="deposited")  # deposited/frozen/released/refunded
    created_at: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


class Contract(Base):
    """任务电子合同。"""

    __tablename__ = "contracts"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    task_id: Mapped[str] = mapped_column(
        ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False,
    )
    task_title: Mapped[str] = mapped_column(String, default="")
    enterprise_id: Mapped[str] = mapped_column(String, default="")
    opc_id: Mapped[str] = mapped_column(String, default="")
    status: Mapped[str] = mapped_column(String, default="signed")  # draft/signed/terminated
    content: Mapped[str] = mapped_column(String, default="")
    created_at: Mapped[str] = mapped_column(String, default="")


class Dispute(Base):
    """任务争议。"""

    __tablename__ = "disputes"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    task_id: Mapped[str] = mapped_column(
        ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False,
    )
    task_title: Mapped[str] = mapped_column(String, default="")
    initiator: Mapped[str] = mapped_column(String, default="")
    reason: Mapped[str] = mapped_column(String, default="")
    status: Mapped[str] = mapped_column(String, default="opened")  # opened/mediating/resolved/closed
    resolution: Mapped[str] = mapped_column(String, default="")
    created_at: Mapped[str] = mapped_column(String, default="")


class Rating(Base):
    """任务互评。"""

    __tablename__ = "ratings"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    task_id: Mapped[str] = mapped_column(
        ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False,
    )
    from_id: Mapped[str] = mapped_column(String, default="")
    to_id: Mapped[str] = mapped_column(String, default="")
    score: Mapped[int] = mapped_column(Integer, default=5)  # 1..5
    comment: Mapped[str] = mapped_column(String, default="")
    created_at: Mapped[str] = mapped_column(String, default="")


class Notification(Base):
    """站内通知。"""

    __tablename__ = "notifications"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    user_id: Mapped[str] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
    )
    type: Mapped[str] = mapped_column(String, default="system")  # task/policy/order/subsidy/system
    title: Mapped[str] = mapped_column(String, default="")
    content: Mapped[str] = mapped_column(String, default="")
    read: Mapped[bool] = mapped_column(Boolean, default=False)
    created_at: Mapped[str] = mapped_column(String, default="")


# ── OPC 超级个体业务模型（工作台/我的任务/财务/消息）────────────────────

class OpcProfile(Base):
    """OPC 超级个体档案（信用评分等）。"""

    __tablename__ = "opc_profiles"

    user_id: Mapped[str] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"), primary_key=True,
    )
    credit_score: Mapped[int] = mapped_column(Integer, default=80)
    created_at: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


class FinanceRecord(Base):
    """OPC 财务流水（收入/支出）。"""

    __tablename__ = "finance_records"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    user_id: Mapped[str] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
    )
    category: Mapped[str] = mapped_column(String, default="income")  # income | expense
    amount: Mapped[int] = mapped_column(Integer, default=0)
    date: Mapped[str] = mapped_column(String, default="")          # YYYY-MM-DD
    note: Mapped[str] = mapped_column(String, default="")
    created_at: Mapped[str] = mapped_column(String, default="")


class Message(Base):
    """OPC 站内消息。"""

    __tablename__ = "messages"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    user_id: Mapped[str] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
    )
    msg_type: Mapped[str] = mapped_column(String, default="system")  # task/policy/service/agent/system
    title: Mapped[str] = mapped_column(String, default="")
    content: Mapped[str] = mapped_column(String, default="")
    read: Mapped[bool] = mapped_column(Boolean, default=False)
    created_at: Mapped[str] = mapped_column(String, default="")


class OpcTask(Base):
    """OPC 个人任务看板（「我的任务」：进行中/已完成/紧急）。"""

    __tablename__ = "opc_tasks"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    user_id: Mapped[str] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
    )
    title: Mapped[str] = mapped_column(String, default="")
    status: Mapped[str] = mapped_column(String, default="in_progress")  # in_progress/completed/urgent
    budget: Mapped[int] = mapped_column(Integer, default=0)
    deadline: Mapped[str] = mapped_column(String, default="")
    progress: Mapped[int] = mapped_column(Integer, default=0)
    created_at: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


class UserIdentity(Base):
    """账号↔端口绑定身份：一个账号可绑定多个端口/身份。

    身份即权限来源：``port`` 为业务端口（operator/government/provider/
    enterprise/carrier/opc），``role``=端口角色码（默认等于 port，供
    require_roles 匹配），``sub_role`` 为端口内细分角色（如 op_super_admin、
    gov_province、企业/园区/服务商的 admin/operator、OPC 的 certified/
    independent 等）。一个账号对应多行，登录后按所选身份签发令牌。
    """

    __tablename__ = "user_identities"

    id: Mapped[str] = mapped_column(String, primary_key=True)
    user_id: Mapped[str] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
    )
    port: Mapped[str] = mapped_column(String, default="opc")  # operator/government/provider/enterprise/carrier/opc
    role: Mapped[str] = mapped_column(String, default="opc_member")  # RBAC 角色码
    sub_role: Mapped[str | None] = mapped_column(String, nullable=True)  # 端口内细分角色
    name: Mapped[str] = mapped_column(String, default="")   # 身份展示名
    org_id: Mapped[str | None] = mapped_column(ForeignKey("organizations.id"), nullable=True)
    region_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
    status: Mapped[str] = mapped_column(String, default="active")  # active | disabled
    created_at: Mapped[str] = mapped_column(String, default="")
    updated_at: Mapped[str] = mapped_column(String, default="")


# ===========================================================================
# 培训业务子应用（原 app/training 独立 opc.db → 并入唯一总库）
# ===========================================================================

class TrainingAccount(Base):
    """培训站账号（原 accounts，含手机/微信登录）。"""
    __tablename__ = "training_accounts"
    id: Mapped[str] = mapped_column(String, primary_key=True)
    username: Mapped[str] = mapped_column(String, unique=True, nullable=False)
    wxid: Mapped[str] = mapped_column(String, default="")
    phone: Mapped[str] = mapped_column(String, default="")
    contact: Mapped[str] = mapped_column(String, default="")
    name: Mapped[str] = mapped_column(String, default="")
    avatar: Mapped[str] = mapped_column(String, default="")
    password: Mapped[str] = mapped_column(String, default="")
    phone_bound: Mapped[int] = mapped_column(Integer, default=0)
    identities: Mapped[str] = mapped_column(Text, default="[]")
    status_label: Mapped[str] = mapped_column(String, default="")
    topics: Mapped[str] = mapped_column(Text, default="")
    source: Mapped[str] = mapped_column(String, default="")
    created_at: Mapped[str] = mapped_column(String, default="")


class Event(Base):
    __tablename__ = "training_events"
    id: Mapped[str] = mapped_column(String, primary_key=True)
    type: Mapped[str] = mapped_column(String, default="")
    mode: Mapped[str] = mapped_column(String, default="offline")
    title: Mapped[str] = mapped_column(String, default="")
    subtitle: Mapped[str] = mapped_column(String, default="")
    desc: Mapped[str] = mapped_column(Text, default="")
    location: Mapped[str] = mapped_column(String, default="")
    host: Mapped[str] = mapped_column(String, default="")
    image: Mapped[str] = mapped_column(String, default="")
    link: Mapped[str] = mapped_column(String, default="")
    start_at: Mapped[str] = mapped_column(String, default="")
    end_at: Mapped[str] = mapped_column(String, default="")
    checkin_at: Mapped[str] = mapped_column(String, default="")
    duration_min: Mapped[int] = mapped_column(Integer, default=90)
    capacity: Mapped[int] = mapped_column(Integer, default=0)
    show_capacity: Mapped[int] = mapped_column(Integer, default=0)
    audit_mode: Mapped[str] = mapped_column(String, default="auto")
    status: Mapped[str] = mapped_column(String, default="open")


class Booking(Base):
    __tablename__ = "training_bookings"
    id: Mapped[str] = mapped_column(String, primary_key=True)
    created_at: Mapped[str] = mapped_column(String, default="")
    status: Mapped[str] = mapped_column(String, default="pending")
    audit_status: Mapped[str] = mapped_column(String, default="pending")
    username: Mapped[str] = mapped_column(String, default="")
    name: Mapped[str] = mapped_column(String, default="")
    contact: Mapped[str] = mapped_column(String, default="")
    status_label: Mapped[str] = mapped_column(String, default="")
    want: Mapped[str] = mapped_column(Text, default="")
    event_id: Mapped[str] = mapped_column(String, default="")
    event_title: Mapped[str] = mapped_column(String, default="")
    event_start: Mapped[str] = mapped_column(String, default="")
    topics: Mapped[str] = mapped_column(Text, default="")
    question: Mapped[str] = mapped_column(Text, default="")
    source: Mapped[str] = mapped_column(String, default="")
    checkin_at: Mapped[str] = mapped_column(String, default="")


class Test(Base):
    __tablename__ = "training_tests"
    id: Mapped[str] = mapped_column(String, primary_key=True)
    created_at: Mapped[str] = mapped_column(String, default="")
    username: Mapped[str] = mapped_column(String, default="")
    type_code: Mapped[str] = mapped_column(String, default="")
    persona: Mapped[str] = mapped_column(String, default="")
    adapt_index: Mapped[int] = mapped_column(Integer, default=0)
    adapt_level: Mapped[str] = mapped_column(String, default="")
    tracks: Mapped[str] = mapped_column(Text, default="")
    version: Mapped[str] = mapped_column(String, default="")


class Course(Base):
    __tablename__ = "training_courses"
    id: Mapped[str] = mapped_column(String, primary_key=True)
    category: Mapped[str] = mapped_column(String, default="")
    level: Mapped[str] = mapped_column(String, default="")
    title: Mapped[str] = mapped_column(String, default="")
    subtitle: Mapped[str] = mapped_column(String, default="")
    desc: Mapped[str] = mapped_column(Text, default="")
    price: Mapped[float] = mapped_column(Float, default=0.0)
    status: Mapped[str] = mapped_column(String, default="draft")
    start_at: Mapped[str] = mapped_column(String, default="")
    end_at: Mapped[str] = mapped_column(String, default="")
    venue: Mapped[str] = mapped_column(String, default="")
    quota: Mapped[int] = mapped_column(Integer, default=0)
    image: Mapped[str] = mapped_column(String, default="")
    host: Mapped[str] = mapped_column(String, default="")
    created_at: Mapped[str] = mapped_column(String, default="")


class PolicyLog(Base):
    __tablename__ = "training_policy_logs"
    id: Mapped[str] = mapped_column(String, primary_key=True)
    created_at: Mapped[str] = mapped_column(String, default="")
    username: Mapped[str] = mapped_column(String, default="")
    answers: Mapped[str] = mapped_column(Text, default="")
    policies_count: Mapped[int] = mapped_column(Integer, default=0)
    subsidies_count: Mapped[int] = mapped_column(Integer, default=0)
    loans_count: Mapped[int] = mapped_column(Integer, default=0)
    summary: Mapped[str] = mapped_column(Text, default="")


class PlanLog(Base):
    __tablename__ = "training_plan_logs"
    id: Mapped[str] = mapped_column(String, primary_key=True)
    created_at: Mapped[str] = mapped_column(String, default="")
    username: Mapped[str] = mapped_column(String, default="")
    region: Mapped[str] = mapped_column(String, default="")
    status: Mapped[str] = mapped_column(String, default="")
    need_park: Mapped[int] = mapped_column(Integer, default=0)
    has_staff: Mapped[int] = mapped_column(Integer, default=0)
    steps_count: Mapped[int] = mapped_column(Integer, default=0)


class SurveyLog(Base):
    __tablename__ = "training_survey_logs"
    id: Mapped[str] = mapped_column(String, primary_key=True)
    created_at: Mapped[str] = mapped_column(String, default="")
    username: Mapped[str] = mapped_column(String, default="")
    source: Mapped[str] = mapped_column(String, default="")
    answers: Mapped[str] = mapped_column(Text, default="")


# ===========================================================================
# 园区子应用（原 app/park 独立 park.db → 并入唯一总库）
# ===========================================================================

class ParkTenant(Base):
    __tablename__ = "park_tenants"
    id: Mapped[str] = mapped_column(String, primary_key=True)
    name: Mapped[str] = mapped_column(String, default="")
    intro_json: Mapped[str] = mapped_column(Text, default="[]")
    username: Mapped[str] = mapped_column(String, default="")
    salt: Mapped[str] = mapped_column(String, default="")
    password_hash: Mapped[str] = mapped_column(String, default="")
    admin_username: Mapped[str] = mapped_column(String, default="")
    status: Mapped[str] = mapped_column(String, default="active")
    data_json: Mapped[str] = mapped_column(Text, default="{}")
    agent_json: Mapped[str] = mapped_column(Text, default="{}")
    created_at: Mapped[str] = mapped_column(String, default="")


class ParkCompany(Base):
    __tablename__ = "park_companies"
    id: Mapped[str] = mapped_column(String, primary_key=True)
    tenant_id: Mapped[str] = mapped_column(ForeignKey("park_tenants.id", ondelete="CASCADE"), nullable=False, index=True)
    name: Mapped[str] = mapped_column(String, default="")
    zone: Mapped[str] = mapped_column(String, default="")
    room: Mapped[str] = mapped_column(String, default="")
    industry: Mapped[str] = mapped_column(String, default="")
    bio: Mapped[str] = mapped_column(Text, default="")
    founder: Mapped[str] = mapped_column(String, default="")
    status: Mapped[str] = mapped_column(String, default="applying")
    employees: Mapped[int | None] = mapped_column(Integer, nullable=True)
    created_at: Mapped[str] = mapped_column(String, default="")


class ParkKbDoc(Base):
    __tablename__ = "park_kb_docs"
    id: Mapped[str] = mapped_column(String, primary_key=True)
    tenant_id: Mapped[str] = mapped_column(ForeignKey("park_tenants.id", ondelete="CASCADE"), nullable=False, index=True)
    grp: Mapped[str] = mapped_column(String, default="general")
    title: Mapped[str] = mapped_column(String, default="")
    content_md: Mapped[str] = mapped_column(Text, default="")
    created_at: Mapped[str] = mapped_column(String, default="")


class ParkScreen(Base):
    __tablename__ = "park_screens"
    id: Mapped[str] = mapped_column(String, primary_key=True)
    tenant_id: Mapped[str] = mapped_column(ForeignKey("park_tenants.id", ondelete="CASCADE"), nullable=False, index=True)
    device_id: Mapped[str] = mapped_column(String, default="")
    name: Mapped[str] = mapped_column(String, default="")
    role: Mapped[str] = mapped_column(String, default="main")
    location: Mapped[str] = mapped_column(String, default="")
    created_at: Mapped[str] = mapped_column(String, default="")
