"""Medium priority tag API tests."""

from __future__ import annotations

from typing import TYPE_CHECKING

import pytest
from fastapi.testclient import TestClient

if TYPE_CHECKING:
    from sqlalchemy.orm import Session
    from backend.db.models import Photo, Tag


class TestTagListing:
    """Test tag listing endpoints."""

    def test_get_tags_success(
        self,
        test_client: TestClient,
        test_db_session: "Session",
    ):
        """Verify tags list retrieval."""
        from backend.db.models import Tag
        
        # Create a test tag
        tag = Tag(tag_name="test-tag")
        test_db_session.add(tag)
        test_db_session.commit()
        
        response = test_client.get("/api/v1/tags")
        
        assert response.status_code == 200
        data = response.json()
        assert "items" in data
        assert "total" in data

    def test_get_tags_empty_list(
        self,
        test_client: TestClient,
    ):
        """Verify empty list when no tags."""
        response = test_client.get("/api/v1/tags")
        
        assert response.status_code == 200
        data = response.json()
        assert "items" in data
        assert isinstance(data["items"], list)


class TestTagCRUD:
    """Test tag CRUD endpoints."""

    def test_create_tag_success(
        self,
        test_client: TestClient,
    ):
        """Verify tag creation."""
        response = test_client.post(
            "/api/v1/tags",
            json={"tag_name": "new-tag"},
        )
        
        assert response.status_code == 200
        data = response.json()
        assert data["tag_name"] == "new-tag"
        assert "id" in data

    def test_create_tag_duplicate(
        self,
        test_client: TestClient,
        test_db_session: "Session",
    ):
        """Verify returns existing tag if duplicate."""
        from backend.db.models import Tag
        
        # Create tag first
        tag = Tag(tag_name="duplicate-tag")
        test_db_session.add(tag)
        test_db_session.commit()
        test_db_session.refresh(tag)
        
        # Try to create again
        response = test_client.post(
            "/api/v1/tags",
            json={"tag_name": "duplicate-tag"},
        )
        
        assert response.status_code == 200
        data = response.json()
        assert data["id"] == tag.id
        assert data["tag_name"] == "duplicate-tag"

    def test_create_tag_strips_whitespace(
        self,
        test_client: TestClient,
    ):
        """Verify whitespace handling."""
        response = test_client.post(
            "/api/v1/tags",
            json={"tag_name": "  whitespace-tag  "},
        )
        
        assert response.status_code == 200
        data = response.json()
        # Tag should be trimmed
        assert "whitespace-tag" in data["tag_name"]

    def test_update_tag_success(
        self,
        test_client: TestClient,
        test_db_session: "Session",
    ):
        """Verify tag update."""
        from backend.db.models import Tag
        
        tag = Tag(tag_name="old-name")
        test_db_session.add(tag)
        test_db_session.commit()
        test_db_session.refresh(tag)
        
        response = test_client.put(
            f"/api/v1/tags/{tag.id}",
            json={"tag_name": "new-name"},
        )
        
        assert response.status_code == 200
        data = response.json()
        assert data["tag_name"] == "new-name"

    def test_update_tag_not_found(
        self,
        test_client: TestClient,
    ):
        """Verify 404 for non-existent tag."""
        response = test_client.put(
            "/api/v1/tags/99999",
            json={"tag_name": "new-name"},
        )
        
        assert response.status_code in [400, 404]  # Implementation dependent

    def test_delete_tag_success(
        self,
        test_client: TestClient,
        test_db_session: "Session",
    ):
        """Verify tag deletion."""
        from backend.db.models import Tag
        
        tag = Tag(tag_name="delete-me")
        test_db_session.add(tag)
        test_db_session.commit()
        test_db_session.refresh(tag)
        
        response = test_client.post(
            "/api/v1/tags/delete",
            json={"tag_ids": [tag.id]},
        )
        
        assert response.status_code == 200

    def test_delete_tag_not_found(
        self,
        test_client: TestClient,
    ):
        """Verify 404 handling."""
        response = test_client.post(
            "/api/v1/tags/delete",
            json={"tag_ids": [99999]},
        )
        
        # May return 200 with 0 deleted or error
        assert response.status_code in [200, 400, 404]


class TestPhotoTagOperations:
    """Test photo-tag operations."""

    def test_add_tags_to_photos_success(
        self,
        test_client: TestClient,
        test_photo: "Photo",
    ):
        """Verify adding tags to photos."""
        response = test_client.post(
            "/api/v1/tags/photos/add",
            json={
                "photo_ids": [test_photo.id],
                "tag_names": ["test-tag-1", "test-tag-2"],
            },
        )
        
        assert response.status_code == 200
        data = response.json()
        assert "photos_updated" in data
        assert data["photos_updated"] >= 0

    def test_add_tags_to_photos_empty_photo_ids(
        self,
        test_client: TestClient,
    ):
        """Verify 400 with empty photo_ids."""
        response = test_client.post(
            "/api/v1/tags/photos/add",
            json={
                "photo_ids": [],
                "tag_names": ["test-tag"],
            },
        )
        
        assert response.status_code == 400

    def test_add_tags_to_photos_empty_tag_names(
        self,
        test_client: TestClient,
        test_photo: "Photo",
    ):
        """Verify 400 with empty tag_names."""
        response = test_client.post(
            "/api/v1/tags/photos/add",
            json={
                "photo_ids": [test_photo.id],
                "tag_names": [],
            },
        )
        
        assert response.status_code == 400

    def test_remove_tags_from_photos_success(
        self,
        test_client: TestClient,
        test_photo: "Photo",
        test_db_session: "Session",
    ):
        """Verify tag removal."""
        from backend.db.models import Tag, PhotoTagLinkage
        
        # Add tag first
        tag = Tag(tag_name="remove-me")
        test_db_session.add(tag)
        test_db_session.flush()
        
        photo_tag = PhotoTagLinkage(photo_id=test_photo.id, tag_id=tag.id)
        test_db_session.add(photo_tag)
        test_db_session.commit()
        
        # Remove it
        response = test_client.post(
            "/api/v1/tags/photos/remove",
            json={
                "photo_ids": [test_photo.id],
                "tag_names": ["remove-me"],
            },
        )
        
        assert response.status_code == 200
        data = response.json()
        assert "tags_removed" in data

    def test_get_photo_tags_success(
        self,
        test_client: TestClient,
        test_photo: "Photo",
        test_db_session: "Session",
    ):
        """Verify photo tags retrieval."""
        from backend.db.models import Tag, PhotoTagLinkage
        
        tag = Tag(tag_name="photo-tag")
        test_db_session.add(tag)
        test_db_session.flush()
        
        photo_tag = PhotoTagLinkage(photo_id=test_photo.id, tag_id=tag.id)
        test_db_session.add(photo_tag)
        test_db_session.commit()
        
        response = test_client.get(f"/api/v1/tags/photos/{test_photo.id}")
        
        assert response.status_code == 200
        data = response.json()
        assert "tags" in data
        assert len(data["tags"]) > 0

    def test_get_photo_tags_empty(
        self,
        test_client: TestClient,
        test_photo: "Photo",
    ):
        """Verify empty list for untagged photo."""
        response = test_client.get(f"/api/v1/tags/photos/{test_photo.id}")
        
        assert response.status_code == 200
        data = response.json()
        assert "tags" in data
        assert isinstance(data["tags"], list)

