"""防回归测试：P1 修复
- Bug 1: gen_task 过期内存对象 _repo.update() 覆盖 DB status 为 pending
- Bug 2: 封面模型误用 .metadata（SQLAlchemy 保留属性），应为 .extra_meta
"""

import ast
from pathlib import Path

import pytest

GENERATION_FILE = Path(__file__).resolve().parents[2] / "apps" / "worker" / "worker_app" / "tasks" / "generation.py"


def _read_source() -> str:
    return GENERATION_FILE.read_text(encoding="utf-8")


class TestCoverModelUsesExtraMeta:
    """封面持久化必须使用 ORM 属性 extra_meta，而不是 SQLAlchemy 保留的 .metadata。"""

    def test_no_metadata_attribute_access_on_cover_model(self):
        source = _read_source()
        # 禁止对 _cover_model.metadata 进行读或写
        assert "_cover_model.metadata" not in source, (
            "_cover_model.metadata is the SQLAlchemy reserved MetaData object, "
            "not the JSON column. Use _cover_model.extra_meta instead."
        )

    def test_extra_meta_used_for_cover_candidates(self):
        source = _read_source()
        assert "_cover_model.extra_meta" in source
        assert 'meta["cover_candidates"]' in source


class TestAssetAnalysesDoesNotOverwriteStatus:
    """保存 asset_analyses 时不能用过期的 gen_task 内存对象整体 _repo.update，
    否则会把已被 _update_task_status 改为 running 的 status 覆盖回 pending。"""

    def test_no_stale_repo_update_with_gen_task(self):
        source = _read_source()
        # 旧代码：gen_task.extra_meta = {...}; _repo.update(gen_task)
        # 这行会把内存中的 pending status 写回 DB
        assert "_repo.update(gen_task)" not in source, (
            "_repo.update(gen_task) writes a stale in-memory object back to DB, "
            "overwriting status set by _update_task_status. "
            "Use an independent session to update only extra_meta."
        )

    def test_no_stale_repo_update(self):
        """旧路径的 _repo.update(gen_task) 模式已随 DEPRECATED 代码一起删除。"""
        source = _read_source()
        assert "_repo.update(gen_task)" not in source


class TestGenerationTaskModelOrmAttribute:
    """确认 ORM 属性映射：Python 属性 extra_meta -> DB 列 metadata。"""

    def test_orm_attribute_is_extra_meta(self):
        from packages.adapters.sqlalchemy_impl.models import GenerationTaskModel

        # ORM 属性必须存在
        assert hasattr(GenerationTaskModel, "extra_meta")
        # .metadata 是 SQLAlchemy 声明基类保留的 MetaData，不是列描述符
        # 它不应该是我们的 JSON 字段
        from sqlalchemy import MetaData

        assert isinstance(GenerationTaskModel.metadata, MetaData)
