"""Tests for app/api/imap_profiles.py and app/utils/allowed_types category helpers."""

import pytest

from app.utils.allowed_types import (
    ALL_CATEGORIES,
    DEFAULT_CATEGORIES,
    FILE_TYPE_CATEGORIES,
    get_allowed_types_for_categories,
)


@pytest.mark.unit
class TestFileTypeCategories:
    """Tests for FILE_TYPE_CATEGORIES and get_allowed_types_for_categories."""

    def test_all_category_keys_present(self):
        """Test that the six expected categories exist."""
        assert set(FILE_TYPE_CATEGORIES.keys()) == {"pdf", "office", "opendocument", "text", "web", "images"}

    def test_each_category_has_required_fields(self):
        """Test that every category entry has label, description, mime_types, extensions."""
        for key, info in FILE_TYPE_CATEGORIES.items():
            assert "label" in info, f"Category '{key}' missing 'label'"
            assert "description" in info, f"Category '{key}' missing 'description'"
            assert "mime_types" in info, f"Category '{key}' missing 'mime_types'"
            assert "extensions" in info, f"Category '{key}' missing 'extensions'"

    def test_pdf_category_contains_pdf_mime(self):
        """Test that the pdf category includes application/pdf."""
        assert "application/pdf" in FILE_TYPE_CATEGORIES["pdf"]["mime_types"]
        assert ".pdf" in FILE_TYPE_CATEGORIES["pdf"]["extensions"]

    def test_images_category_contains_jpeg(self):
        """Test that the images category includes image/jpeg."""
        assert "image/jpeg" in FILE_TYPE_CATEGORIES["images"]["mime_types"]
        assert ".jpg" in FILE_TYPE_CATEGORIES["images"]["extensions"]
        assert ".png" in FILE_TYPE_CATEGORIES["images"]["extensions"]

    def test_get_allowed_types_for_default_categories(self):
        """Test that DEFAULT_CATEGORIES excludes image MIME types."""
        mime_types, extensions = get_allowed_types_for_categories(DEFAULT_CATEGORIES)
        assert "application/pdf" in mime_types
        assert "application/msword" in mime_types
        # images should NOT be in the default
        assert "image/jpeg" not in mime_types
        assert ".jpg" not in extensions

    def test_get_allowed_types_for_all_categories(self):
        """Test that ALL_CATEGORIES includes image MIME types."""
        mime_types, extensions = get_allowed_types_for_categories(ALL_CATEGORIES)
        assert "image/jpeg" in mime_types
        assert ".jpg" in extensions
        assert "application/pdf" in mime_types

    def test_get_allowed_types_returns_frozensets(self):
        """Test that returned sets are frozensets."""
        mime_types, extensions = get_allowed_types_for_categories(["pdf"])
        assert isinstance(mime_types, frozenset)
        assert isinstance(extensions, frozenset)

    def test_get_allowed_types_unknown_category_ignored(self):
        """Test that unknown category keys are silently ignored."""
        mime_types, extensions = get_allowed_types_for_categories(["pdf", "nonexistent_category"])
        assert "application/pdf" in mime_types  # 'pdf' still works
        # No crash for unknown key

    def test_get_allowed_types_empty_list(self):
        """Test empty category list returns empty sets."""
        mime_types, extensions = get_allowed_types_for_categories([])
        assert mime_types == frozenset()
        assert extensions == frozenset()

    def test_default_categories_excludes_images(self):
        """Test that DEFAULT_CATEGORIES does not include 'images'."""
        assert "images" not in DEFAULT_CATEGORIES

    def test_all_categories_includes_images(self):
        """Test that ALL_CATEGORIES includes 'images'."""
        assert "images" in ALL_CATEGORIES

    def test_all_categories_is_superset_of_default(self):
        """Test that ALL_CATEGORIES contains all DEFAULT_CATEGORIES."""
        for cat in DEFAULT_CATEGORIES:
            assert cat in ALL_CATEGORIES


@pytest.mark.unit
class TestImapProfilesApiLogic:
    """Tests for ingestion profile validation helpers."""

    def test_validate_categories_accepts_valid_keys(self):
        """Test that valid category keys pass validation."""
        from app.api.imap_profiles import _validate_categories

        result = _validate_categories(["pdf", "office", "images"])
        assert set(result) == {"pdf", "office", "images"}

    def test_validate_categories_rejects_unknown_key(self):
        """Test that unknown category keys raise 422."""
        from fastapi import HTTPException

        from app.api.imap_profiles import _validate_categories

        with pytest.raises(HTTPException) as exc_info:
            _validate_categories(["pdf", "nonexistent"])
        assert exc_info.value.status_code == 422
        assert "nonexistent" in str(exc_info.value.detail)

    def test_validate_categories_deduplicates(self):
        """Test that duplicate category keys are de-duplicated while preserving order."""
        from app.api.imap_profiles import _validate_categories

        result = _validate_categories(["pdf", "pdf", "office", "pdf"])
        assert result == ["pdf", "office"]

    def test_to_response_serializes_profile(self, tmp_path):
        """Test _to_response produces expected dict shape."""
        from unittest.mock import MagicMock

        from app.api.imap_profiles import _to_response

        profile = MagicMock()
        profile.id = 42
        profile.name = "My Profile"
        profile.description = "Test description"
        profile.owner_id = "user@example.com"
        profile.allowed_categories = '["pdf","office"]'
        profile.is_builtin = False
        profile.created_at = None
        profile.updated_at = None

        result = _to_response(profile)
        assert result["id"] == 42
        assert result["name"] == "My Profile"
        assert result["allowed_categories"] == ["pdf", "office"]
        assert len(result["categories_detail"]) == 2
        assert result["categories_detail"][0]["key"] == "pdf"
        assert result["is_builtin"] is False

    def test_to_response_handles_invalid_categories_json(self):
        """Test _to_response gracefully handles invalid JSON in allowed_categories."""
        from unittest.mock import MagicMock

        from app.api.imap_profiles import _to_response

        profile = MagicMock()
        profile.id = 1
        profile.name = "Broken"
        profile.description = None
        profile.owner_id = None
        profile.allowed_categories = "this is not valid json {"
        profile.is_builtin = True
        profile.created_at = None
        profile.updated_at = None

        result = _to_response(profile)
        assert result["allowed_categories"] == []
