import pytest
from fastapi import status
from app.core.exceptions import (
    ListNotFoundError,
    ListPermissionError,
    ListCreatorRequiredError,
    GroupNotFoundError,
    GroupPermissionError,
    GroupMembershipError,
    GroupOperationError,
    GroupValidationError,
    ItemNotFoundError,
    UserNotFoundError,
    InvalidOperationError,
    DatabaseConnectionError,
    DatabaseIntegrityError,
    DatabaseTransactionError,
    DatabaseQueryError,
    OCRServiceUnavailableError,
    OCRServiceConfigError,
    OCRUnexpectedError,
    OCRQuotaExceededError,
    InvalidFileTypeError,
    FileTooLargeError,
    OCRProcessingError,
    EmailAlreadyRegisteredError,
    UserCreationError,
    InviteNotFoundError,
    InviteExpiredError,
    InviteAlreadyUsedError,
    InviteCreationError,
    ListStatusNotFoundError,
    ConflictError,
    InvalidCredentialsError,
    NotAuthenticatedError,
    JWTError,
    JWTUnexpectedError
)

def test_list_not_found_error():
    list_id = 123
    with pytest.raises(ListNotFoundError) as excinfo:
        raise ListNotFoundError(list_id=list_id)
    assert excinfo.value.status_code == status.HTTP_404_NOT_FOUND
    assert excinfo.value.detail == f"List {list_id} not found"

def test_list_permission_error():
    list_id = 456
    action = "delete"
    with pytest.raises(ListPermissionError) as excinfo:
        raise ListPermissionError(list_id=list_id, action=action)
    assert excinfo.value.status_code == status.HTTP_403_FORBIDDEN
    assert excinfo.value.detail == f"You do not have permission to {action} list {list_id}"

def test_list_permission_error_default_action():
    list_id = 789
    with pytest.raises(ListPermissionError) as excinfo:
        raise ListPermissionError(list_id=list_id)
    assert excinfo.value.status_code == status.HTTP_403_FORBIDDEN
    assert excinfo.value.detail == f"You do not have permission to access list {list_id}"

def test_list_creator_required_error():
    list_id = 101
    action = "update"
    with pytest.raises(ListCreatorRequiredError) as excinfo:
        raise ListCreatorRequiredError(list_id=list_id, action=action)
    assert excinfo.value.status_code == status.HTTP_403_FORBIDDEN
    assert excinfo.value.detail == f"Only the list creator can {action} list {list_id}"

def test_group_not_found_error():
    group_id = 202
    with pytest.raises(GroupNotFoundError) as excinfo:
        raise GroupNotFoundError(group_id=group_id)
    assert excinfo.value.status_code == status.HTTP_404_NOT_FOUND
    assert excinfo.value.detail == f"Group {group_id} not found"

def test_group_permission_error():
    group_id = 303
    action = "invite"
    with pytest.raises(GroupPermissionError) as excinfo:
        raise GroupPermissionError(group_id=group_id, action=action)
    assert excinfo.value.status_code == status.HTTP_403_FORBIDDEN
    assert excinfo.value.detail == f"You do not have permission to {action} in group {group_id}"

def test_group_membership_error():
    group_id = 404
    action = "post"
    with pytest.raises(GroupMembershipError) as excinfo:
        raise GroupMembershipError(group_id=group_id, action=action)
    assert excinfo.value.status_code == status.HTTP_403_FORBIDDEN
    assert excinfo.value.detail == f"You must be a member of group {group_id} to {action}"

def test_group_membership_error_default_action():
    group_id = 505
    with pytest.raises(GroupMembershipError) as excinfo:
        raise GroupMembershipError(group_id=group_id)
    assert excinfo.value.status_code == status.HTTP_403_FORBIDDEN
    assert excinfo.value.detail == f"You must be a member of group {group_id} to access"

def test_group_operation_error():
    detail_msg = "Failed to perform group operation."
    with pytest.raises(GroupOperationError) as excinfo:
        raise GroupOperationError(detail=detail_msg)
    assert excinfo.value.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
    assert excinfo.value.detail == detail_msg

def test_group_validation_error():
    detail_msg = "Invalid group data."
    with pytest.raises(GroupValidationError) as excinfo:
        raise GroupValidationError(detail=detail_msg)
    assert excinfo.value.status_code == status.HTTP_400_BAD_REQUEST
    assert excinfo.value.detail == detail_msg

def test_item_not_found_error():
    item_id = 606
    with pytest.raises(ItemNotFoundError) as excinfo:
        raise ItemNotFoundError(item_id=item_id)
    assert excinfo.value.status_code == status.HTTP_404_NOT_FOUND
    assert excinfo.value.detail == f"Item {item_id} not found"

def test_user_not_found_error_no_identifier():
    with pytest.raises(UserNotFoundError) as excinfo:
        raise UserNotFoundError()
    assert excinfo.value.status_code == status.HTTP_404_NOT_FOUND
    assert excinfo.value.detail == "User not found."

def test_user_not_found_error_with_id():
    user_id = 707
    with pytest.raises(UserNotFoundError) as excinfo:
        raise UserNotFoundError(user_id=user_id)
    assert excinfo.value.status_code == status.HTTP_404_NOT_FOUND
    assert excinfo.value.detail == f"User with ID {user_id} not found."

def test_user_not_found_error_with_identifier_string():
    identifier = "test_user"
    with pytest.raises(UserNotFoundError) as excinfo:
        raise UserNotFoundError(identifier=identifier)
    assert excinfo.value.status_code == status.HTTP_404_NOT_FOUND
    assert excinfo.value.detail == f"User with identifier '{identifier}' not found."

def test_invalid_operation_error():
    detail_msg = "This operation is not allowed."
    with pytest.raises(InvalidOperationError) as excinfo:
        raise InvalidOperationError(detail=detail_msg)
    assert excinfo.value.status_code == status.HTTP_400_BAD_REQUEST
    assert excinfo.value.detail == detail_msg

def test_invalid_operation_error_custom_status():
    detail_msg = "This operation is forbidden."
    custom_status = status.HTTP_403_FORBIDDEN
    with pytest.raises(InvalidOperationError) as excinfo:
        raise InvalidOperationError(detail=detail_msg, status_code=custom_status)
    assert excinfo.value.status_code == custom_status
    assert excinfo.value.detail == detail_msg

def test_email_already_registered_error():
    with pytest.raises(EmailAlreadyRegisteredError) as excinfo:
        raise EmailAlreadyRegisteredError()
    assert excinfo.value.status_code == status.HTTP_400_BAD_REQUEST
    assert excinfo.value.detail == "Email already registered."

def test_user_creation_error():
    with pytest.raises(UserCreationError) as excinfo:
        raise UserCreationError()
    assert excinfo.value.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
    assert excinfo.value.detail == "An error occurred during user creation."

def test_invite_not_found_error():
    invite_code = "TESTCODE123"
    with pytest.raises(InviteNotFoundError) as excinfo:
        raise InviteNotFoundError(invite_code=invite_code)
    assert excinfo.value.status_code == status.HTTP_404_NOT_FOUND
    assert excinfo.value.detail == f"Invite code {invite_code} not found"

def test_invite_expired_error():
    invite_code = "EXPIREDCODE"
    with pytest.raises(InviteExpiredError) as excinfo:
        raise InviteExpiredError(invite_code=invite_code)
    assert excinfo.value.status_code == status.HTTP_410_GONE
    assert excinfo.value.detail == f"Invite code {invite_code} has expired"

def test_invite_already_used_error():
    invite_code = "USEDCODE"
    with pytest.raises(InviteAlreadyUsedError) as excinfo:
        raise InviteAlreadyUsedError(invite_code=invite_code)
    assert excinfo.value.status_code == status.HTTP_410_GONE
    assert excinfo.value.detail == f"Invite code {invite_code} has already been used"

def test_invite_creation_error():
    group_id = 909
    with pytest.raises(InviteCreationError) as excinfo:
        raise InviteCreationError(group_id=group_id)
    assert excinfo.value.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
    assert excinfo.value.detail == f"Failed to create invite for group {group_id}"

def test_list_status_not_found_error():
    list_id = 808
    with pytest.raises(ListStatusNotFoundError) as excinfo:
        raise ListStatusNotFoundError(list_id=list_id)
    assert excinfo.value.status_code == status.HTTP_404_NOT_FOUND
    assert excinfo.value.detail == f"Status for list {list_id} not found"

def test_conflict_error():
    detail_msg = "Resource version mismatch."
    with pytest.raises(ConflictError) as excinfo:
        raise ConflictError(detail=detail_msg)
    assert excinfo.value.status_code == status.HTTP_409_CONFLICT
    assert excinfo.value.detail == detail_msg
