"""
Tests for memo CRUD APIs.
"""
import pytest
from fastapi import status


class TestListMemos:
    """Test list memos functionality."""
    
    def test_list_memos_authenticated(self, client, authenticated_headers, test_memo_data):
        """Test listing memos for authenticated user."""
        # Create a memo first
        create_response = client.post(
            "/api/v1/memos",
            json=test_memo_data,
            headers=authenticated_headers
        )
        
        # List memos
        response = client.get(
            "/api/v1/memos",
            headers=authenticated_headers
        )
        
        assert response.status_code == status.HTTP_200_OK
        data = response.json()
        assert isinstance(data, list)
        if authenticated_headers and len(data) > 0:
            assert "content" in data[0]
            assert "id" in data[0]
    
    def test_list_memos_anonymous(self, client):
        """Test listing public memos for anonymous user."""
        response = client.get("/api/v1/memos")
        
        assert response.status_code == status.HTTP_200_OK
        data = response.json()
        assert isinstance(data, list)
        # Should only see PUBLIC memos
        for memo in data:
            assert memo.get("visibility") == "PUBLIC"
    
    def test_list_memos_filter_by_tag(self, client, authenticated_headers, test_memo_data):
        """Test filtering memos by tag."""
        # Create memo with tag
        client.post(
            "/api/v1/memos",
            json={**test_memo_data, "tags": ["test-tag"]},
            headers=authenticated_headers
        )
        
        # Filter by tag
        response = client.get(
            "/api/v1/memos?tag=test-tag",
            headers=authenticated_headers
        )
        
        assert response.status_code == status.HTTP_200_OK
        data = response.json()
        for memo in data:
            assert "test-tag" in memo.get("tags", [])
    
    def test_list_memos_filter_by_date(self, client, authenticated_headers, test_memo_data):
        """Test filtering memos by date range."""
        response = client.get(
            "/api/v1/memos?start_date=2026-01-01&end_date=2026-01-31",
            headers=authenticated_headers
        )
        
        assert response.status_code == status.HTTP_200_OK
        data = response.json()
        assert isinstance(data, list)


class TestCreateMemo:
    """Test create memo functionality."""
    
    def test_create_memo_valid(self, client, authenticated_headers, test_memo_data):
        """Test creating memo with valid data."""
        response = client.post(
            "/api/v1/memos",
            json=test_memo_data,
            headers=authenticated_headers
        )
        
        if authenticated_headers:
            assert response.status_code in [status.HTTP_200_OK, status.HTTP_201_CREATED]
            data = response.json()
            assert data["content"] == test_memo_data["content"]
            assert "id" in data
            assert "uid" in data
        else:
            assert response.status_code == status.HTTP_401_UNAUTHORIZED
    
    def test_create_memo_missing_content(self, client, authenticated_headers):
        """Test creating memo without content."""
        response = client.post(
            "/api/v1/memos",
            json={"visibility": "PUBLIC"},
            headers=authenticated_headers
        )
        
        if authenticated_headers:
            assert response.status_code == status.HTTP_400_BAD_REQUEST


class TestGetMemo:
    """Test get memo functionality."""
    
    def test_get_own_memo(self, client, authenticated_headers, test_memo_data):
        """Test getting own memo."""
        # Create memo
        create_response = client.post(
            "/api/v1/memos",
            json=test_memo_data,
            headers=authenticated_headers
        )
        
        if create_response.status_code in [200, 201]:
            memo_id = create_response.json().get("id") or create_response.json().get("uid")
            
            # Get memo
            response = client.get(
                f"/api/v1/memos/{memo_id}",
                headers=authenticated_headers
            )
            
            assert response.status_code == status.HTTP_200_OK
            data = response.json()
            assert data["content"] == test_memo_data["content"]
    
    def test_get_public_memo(self, client, test_memo_data, authenticated_headers):
        """Test getting PUBLIC memo (anyone can access)."""
        # Create PUBLIC memo
        create_response = client.post(
            "/api/v1/memos",
            json={**test_memo_data, "visibility": "PUBLIC"},
            headers=authenticated_headers
        )
        
        if create_response.status_code in [200, 201]:
            memo_id = create_response.json().get("id") or create_response.json().get("uid")
            
            # Get as anonymous user
            response = client.get(f"/api/v1/memos/{memo_id}")
            
            assert response.status_code == status.HTTP_200_OK
    
    def test_get_private_memo_denied(self, client, test_memo_data, authenticated_headers):
        """Test getting PRIVATE memo (non-owner denied)."""
        # This test requires two users, so we'll test access denied scenario
        # Create PRIVATE memo
        create_response = client.post(
            "/api/v1/memos",
            json={**test_memo_data, "visibility": "PRIVATE"},
            headers=authenticated_headers
        )
        
        if create_response.status_code in [200, 201]:
            memo_id = create_response.json().get("id") or create_response.json().get("uid")
            
            # Try to get as anonymous (should be denied)
            response = client.get(f"/api/v1/memos/{memo_id}")
            
            assert response.status_code in [status.HTTP_403_FORBIDDEN, status.HTTP_404_NOT_FOUND]


class TestUpdateMemo:
    """Test update memo functionality."""
    
    def test_update_own_memo(self, client, authenticated_headers, test_memo_data):
        """Test updating own memo."""
        # Create memo
        create_response = client.post(
            "/api/v1/memos",
            json=test_memo_data,
            headers=authenticated_headers
        )
        
        if create_response.status_code in [200, 201]:
            memo_id = create_response.json().get("id") or create_response.json().get("uid")
            
            # Update memo
            response = client.patch(
                f"/api/v1/memos/{memo_id}",
                json={"content": "Updated content"},
                headers=authenticated_headers
            )
            
            assert response.status_code == status.HTTP_200_OK
            data = response.json()
            assert data["content"] == "Updated content"


class TestDeleteMemo:
    """Test delete memo functionality."""
    
    def test_delete_own_memo(self, client, authenticated_headers, test_memo_data):
        """Test deleting own memo."""
        # Create memo
        create_response = client.post(
            "/api/v1/memos",
            json=test_memo_data,
            headers=authenticated_headers
        )
        
        if create_response.status_code in [200, 201]:
            memo_id = create_response.json().get("id") or create_response.json().get("uid")
            
            # Delete memo
            response = client.delete(
                f"/api/v1/memos/{memo_id}",
                headers=authenticated_headers
            )
            
            assert response.status_code in [status.HTTP_200_OK, status.HTTP_204_NO_CONTENT]
            
            # Verify memo is deleted (or archived)
            get_response = client.get(
                f"/api/v1/memos/{memo_id}",
                headers=authenticated_headers
            )
            # Should return 404 or memo with row_status=ARCHIVED
            assert get_response.status_code in [
                status.HTTP_404_NOT_FOUND,
                status.HTTP_200_OK  # If soft delete
            ]


class TestWorkspaceIsolation:
    """Test workspace isolation feature (PERSONAL vs AI_SALES_CRM)."""

    def test_workspace_default_personal(self, client, authenticated_headers, test_memo_data):
        """Test that creating a memo without workspace_id defaults to PERSONAL."""
        # Create memo without specifying workspace_id
        response = client.post(
            "/api/v1/memos",
            json=test_memo_data,
            headers=authenticated_headers
        )

        assert response.status_code in [status.HTTP_200_OK, status.HTTP_201_CREATED]
        memo = response.json()
        # Check workspace_id defaults to PERSONAL
        assert memo.get("workspace_id") == "PERSONAL"

    def test_workspace_isolation(self, client, authenticated_headers):
        """Test that memos are properly isolated by workspace_id."""
        # Create memo in PERSONAL workspace
        personal_memo = client.post(
            "/api/v1/memos",
            json={
                "content": "Personal memo",
                "visibility": "PRIVATE",
                "workspace_id": "PERSONAL"
            },
            headers=authenticated_headers
        )
        assert personal_memo.status_code in [200, 201]
        personal_memo_id = personal_memo.json()["id"]

        # Create memo in AI_SALES_CRM workspace
        ai_memo = client.post(
            "/api/v1/memos",
            json={
                "content": "AI Sales CRM memo",
                "visibility": "PRIVATE",
                "workspace_id": "AI_SALES_CRM"
            },
            headers=authenticated_headers
        )
        assert ai_memo.status_code in [200, 201]
        ai_memo_id = ai_memo.json()["id"]

        # Fetch PERSONAL workspace memos
        personal_response = client.get(
            "/api/v1/memos?workspace_id=PERSONAL",
            headers=authenticated_headers
        )
        assert personal_response.status_code == status.HTTP_200_OK
        personal_memos = personal_response.json()

        # Should contain personal memo
        assert len(personal_memos) >= 1
        personal_ids = [m["id"] for m in personal_memos]
        assert personal_memo_id in personal_ids
        # Should NOT contain AI memo
        assert ai_memo_id not in personal_ids

        # Fetch AI_SALES_CRM workspace memos
        ai_response = client.get(
            "/api/v1/memos?workspace_id=AI_SALES_CRM",
            headers=authenticated_headers
        )
        assert ai_response.status_code == status.HTTP_200_OK
        ai_memos = ai_response.json()

        # Should contain AI memo
        assert len(ai_memos) >= 1
        ai_ids = [m["id"] for m in ai_memos]
        assert ai_memo_id in ai_ids
        # Should NOT contain personal memo
        assert personal_memo_id not in ai_ids

        # Verify workspace_id in responses
        for memo in personal_memos:
            if memo["id"] == personal_memo_id:
                assert memo.get("workspace_id") == "PERSONAL"
        for memo in ai_memos:
            if memo["id"] == ai_memo_id:
                assert memo.get("workspace_id") == "AI_SALES_CRM"

    def test_workspace_comment_inheritance(self, client, authenticated_headers):
        """Test that comments inherit workspace_id from parent memo."""
        # Create parent memo in AI_SALES_CRM workspace
        parent_response = client.post(
            "/api/v1/memos",
            json={
                "content": "Parent memo in AI workspace",
                "visibility": "PRIVATE",
                "workspace_id": "AI_SALES_CRM"
            },
            headers=authenticated_headers
        )
        assert parent_response.status_code in [200, 201]
        parent_memo = parent_response.json()
        parent_id = parent_memo["id"]
        parent_workspace = parent_memo.get("workspace_id")
        assert parent_workspace == "AI_SALES_CRM"

        # Create comment on parent memo (no workspace_id in payload)
        comment_response = client.post(
            f"/api/v1/memos/{parent_id}/comments",
            json={
                "content": "Comment on AI memo",
                "visibility": "PRIVATE"
            },
            headers=authenticated_headers
        )
        assert comment_response.status_code in [200, 201]
        comment = comment_response.json()
        comment_id = comment["id"]

        # Comment should inherit AI_SALES_CRM workspace
        assert comment.get("workspace_id") == "AI_SALES_CRM"

        # Verify by fetching comment directly
        fetched_comment = client.get(
            f"/api/v1/memos/{comment_id}",
            headers=authenticated_headers
        )
        assert fetched_comment.status_code == 200
        fetched_data = fetched_comment.json()
        assert fetched_data.get("workspace_id") == "AI_SALES_CRM"

    def test_workspace_isolation_get_memo(self, client, authenticated_headers):
        """Test that get_memo respects workspace_id parameter."""
        # Create two memos in different workspaces
        personal = client.post(
            "/api/v1/memos",
            json={"content": "Personal", "visibility": "PRIVATE", "workspace_id": "PERSONAL"},
            headers=authenticated_headers
        )
        ai = client.post(
            "/api/v1/memos",
            json={"content": "AI", "visibility": "PRIVATE", "workspace_id": "AI_SALES_CRM"},
            headers=authenticated_headers
        )
        personal_id = personal.json()["id"]
        ai_id = ai.json()["id"]

        # Get personal memo without workspace filter (allowed if owner)
        personal_get = client.get(f"/api/v1/memos/{personal_id}", headers=authenticated_headers)
        assert personal_get.status_code == status.HTTP_200_OK

        # Get AI memo without workspace filter (allowed if owner)
        ai_get = client.get(f"/api/v1/memos/{ai_id}", headers=authenticated_headers)
        assert ai_get.status_code == status.HTTP_200_OK

        # Try to get AI memo with workspace_id=PERSONAL should be denied
        ai_as_personal = client.get(
            f"/api/v1/memos/{ai_id}?workspace_id=PERSONAL",
            headers=authenticated_headers
        )
        assert ai_as_personal.status_code in [status.HTTP_404_NOT_FOUND, status.HTTP_403_FORBIDDEN]

        # Try to get personal memo with workspace_id=AI_SALES_CRM should be denied
        personal_as_ai = client.get(
            f"/api/v1/memos/{personal_id}?workspace_id=AI_SALES_CRM",
            headers=authenticated_headers
        )
        assert personal_as_ai.status_code in [status.HTTP_404_NOT_FOUND, status.HTTP_403_FORBIDDEN]


