# tests/fixtures/message_fixtures.py
"""
Messaging-related test fixtures.

Note: Fixtures should NOT use db.expunge() as it breaks lazy loading.
See tests/conftest.py for details on fixture best practices.
"""

import pytest

from app.modules.messaging.models import (
    Conversation,
    ConversationParticipant,
    ConversationType,
    Message,
    MessageAttachment,
    ParticipantType,
)


@pytest.fixture
def test_conversation_admin_vendor(db, test_admin, test_vendor_user, test_vendor):
    """Create a test conversation between admin and vendor user."""
    conversation = Conversation(
        conversation_type=ConversationType.ADMIN_VENDOR,
        subject="Test Admin-Vendor Conversation",
        vendor_id=test_vendor.id,
    )
    db.add(conversation)
    db.commit()
    db.refresh(conversation)

    # Add admin participant
    admin_participant = ConversationParticipant(
        conversation_id=conversation.id,
        participant_type=ParticipantType.ADMIN,
        participant_id=test_admin.id,
    )
    db.add(admin_participant)

    # Add vendor participant
    vendor_participant = ConversationParticipant(
        conversation_id=conversation.id,
        participant_type=ParticipantType.VENDOR,
        participant_id=test_vendor_user.id,
        vendor_id=test_vendor.id,
    )
    db.add(vendor_participant)

    db.commit()
    db.refresh(conversation)
    return conversation


@pytest.fixture
def test_conversation_vendor_customer(db, test_vendor_user, test_customer, test_vendor):
    """Create a test conversation between vendor and customer."""
    conversation = Conversation(
        conversation_type=ConversationType.VENDOR_CUSTOMER,
        subject="Test Vendor-Customer Conversation",
        vendor_id=test_vendor.id,
    )
    db.add(conversation)
    db.commit()
    db.refresh(conversation)

    # Add vendor participant
    vendor_participant = ConversationParticipant(
        conversation_id=conversation.id,
        participant_type=ParticipantType.VENDOR,
        participant_id=test_vendor_user.id,
        vendor_id=test_vendor.id,
    )
    db.add(vendor_participant)

    # Add customer participant
    customer_participant = ConversationParticipant(
        conversation_id=conversation.id,
        participant_type=ParticipantType.CUSTOMER,
        participant_id=test_customer.id,
    )
    db.add(customer_participant)

    db.commit()
    db.refresh(conversation)
    return conversation


@pytest.fixture
def test_conversation_admin_customer(db, test_admin, test_customer, test_vendor):
    """Create a test conversation between admin and customer."""
    conversation = Conversation(
        conversation_type=ConversationType.ADMIN_CUSTOMER,
        subject="Test Admin-Customer Conversation",
        vendor_id=test_vendor.id,
    )
    db.add(conversation)
    db.commit()
    db.refresh(conversation)

    # Add admin participant
    admin_participant = ConversationParticipant(
        conversation_id=conversation.id,
        participant_type=ParticipantType.ADMIN,
        participant_id=test_admin.id,
    )
    db.add(admin_participant)

    # Add customer participant
    customer_participant = ConversationParticipant(
        conversation_id=conversation.id,
        participant_type=ParticipantType.CUSTOMER,
        participant_id=test_customer.id,
    )
    db.add(customer_participant)

    db.commit()
    db.refresh(conversation)
    return conversation


@pytest.fixture
def test_message(db, test_conversation_admin_vendor, test_admin):
    """Create a test message in a conversation."""
    message = Message(
        conversation_id=test_conversation_admin_vendor.id,
        sender_type=ParticipantType.ADMIN,
        sender_id=test_admin.id,
        content="This is a test message from admin.",
    )
    db.add(message)

    # Update conversation stats
    test_conversation_admin_vendor.message_count = 1
    test_conversation_admin_vendor.last_message_at = message.created_at

    db.commit()
    db.refresh(message)
    return message


@pytest.fixture
def test_message_with_attachment(db, test_conversation_admin_vendor, test_admin):
    """Create a test message with an attachment."""
    message = Message(
        conversation_id=test_conversation_admin_vendor.id,
        sender_type=ParticipantType.ADMIN,
        sender_id=test_admin.id,
        content="This message has an attachment.",
    )
    db.add(message)
    db.commit()
    db.refresh(message)

    attachment = MessageAttachment(
        message_id=message.id,
        filename="test_file_abc123.pdf",
        original_filename="test_document.pdf",
        file_path="/uploads/messages/2025/01/1/test_file_abc123.pdf",
        file_size=12345,
        mime_type="application/pdf",
        is_image=False,
    )
    db.add(attachment)
    db.commit()
    db.refresh(message)

    return message


@pytest.fixture
def closed_conversation(db, test_admin, test_vendor_user, test_vendor):
    """Create a closed conversation."""
    from datetime import datetime, timezone

    conversation = Conversation(
        conversation_type=ConversationType.ADMIN_VENDOR,
        subject="Closed Conversation",
        vendor_id=test_vendor.id,
        is_closed=True,
        closed_at=datetime.now(timezone.utc),
        closed_by_type=ParticipantType.ADMIN,
        closed_by_id=test_admin.id,
    )
    db.add(conversation)
    db.commit()
    db.refresh(conversation)

    # Add participants
    admin_participant = ConversationParticipant(
        conversation_id=conversation.id,
        participant_type=ParticipantType.ADMIN,
        participant_id=test_admin.id,
    )
    db.add(admin_participant)

    vendor_participant = ConversationParticipant(
        conversation_id=conversation.id,
        participant_type=ParticipantType.VENDOR,
        participant_id=test_vendor_user.id,
        vendor_id=test_vendor.id,
    )
    db.add(vendor_participant)

    db.commit()
    db.refresh(conversation)
    return conversation


@pytest.fixture
def multiple_conversations(db, test_admin, test_vendor_user, test_customer, test_vendor):
    """Create multiple conversations of different types."""
    conversations = []

    # Create 3 admin-vendor conversations
    for i in range(3):
        conv = Conversation(
            conversation_type=ConversationType.ADMIN_VENDOR,
            subject=f"Admin-Vendor Conversation {i+1}",
            vendor_id=test_vendor.id,
        )
        db.add(conv)
        db.commit()
        db.refresh(conv)

        db.add(
            ConversationParticipant(
                conversation_id=conv.id,
                participant_type=ParticipantType.ADMIN,
                participant_id=test_admin.id,
            )
        )
        db.add(
            ConversationParticipant(
                conversation_id=conv.id,
                participant_type=ParticipantType.VENDOR,
                participant_id=test_vendor_user.id,
                vendor_id=test_vendor.id,
            )
        )
        conversations.append(conv)

    # Create 2 vendor-customer conversations
    for i in range(2):
        conv = Conversation(
            conversation_type=ConversationType.VENDOR_CUSTOMER,
            subject=f"Vendor-Customer Conversation {i+1}",
            vendor_id=test_vendor.id,
        )
        db.add(conv)
        db.commit()
        db.refresh(conv)

        db.add(
            ConversationParticipant(
                conversation_id=conv.id,
                participant_type=ParticipantType.VENDOR,
                participant_id=test_vendor_user.id,
                vendor_id=test_vendor.id,
            )
        )
        db.add(
            ConversationParticipant(
                conversation_id=conv.id,
                participant_type=ParticipantType.CUSTOMER,
                participant_id=test_customer.id,
            )
        )
        conversations.append(conv)

    db.commit()

    # Refresh all
    for conv in conversations:
        db.refresh(conv)

    return conversations


@pytest.fixture
def vendor_api_conversation(db, test_admin, test_vendor_user, test_vendor_with_vendor_user):
    """Create a conversation for vendor API tests (uses vendor from vendor_user_headers)."""
    conversation = Conversation(
        conversation_type=ConversationType.ADMIN_VENDOR,
        subject="Vendor API Test Conversation",
        vendor_id=test_vendor_with_vendor_user.id,
    )
    db.add(conversation)
    db.commit()
    db.refresh(conversation)

    # Add admin participant
    admin_participant = ConversationParticipant(
        conversation_id=conversation.id,
        participant_type=ParticipantType.ADMIN,
        participant_id=test_admin.id,
    )
    db.add(admin_participant)

    # Add vendor participant (uses test_vendor_user which vendor_user_headers uses)
    vendor_participant = ConversationParticipant(
        conversation_id=conversation.id,
        participant_type=ParticipantType.VENDOR,
        participant_id=test_vendor_user.id,
        vendor_id=test_vendor_with_vendor_user.id,
    )
    db.add(vendor_participant)

    db.commit()
    db.refresh(conversation)
    return conversation


@pytest.fixture
def vendor_api_closed_conversation(db, test_admin, test_vendor_user, test_vendor_with_vendor_user):
    """Create a closed conversation for vendor API tests."""
    from datetime import datetime, timezone

    conversation = Conversation(
        conversation_type=ConversationType.ADMIN_VENDOR,
        subject="Vendor API Closed Conversation",
        vendor_id=test_vendor_with_vendor_user.id,
        is_closed=True,
        closed_at=datetime.now(timezone.utc),
        closed_by_type=ParticipantType.ADMIN,
        closed_by_id=test_admin.id,
    )
    db.add(conversation)
    db.commit()
    db.refresh(conversation)

    # Add participants
    admin_participant = ConversationParticipant(
        conversation_id=conversation.id,
        participant_type=ParticipantType.ADMIN,
        participant_id=test_admin.id,
    )
    db.add(admin_participant)

    vendor_participant = ConversationParticipant(
        conversation_id=conversation.id,
        participant_type=ParticipantType.VENDOR,
        participant_id=test_vendor_user.id,
        vendor_id=test_vendor_with_vendor_user.id,
    )
    db.add(vendor_participant)

    db.commit()
    db.refresh(conversation)
    return conversation
