"""classification 分类领域模型单测."""

import pytest

from packages.domain.classification import (
    AssetClassification,
    AssetLibraryKind,
    ClassificationJob,
    ClassificationJobStatus,
    ClassificationStatus,
    IngestJobStatus,
)


class TestAssetLibraryKind:
    def test_values(self):
        assert AssetLibraryKind.VIDEO.value == "video"
        assert AssetLibraryKind.VOICE.value == "voice"
        assert AssetLibraryKind.IMAGE.value == "image"

    def test_is_str(self):
        assert isinstance(AssetLibraryKind.VIDEO, str)


class TestIngestJobStatus:
    def test_values(self):
        assert IngestJobStatus.PENDING.value == "pending"
        assert IngestJobStatus.PROCESSING.value == "processing"
        assert IngestJobStatus.COMPLETED.value == "completed"
        assert IngestJobStatus.FAILED.value == "failed"


class TestClassificationJobStatusMissing:
    """ClassificationJobStatus._missing_ 兼容性测试."""

    def test_normal_values(self):
        assert ClassificationJobStatus("pending") == ClassificationJobStatus.PENDING
        assert ClassificationJobStatus("processing") == ClassificationJobStatus.PROCESSING
        assert ClassificationJobStatus("completed") == ClassificationJobStatus.COMPLETED
        assert ClassificationJobStatus("failed") == ClassificationJobStatus.FAILED

    @pytest.mark.parametrize("value", ["done", "success", "finished", "complete"])
    def test_completed_aliases(self, value):
        assert ClassificationJobStatus(value) == ClassificationJobStatus.COMPLETED

    @pytest.mark.parametrize("value", ["fail", "error", "err"])
    def test_failed_aliases(self, value):
        assert ClassificationJobStatus(value) == ClassificationJobStatus.FAILED

    @pytest.mark.parametrize("value", ["process", "processing", "running", "run"])
    def test_processing_aliases(self, value):
        assert ClassificationJobStatus(value) == ClassificationJobStatus.PROCESSING

    @pytest.mark.parametrize("value", ["unknown", "foobar", ""])
    def test_unknown_fallback_to_pending(self, value):
        assert ClassificationJobStatus(value) == ClassificationJobStatus.PENDING

    def test_none_fallback_to_pending(self):
        assert ClassificationJobStatus(None) == ClassificationJobStatus.PENDING  # type: ignore[arg-type]

    def test_case_insensitive_with_strip(self):
        assert ClassificationJobStatus(" DONE ") == ClassificationJobStatus.COMPLETED
        assert ClassificationJobStatus("ERROR") == ClassificationJobStatus.FAILED

    def test_backward_compat_alias(self):
        """ClassificationStatus 是 ClassificationJobStatus 的别名."""
        assert ClassificationStatus is ClassificationJobStatus
        assert ClassificationStatus("done") == ClassificationJobStatus.COMPLETED


class TestAssetClassification:
    def test_values(self):
        assert AssetClassification.SCENIC.value == "scenic"
        assert AssetClassification.PRODUCT.value == "product"
        assert AssetClassification.PERSON.value == "person"
        assert AssetClassification.ANIMAL.value == "animal"
        assert AssetClassification.FOOD.value == "food"
        assert AssetClassification.TECH.value == "tech"
        assert AssetClassification.SPORT.value == "sport"
        assert AssetClassification.MUSIC.value == "music"
        assert AssetClassification.OTHER.value == "other"


class TestClassificationJobCreate:
    def test_create_normal(self):
        job = ClassificationJob.create(project_id="proj1", asset_id="asset1")
        assert job.id
        assert job.project_id == "proj1"
        assert job.asset_id == "asset1"
        assert job.status == ClassificationJobStatus.PENDING
        assert job.classification == ""
        assert job.confidence == 0.0
        assert job.error_message == ""

    def test_create_strips_whitespace(self):
        job = ClassificationJob.create(project_id="  proj1  ", asset_id="  asset1  ")
        assert job.project_id == "proj1"
        assert job.asset_id == "asset1"

    def test_create_empty_project_id_raises(self):
        with pytest.raises(ValueError, match="project_id 不能为空"):
            ClassificationJob.create(project_id="", asset_id="a1")

    def test_create_empty_asset_id_raises(self):
        with pytest.raises(ValueError, match="asset_id 不能为空"):
            ClassificationJob.create(project_id="p1", asset_id="")

    def test_create_whitespace_project_id_raises(self):
        with pytest.raises(ValueError, match="project_id 不能为空"):
            ClassificationJob.create(project_id="   ", asset_id="a1")

    def test_create_unique_ids(self):
        job1 = ClassificationJob.create(project_id="p1", asset_id="a1")
        job2 = ClassificationJob.create(project_id="p1", asset_id="a2")
        assert job1.id != job2.id
