"""
资产编码生成工具
使用PostgreSQL Advisory Lock保证并发安全
"""
from datetime import datetime
from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.config import settings


async def generate_asset_code(db: AsyncSession) -> str:
    """
    生成资产编码

    格式: AS + YYYYMMDD + 流水号(4位)
    示例: AS202501240001

    使用PostgreSQL Advisory Lock保证并发安全

    Args:
        db: 数据库会话

    Returns:
        资产编码
    """
    # 获取当前日期字符串
    date_str = datetime.now().strftime("%Y%m%d")
    prefix = f"AS{date_str}"

    # 使用Advisory Lock保证并发安全
    # 使用日期作为锁ID，避免不同日期的锁冲突
    lock_id = int(date_str)

    try:
        # 获取锁
        await db.execute(text(f"SELECT pg_advisory_lock({lock_id})"))

        # 查询今天最大的序号
        result = await db.execute(
            text("""
                SELECT CAST(SUBSTRING(asset_code FROM 13 FOR 4) AS INTEGER) as max_seq
                FROM assets
                WHERE asset_code LIKE :prefix
                AND deleted_at IS NULL
                ORDER BY asset_code DESC
                LIMIT 1
            """),
            {"prefix": f"{prefix}%"}
        )

        row = result.fetchone()
        max_seq = row[0] if row and row[0] else 0

        # 生成新序号
        new_seq = max_seq + 1
        seq_str = f"{new_seq:04d}"  # 补零到4位

        # 组合编码
        asset_code = f"{prefix}{seq_str}"

        return asset_code

    finally:
        # 释放锁
        await db.execute(text(f"SELECT pg_advisory_unlock({lock_id})"))


def validate_asset_code(asset_code: str) -> bool:
    """
    验证资产编码格式

    Args:
        asset_code: 资产编码

    Returns:
        是否有效
    """
    if not asset_code or len(asset_code) != 14:
        return False

    # 检查前缀
    if not asset_code.startswith("AS"):
        return False

    # 检查日期部分
    date_str = asset_code[2:10]
    try:
        datetime.strptime(date_str, "%Y%m%d")
    except ValueError:
        return False

    # 检查序号部分
    seq_str = asset_code[10:]
    if not seq_str.isdigit():
        return False

    return True
