# -*- coding: utf-8 -*-
"""基础设施层 · 异步 SQLAlchemy 引擎 / 会话 / 声明基类。

四层架构：基础设施层（含数据模型层）。全异步：
  - 开发/默认：SQLite + aiosqlite
  - 生产：MySQL + asyncmy（经 config.DATABASE_URL 切换）
每请求一个 async session（``get_session`` 依赖），事件循环内无阻塞。
"""
from __future__ import annotations

from collections.abc import AsyncGenerator

from sqlalchemy.ext.asyncio import (
    AsyncSession,
    async_sessionmaker,
    create_async_engine,
)
from sqlalchemy.orm import DeclarativeBase

from .. import config


class Base(DeclarativeBase):
    """SQLAlchemy 声明式基类（数据模型层继承）。"""


engine = create_async_engine(
    config.DATABASE_URL,
    pool_pre_ping=True,
)

AsyncSessionLocal = async_sessionmaker(
    bind=engine,
    class_=AsyncSession,
    autoflush=False,
    expire_on_commit=False,
)


async def init_db() -> None:
    """幂等地创建全部表（create_all 对已存在表无操作）。"""
    from . import models  # noqa: F401

    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)


async def get_session() -> AsyncGenerator[AsyncSession, None]:
    """FastAPI 依赖：请求级异步 SQLAlchemy 会话，请求结束自动关闭。"""
    async with AsyncSessionLocal() as session:
        yield session


def make_async_engine(db_url: str):
    """按给定 URL 创建独立异步引擎（测试用 tmp 数据库）。"""
    return create_async_engine(db_url, pool_pre_ping=True)


def make_async_session_factory(db_url: str) -> async_sessionmaker:
    return async_sessionmaker(
        bind=make_async_engine(db_url),
        class_=AsyncSession,
        autoflush=False,
        expire_on_commit=False,
    )
