"""存储基类测试：单入口 write 自动维护元数据。"""

import os
import hashlib

import pytest

from nutricare_data_packages.storage_base import StorageBase


class ConcreteStorage(StorageBase):
    """用于测试的具象存储实现。"""

    @property
    def storage_subdir(self) -> str:
        return "test_subdir"

    def _write_impl(self, relative_path: str, data: bytes) -> bool:
        target, _ = self.resolve_path(relative_path)
        target.parent.mkdir(parents=True, exist_ok=True)
        target.write_bytes(data)
        return True


class TestStorageBaseWrite:
    """直接写文件并校验自动元数据。"""

    @pytest.fixture
    def setup_env(self):
        original = {
            "mongodb_url": os.environ.get("mongodb_url"),
            "NUTRICARE_TICKET_ID": os.environ.get("NUTRICARE_TICKET_ID"),
            "NUTRICARE_TASK_ID": os.environ.get("NUTRICARE_TASK_ID"),
        }
        os.environ["mongodb_url"] = os.environ.get("mongodb_url", "127.0.0.1:27017")
        os.environ["NUTRICARE_TICKET_ID"] = "test_ticket_001"
        os.environ["NUTRICARE_TASK_ID"] = "test_task_001"
        yield
        for key, value in original.items():
            if value is None:
                os.environ.pop(key, None)
            else:
                os.environ[key] = value

    def test_write_upload_file_and_metadata(self, setup_env):
        """直接 write 后，校验文件和元数据。"""
        relative_path = "ceshi"
        content = b"content"
        expected_md5 = hashlib.md5(content).hexdigest()

        storage = ConcreteStorage()
        ok = storage.write(relative_path, content, title="展示用标题")
        path, _ = storage.resolve_path(relative_path)

        assert ok is True
        assert path.exists(), f"文件应写入: {path}"
        assert path.read_bytes() == content
        # 确认落在配置的存储根下
        assert path.resolve().relative_to(storage.get_root())
        doc = storage.metadata_collection.find_one(
            {"storage_subdir": "test_subdir", "relative_path": relative_path}
        )
        assert doc is not None
        assert doc.get("ticket_id") == "test_ticket_001"
        assert doc.get("task_id") == "test_task_001"
        assert doc.get("size") == len(content)
        assert doc.get("md5") == expected_md5
        assert doc.get("title") == "展示用标题"