"""Views for standingsmanager."""

import csv
import json

from django.contrib.auth.decorators import login_required, permission_required
from django.core.exceptions import ValidationError
from django.db import IntegrityError
from django.http import HttpResponse, JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone
from django.views.decorators.http import require_http_methods
from esi.decorators import token_required

from allianceauth.authentication.models import CharacterOwnership
from allianceauth.eveonline.models import EveCharacter, EveCorporationInfo
from allianceauth.services.hooks import get_extension_logger
from app_utils.logging import LoggerAddTag

from . import __title__, tasks
from .app_settings import STANDINGS_LABEL_NAME
from .models import (
    EveEntity,
    StandingRequest,
    StandingRevocation,
    StandingsEntry,
    SyncedCharacter,
)
from .validators import (
    can_user_request_character_standing,
    can_user_request_corporation_standing,
    get_required_scopes_for_user,
    validate_corporation_token_coverage,
)

logger = LoggerAddTag(get_extension_logger(__name__), __title__)


def common_context(ctx: dict) -> dict:
    """Return common context used by several views."""
    result = {
        "app_title": __title__,
        "page_title": "PLACEHOLDER",
        "label_name": STANDINGS_LABEL_NAME,
    }
    result.update(ctx)
    return result


# ============================================================================
# Main Navigation Views
# ============================================================================


@login_required
@permission_required("standingsmanager.add_syncedcharacter")
def index(request):
    """Render index page - redirect to request standings."""
    return redirect("standingsmanager:request_standings")


@login_required
@permission_required("standingsmanager.add_syncedcharacter")
@token_required(scopes=SyncedCharacter.get_esi_scopes(), new=True)
def add_scopes(request, token):
    """
    View that triggers EVE OAuth with required scopes.

    Uses token_required decorator with new=True which will:
    1. Always redirect to EVE SSO to get a fresh token with required scopes
    2. After successful auth, redirect back here with the new token
    3. Then redirect to the request standings page

    The token parameter is provided by the decorator after successful auth.
    """
    # Log token info for debugging
    logger.info(
        f"Token added for character_id={token.character_id}, "
        f"character_name={token.character_name}, "
        f"scopes={list(token.scopes.values_list('name', flat=True))}"
    )
    # Token was successfully added/updated with required scopes
    # Redirect back to the request standings page
    return redirect("standingsmanager:request_standings")


# ============================================================================
# User Views - Request Standings
# ============================================================================


@login_required
@permission_required("standingsmanager.add_syncedcharacter")
def request_standings(request):
    """
    View for users to request standings for their characters and corporations.

    Shows all user's characters with their status:
    - Already has standing
    - Pending request
    - Can request standing
    - Cannot request (missing scopes, etc.)
    """
    user = request.user

    # Get all user's characters
    character_ownerships = CharacterOwnership.objects.filter(user=user).select_related(
        "character"
    )

    characters_data = []
    corporations_data = {}

    # Get required scopes for this user
    required_scopes = get_required_scopes_for_user(user)

    # Pre-fetch all character IDs for bulk queries
    character_ids = [co.character.character_id for co in character_ownerships]

    # Bulk fetch all entities for these characters
    character_entities = {
        e.id: e
        for e in EveEntity.objects.filter(
            id__in=character_ids, category=EveEntity.CATEGORY_CHARACTER
        )
    }

    # Bulk fetch standings for all character entities
    entity_ids_with_standings = set(
        StandingsEntry.objects.filter(
            eve_entity_id__in=character_entities.keys()
        ).values_list("eve_entity_id", flat=True)
    )

    # Bulk fetch pending requests for all character entities
    entity_ids_with_pending = set(
        StandingRequest.objects.filter(
            eve_entity_id__in=character_entities.keys(),
            state=StandingRequest.State.PENDING,
        ).values_list("eve_entity_id", flat=True)
    )

    # Bulk fetch all valid tokens for this user with scopes
    from esi.models import Token

    user_tokens = list(
        Token.objects.filter(user=user, character_id__in=character_ids)
        .require_valid()
        .prefetch_related("scopes")
    )

    # Build a map of character_id -> set of scopes
    character_scopes = {}
    for token in user_tokens:
        if token.character_id not in character_scopes:
            character_scopes[token.character_id] = set()
        character_scopes[token.character_id].update(
            scope.name for scope in token.scopes.all()
        )

    required_scopes_set = set(required_scopes)

    for co in character_ownerships:
        character = co.character
        character_id = character.character_id

        # Check if character has standing (using pre-fetched data)
        has_standing = character_id in entity_ids_with_standings

        # Check if there's a pending request (using pre-fetched data)
        pending_request = character_id in entity_ids_with_pending

        # Check scopes (using pre-fetched data)
        token_scopes = character_scopes.get(character_id, set())
        missing_scopes = list(required_scopes_set - token_scopes)
        has_scopes = len(missing_scopes) == 0

        # Determine eligibility and status
        if has_standing:
            status = "approved"
            status_text = "Approved"
            can_request = False
            can_remove = True
            error_message = None
        elif pending_request:
            status = "pending"
            status_text = "Pending Approval"
            can_request = False
            can_remove = False
            error_message = None
        elif not has_scopes:
            status = "cannot_request"
            scope_list = ", ".join(missing_scopes)
            status_text = "Missing scopes"
            can_request = False
            can_remove = False
            error_message = f"Missing required scopes: {scope_list}"
        else:
            status = "can_request"
            status_text = "Can Request"
            can_request = True
            can_remove = False
            error_message = None

        character_data = {
            "id": character_id,
            "name": character.character_name,
            "portrait_url": character.portrait_url(),
            "corporation_name": character.corporation_name,
            "corporation_id": character.corporation_id,
            "corporation_ticker": character.corporation_ticker,
            "alliance_name": character.alliance_name or "",
            "alliance_ticker": character.alliance_ticker or "",
            "status": status,
            "status_text": status_text,
            "can_request": can_request,
            "can_remove": can_remove,
            "has_scopes": has_scopes,
            "missing_scopes": missing_scopes,
            "error_message": error_message,
        }
        characters_data.append(character_data)

        # Track corporations for corp-level requests
        corp_id = character.corporation_id
        if corp_id not in corporations_data:
            corporations_data[corp_id] = {
                "id": corp_id,
                "name": character.corporation_name,
                "ticker": character.corporation_ticker,
                "logo_url": f"https://images.evetech.net/corporations/{corp_id}/logo?size=64",
                "alliance_name": character.alliance_name or "",
                "characters": [],
                "character_count": 0,
            }
        corporations_data[corp_id]["characters"].append(character_data)
        corporations_data[corp_id]["character_count"] += 1

    # Process corporation data
    corporations_list = []

    # Bulk fetch corporation entities
    corp_ids = list(corporations_data.keys())
    corp_entities = {
        e.id: e
        for e in EveEntity.objects.filter(
            id__in=corp_ids, category=EveEntity.CATEGORY_CORPORATION
        )
    }

    # Bulk fetch standings for corporations
    corp_ids_with_standings = set(
        StandingsEntry.objects.filter(
            eve_entity_id__in=corp_entities.keys()
        ).values_list("eve_entity_id", flat=True)
    )

    # Bulk fetch pending requests for corporations
    corp_ids_with_pending = set(
        StandingRequest.objects.filter(
            eve_entity_id__in=corp_entities.keys(), state=StandingRequest.State.PENDING
        ).values_list("eve_entity_id", flat=True)
    )

    # Bulk fetch EveCorporationInfo
    corp_infos = {
        c.corporation_id: c
        for c in EveCorporationInfo.objects.filter(corporation_id__in=corp_ids)
    }

    for corp_data in corporations_data.values():
        corp_id = corp_data["id"]

        # Check if corporation has standing (using pre-fetched data)
        has_standing = corp_id in corp_ids_with_standings

        # Check if there's a pending request (using pre-fetched data)
        pending_request = corp_id in corp_ids_with_pending

        # Get or create corporation info
        corp_info = corp_infos.get(corp_id)
        if not corp_info:
            # Create corporation info if it doesn't exist
            # Handle race condition where another process may have created it
            try:
                corp_info = EveCorporationInfo.objects.create_corporation(corp_id)
            except IntegrityError:
                # Another process created it, fetch it
                corp_info = EveCorporationInfo.objects.get(corporation_id=corp_id)

        # Check token coverage for all corp members
        has_full_coverage, missing_characters = validate_corporation_token_coverage(
            corp_info, user
        )

        # Get actual member count from corp info
        actual_member_count = corp_info.member_count
        registered_count = EveCharacter.objects.filter(
            corporation_id=corp_id,
            character_ownership__isnull=False,
        ).count()

        # Determine eligibility and status
        if has_standing:
            status = "approved"
            status_text = "Approved"
            can_request = False
            can_remove = True
            error_message = None
        elif pending_request:
            status = "pending"
            status_text = "Pending Approval"
            can_request = False
            can_remove = False
            error_message = None
        elif not has_full_coverage:
            status = "cannot_request"
            char_list = ", ".join(missing_characters)
            status_text = "Incomplete"
            can_request = False
            can_remove = False
            error_message = f"Missing: {char_list}"
        else:
            status = "can_request"
            status_text = "Can Request"
            can_request = True
            can_remove = False
            error_message = None

        corp_data.update(
            {
                "status": status,
                "status_text": status_text,
                "can_request": can_request,
                "can_remove": can_remove,
                "has_full_coverage": has_full_coverage,
                "missing_characters": missing_characters,
                "error_message": error_message,
                "actual_member_count": actual_member_count,
                "registered_count": registered_count,
            }
        )
        corporations_list.append(corp_data)

    context = {
        "page_title": "Request Standings",
        "characters": characters_data,
        "corporations": corporations_list,
        "required_scopes": required_scopes,
    }

    return render(request, "standingsmanager/request.html", common_context(context))


# ============================================================================
# User Views - My Synced Characters
# ============================================================================


@login_required
@permission_required("standingsmanager.add_syncedcharacter")
def my_synced_characters(request):
    """
    View for users to manage their synced characters.

    Shows all user's characters and their sync status.
    """
    user = request.user

    # Get all user's characters
    character_ownerships = CharacterOwnership.objects.filter(user=user).select_related(
        "character"
    )

    characters_data = []

    for co in character_ownerships:
        character = co.character
        character_id = character.character_id

        # Check if character is synced
        try:
            synced_char = SyncedCharacter.objects.get(character_ownership=co)
            is_synced = True
            has_label = synced_char.has_label
            last_sync_at = synced_char.last_sync_at
            last_error = synced_char.last_error
            is_fresh = synced_char.is_sync_fresh

            # Determine sync status
            if last_error:
                sync_status = "error"
                sync_status_text = f"Error: {last_error}"
            elif not has_label:
                sync_status = "no_label"
                sync_status_text = f"Missing label: {STANDINGS_LABEL_NAME}"
            elif is_fresh:
                sync_status = "fresh"
                sync_status_text = "Synced"
            else:
                sync_status = "stale"
                sync_status_text = "Needs sync"

        except SyncedCharacter.DoesNotExist:
            is_synced = False
            has_label = None
            last_sync_at = None
            last_error = None
            sync_status = "not_synced"
            sync_status_text = "Not synced"

        # Check if character has standing (required for sync)
        try:
            entity = EveEntity.objects.get(
                id=character_id, category=EveEntity.CATEGORY_CHARACTER
            )
            has_standing = StandingsEntry.objects.filter(eve_entity=entity).exists()
        except EveEntity.DoesNotExist:
            has_standing = False

        character_data = {
            "id": character_id,
            "name": character.character_name,
            "portrait_url": character.portrait_url(),
            "corporation_name": character.corporation_name,
            "corporation_ticker": character.corporation_ticker,
            "alliance_name": character.alliance_name or "",
            "is_synced": is_synced,
            "has_label": has_label,
            "last_sync_at": last_sync_at,
            "last_error": last_error,
            "sync_status": sync_status,
            "sync_status_text": sync_status_text,
            "has_standing": has_standing,
            "can_add_sync": has_standing and not is_synced,
            "can_remove_sync": is_synced,
            "synced_char_pk": synced_char.pk if is_synced else None,
        }
        characters_data.append(character_data)

    context = {
        "page_title": "My Synced Characters",
        "characters": characters_data,
        "label_name": STANDINGS_LABEL_NAME,
    }

    return render(request, "standingsmanager/sync.html", common_context(context))


# ============================================================================
# Approver Views - Manage Requests
# ============================================================================


@login_required
@permission_required("standingsmanager.approve_standings")
def manage_requests(request):
    """
    View for approvers to manage pending standing requests.

    Shows all pending requests with details about the requester.
    """
    # Get all pending requests
    pending_requests = (
        StandingRequest.objects.filter(state=StandingRequest.State.PENDING)
        .select_related("eve_entity", "requested_by")
        .order_by("-request_date")
    )

    requests_data = []
    for req in pending_requests:
        entity = req.eve_entity
        requester = req.requested_by

        # Get entity details
        entity_name = entity.name
        entity_id = entity.id
        entity_type = req.entity_type

        # Get requester main character
        main_char = requester.profile.main_character if requester.profile else None

        request_data = {
            "pk": req.pk,
            "entity_id": entity_id,
            "entity_name": entity_name,
            "entity_type": entity_type,
            "entity_type_display": req.get_entity_type_display(),
            "requester_name": requester.username,
            "requester_main": main_char.character_name if main_char else "Unknown",
            "requester_main_corporation": (
                main_char.corporation_name if main_char else ""
            ),
            "requester_main_alliance": main_char.alliance_name if main_char else "",
            "request_date": req.request_date,
            "age_days": (timezone.now() - req.request_date).days,
        }

        # Add entity-specific details
        if entity_type == StandingsEntry.EntityType.CHARACTER:
            request_data["portrait_url"] = (
                f"https://images.evetech.net/characters/{entity_id}/portrait?size=64"
            )
        elif entity_type == StandingsEntry.EntityType.CORPORATION:
            request_data["logo_url"] = (
                f"https://images.evetech.net/corporations/{entity_id}/logo?size=64"
            )
        elif entity_type == StandingsEntry.EntityType.ALLIANCE:
            request_data["logo_url"] = (
                f"https://images.evetech.net/alliances/{entity_id}/logo?size=64"
            )

        requests_data.append(request_data)

    context = {
        "page_title": "Manage Standing Requests",
        "requests": requests_data,
        "request_count": len(requests_data),
    }

    return render(
        request, "standingsmanager/manage_requests.html", common_context(context)
    )


@login_required
@permission_required("standingsmanager.approve_standings")
def manage_revocations(request):
    """
    View for approvers to manage pending standing revocations.

    Shows all pending revocations with details about the requester.
    """
    # Get all pending revocations
    pending_revocations = (
        StandingRevocation.objects.filter(state=StandingRevocation.State.PENDING)
        .select_related("eve_entity", "requested_by")
        .order_by("-request_date")
    )

    revocations_data = []
    for rev in pending_revocations:
        entity = rev.eve_entity
        requester = rev.requested_by

        # Get entity details
        entity_name = entity.name
        entity_id = entity.id
        entity_type = rev.entity_type

        # Handle auto-revocations (system-initiated)
        if requester is None:
            requester_name = "System (Auto)"
            requester_main = "N/A"
            requester_main_corporation = ""
            requester_main_alliance = ""
        else:
            requester_name = requester.username
            main_char = requester.profile.main_character if requester.profile else None
            requester_main = main_char.character_name if main_char else "Unknown"
            requester_main_corporation = main_char.corporation_name if main_char else ""
            requester_main_alliance = main_char.alliance_name if main_char else ""

        revocation_data = {
            "pk": rev.pk,
            "entity_id": entity_id,
            "entity_name": entity_name,
            "entity_type": entity_type,
            "entity_type_display": rev.get_entity_type_display(),
            "requester_name": requester_name,
            "requester_main": requester_main,
            "requester_main_corporation": requester_main_corporation,
            "requester_main_alliance": requester_main_alliance,
            "request_date": rev.request_date,
            "reason": rev.get_reason_display(),
            "age_days": (timezone.now() - rev.request_date).days,
            "is_auto": requester is None,
        }

        # Add entity-specific details
        if entity_type == StandingsEntry.EntityType.CHARACTER:
            revocation_data["portrait_url"] = (
                f"https://images.evetech.net/characters/{entity_id}/portrait?size=64"
            )
        elif entity_type == StandingsEntry.EntityType.CORPORATION:
            revocation_data["logo_url"] = (
                f"https://images.evetech.net/corporations/{entity_id}/logo?size=64"
            )
        elif entity_type == StandingsEntry.EntityType.ALLIANCE:
            revocation_data["logo_url"] = (
                f"https://images.evetech.net/alliances/{entity_id}/logo?size=64"
            )

        revocations_data.append(revocation_data)

    context = {
        "page_title": "Manage Standing Revocations",
        "revocations": revocations_data,
        "revocation_count": len(revocations_data),
    }

    return render(
        request, "standingsmanager/manage_revocations.html", common_context(context)
    )


# ============================================================================
# Approver Views - View Standings
# ============================================================================


@login_required
@permission_required("standingsmanager.approve_standings")
def view_standings(request):
    """
    View for approvers to view all current standings.

    Shows all standings entries grouped by type.
    """
    # Get all standings
    all_standings = StandingsEntry.objects.select_related(
        "eve_entity", "added_by"
    ).order_by("entity_type", "eve_entity__name")

    # Group by entity type
    characters = []
    corporations = []
    alliances = []

    for standing in all_standings:
        entity = standing.eve_entity
        added_by = standing.added_by

        # Get added_by information, handling None case
        if added_by:
            added_by_username = added_by.username
            main_char = added_by.profile.main_character if added_by.profile else None
            added_by_main = main_char.character_name if main_char else "Unknown"
        else:
            added_by_username = "Unknown"
            added_by_main = "Unknown"

        standing_data = {
            "entity_id": entity.id,
            "entity_name": entity.name,
            "entity_type": standing.entity_type,
            "standing": standing.standing,
            "added_by": added_by_username,
            "added_by_main": added_by_main,
            "added_date": standing.added_date,
            "notes": standing.notes,
        }

        # Add entity-specific details
        if standing.entity_type == StandingsEntry.EntityType.CHARACTER:
            standing_data["portrait_url"] = (
                f"https://images.evetech.net/characters/{entity.id}/portrait?size=64"
            )
            characters.append(standing_data)
        elif standing.entity_type == StandingsEntry.EntityType.CORPORATION:
            standing_data["logo_url"] = (
                f"https://images.evetech.net/corporations/{entity.id}/logo?size=64"
            )
            corporations.append(standing_data)
        elif standing.entity_type == StandingsEntry.EntityType.ALLIANCE:
            standing_data["logo_url"] = (
                f"https://images.evetech.net/alliances/{entity.id}/logo?size=64"
            )
            alliances.append(standing_data)

    context = {
        "page_title": "View Standings",
        "characters": characters,
        "corporations": corporations,
        "alliances": alliances,
        "total_count": len(all_standings),
        "character_count": len(characters),
        "corporation_count": len(corporations),
        "alliance_count": len(alliances),
    }

    return render(
        request, "standingsmanager/view_standings.html", common_context(context)
    )


# ============================================================================
# CSV Export
# ============================================================================


@login_required
@permission_required("standingsmanager.approve_standings")
def export_standings_csv(request):
    """
    Export all standings to CSV format.
    """
    # Create the HttpResponse object with CSV header
    response = HttpResponse(content_type="text/csv")
    response["Content-Disposition"] = 'attachment; filename="standings_export.csv"'

    writer = csv.writer(response)
    writer.writerow(
        [
            "Entity Type",
            "Entity ID",
            "Entity Name",
            "Standing",
            "Requested By",
            "Added Date",
            "Notes",
        ]
    )

    # Get all standings
    all_standings = StandingsEntry.objects.select_related(
        "eve_entity", "added_by"
    ).order_by("entity_type", "eve_entity__name")

    for standing in all_standings:
        # Handle None case for added_by
        added_by_username = (
            standing.added_by.username if standing.added_by else "Unknown"
        )

        writer.writerow(
            [
                standing.get_entity_type_display(),
                standing.eve_entity.id,
                standing.eve_entity.name,
                standing.standing,
                added_by_username,
                standing.added_date.strftime("%Y-%m-%d %H:%M:%S"),
                standing.notes or "",
            ]
        )

    return response


# ============================================================================
# User API Endpoints
# ============================================================================


@login_required
@permission_required("standingsmanager.add_syncedcharacter")
@require_http_methods(["POST"])
def api_request_character_standing(request, character_id):
    """
    API endpoint to create a character standing request.

    Args:
        character_id: EVE character ID

    Returns:
        JSON response with success/error status
    """
    try:
        # Get character
        character = get_object_or_404(EveCharacter, character_id=character_id)

        # Check if user owns character
        if not CharacterOwnership.objects.filter(
            user=request.user, character=character
        ).exists():
            return JsonResponse(
                {"success": False, "error": "You do not own this character."},
                status=403,
            )

        # Check eligibility
        can_request, error_message = can_user_request_character_standing(
            character, request.user
        )
        if not can_request:
            return JsonResponse({"success": False, "error": error_message}, status=400)

        # Create request
        standing_request = StandingRequest.objects.create_character_request(
            character, request.user
        )

        logger.info(
            f"User {request.user.username} created standing request for character {character.character_name}"
        )

        return JsonResponse(
            {
                "success": True,
                "message": f"Standing request created for {character.character_name}",
                "request_pk": standing_request.pk,
            }
        )

    except Exception as e:
        logger.exception(f"Error creating character standing request: {e}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )


@login_required
@permission_required("standingsmanager.add_syncedcharacter")
@require_http_methods(["POST"])
def api_request_corporation_standing(request, corporation_id):
    """
    API endpoint to create a corporation standing request.

    Args:
        corporation_id: EVE corporation ID

    Returns:
        JSON response with success/error status
    """
    try:
        # Get corporation
        try:
            corporation = EveCorporationInfo.objects.get(corporation_id=corporation_id)
        except EveCorporationInfo.DoesNotExist:
            # Handle race condition where another process may have created it
            try:
                corporation = EveCorporationInfo.objects.create_corporation(
                    corporation_id
                )
            except IntegrityError:
                # Another process created it, fetch it
                corporation = EveCorporationInfo.objects.get(
                    corporation_id=corporation_id
                )

        # Check eligibility
        can_request, error_message = can_user_request_corporation_standing(
            corporation, request.user
        )
        if not can_request:
            return JsonResponse({"success": False, "error": error_message}, status=400)

        # Create request
        standing_request = StandingRequest.objects.create_corporation_request(
            corporation, request.user
        )

        logger.info(
            f"User {request.user.username} created standing request for corporation {corporation.corporation_name}"
        )

        return JsonResponse(
            {
                "success": True,
                "message": f"Standing request created for {corporation.corporation_name}",
                "request_pk": standing_request.pk,
            }
        )

    except Exception as e:
        logger.exception(f"Error creating corporation standing request: {e}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )


@login_required
@permission_required("standingsmanager.add_syncedcharacter")
@require_http_methods(["POST"])
def api_remove_standing(request, entity_id):
    """
    API endpoint to create a revocation request for a standing.

    Args:
        entity_id: EVE entity ID (character, corp, or alliance)

    Returns:
        JSON response with success/error status
    """
    try:
        # Find entity
        try:
            entity = EveEntity.objects.get(id=entity_id)
        except EveEntity.DoesNotExist:
            return JsonResponse(
                {"success": False, "error": "Entity not found."}, status=404
            )

        # Check if standing exists
        if not StandingsEntry.objects.filter(eve_entity=entity).exists():
            return JsonResponse(
                {"success": False, "error": "No standing exists for this entity."},
                status=404,
            )

        # Check if user owns this entity
        # For characters, verify ownership
        if entity.category == EveEntity.CATEGORY_CHARACTER:
            try:
                CharacterOwnership.objects.get(
                    user=request.user, character__character_id=entity_id
                )
            except CharacterOwnership.DoesNotExist:
                return JsonResponse(
                    {
                        "success": False,
                        "error": "You can only request removal of your own standings.",
                    },
                    status=403,
                )

        # Create revocation
        try:
            revocation = StandingRevocation.objects.create_for_entity(
                entity,
                reason=StandingRevocation.RevocationReason.USER_REQUEST,
                user=request.user,
            )
        except ValidationError as e:
            # Handle Django ValidationError message extraction
            if hasattr(e, "messages") and e.messages:
                error_msg = str(e.messages[0])
            elif hasattr(e, "message"):
                error_msg = str(e.message)
            else:
                error_msg = str(e)
            logger.warning(
                f"Validation error creating revocation for {entity.name}: {error_msg}"
            )
            return JsonResponse(
                {"success": False, "error": error_msg},
                status=400,
            )

        logger.info(
            f"User {request.user.username} created revocation request for {entity.name}"
        )

        return JsonResponse(
            {
                "success": True,
                "message": f"Revocation request created for {entity.name}",
                "revocation_pk": revocation.pk,
            }
        )

    except Exception:
        logger.exception(f"Error creating revocation request for entity_id={entity_id}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )


@login_required
@permission_required("standingsmanager.add_syncedcharacter")
@require_http_methods(["POST"])
def api_bulk_request_character_standings(request):
    """
    API endpoint to create standing requests for multiple characters.

    Expects JSON body with:
        character_ids: list of EVE character IDs

    Returns:
        JSON response with success/error status and details for each character
    """
    try:
        # Parse JSON body
        try:
            data = json.loads(request.body)
            character_ids = data.get("character_ids", [])
        except json.JSONDecodeError:
            return JsonResponse(
                {"success": False, "error": "Invalid JSON body."}, status=400
            )

        if not character_ids:
            return JsonResponse(
                {"success": False, "error": "No characters specified."}, status=400
            )

        results = []
        success_count = 0
        error_count = 0

        for character_id in character_ids:
            try:
                # Get character
                try:
                    character = EveCharacter.objects.get(character_id=character_id)
                except EveCharacter.DoesNotExist:
                    results.append(
                        {
                            "character_id": character_id,
                            "success": False,
                            "error": "Character not found.",
                        }
                    )
                    error_count += 1
                    continue

                # Check if user owns character
                if not CharacterOwnership.objects.filter(
                    user=request.user, character=character
                ).exists():
                    results.append(
                        {
                            "character_id": character_id,
                            "character_name": character.character_name,
                            "success": False,
                            "error": "You do not own this character.",
                        }
                    )
                    error_count += 1
                    continue

                # Check eligibility
                can_request, error_message = can_user_request_character_standing(
                    character, request.user
                )
                if not can_request:
                    results.append(
                        {
                            "character_id": character_id,
                            "character_name": character.character_name,
                            "success": False,
                            "error": error_message,
                        }
                    )
                    error_count += 1
                    continue

                # Create request
                standing_request = StandingRequest.objects.create_character_request(
                    character, request.user
                )

                logger.info(
                    f"User {request.user.username} created standing request "
                    f"for character {character.character_name}"
                )

                results.append(
                    {
                        "character_id": character_id,
                        "character_name": character.character_name,
                        "success": True,
                        "request_pk": standing_request.pk,
                    }
                )
                success_count += 1

            except Exception as e:
                logger.exception(
                    f"Error creating standing request for character {character_id}: {e}"
                )
                results.append(
                    {
                        "character_id": character_id,
                        "success": False,
                        "error": "An unexpected error occurred.",
                    }
                )
                error_count += 1

        message = f"Requested standings for {success_count} character(s)"
        if error_count > 0:
            message += f", {error_count} failed"

        return JsonResponse(
            {
                "success": error_count == 0,
                "message": message,
                "results": results,
                "success_count": success_count,
                "error_count": error_count,
            }
        )

    except Exception as e:
        logger.exception(f"Error in bulk character standing request: {e}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )


@login_required
@permission_required("standingsmanager.add_syncedcharacter")
@require_http_methods(["POST"])
def api_bulk_remove_standings(request):
    """
    API endpoint to create revocation requests for multiple entities.

    Expects JSON body with:
        entity_ids: list of EVE entity IDs (characters)

    Returns:
        JSON response with success/error status and details for each entity
    """
    try:
        # Parse JSON body
        try:
            data = json.loads(request.body)
            entity_ids = data.get("entity_ids", [])
        except json.JSONDecodeError:
            return JsonResponse(
                {"success": False, "error": "Invalid JSON body."}, status=400
            )

        if not entity_ids:
            return JsonResponse(
                {"success": False, "error": "No entities specified."}, status=400
            )

        results = []
        success_count = 0
        error_count = 0

        for entity_id in entity_ids:
            try:
                # Find entity
                try:
                    entity = EveEntity.objects.get(id=entity_id)
                except EveEntity.DoesNotExist:
                    results.append(
                        {
                            "entity_id": entity_id,
                            "success": False,
                            "error": "Entity not found.",
                        }
                    )
                    error_count += 1
                    continue

                # Check if standing exists
                if not StandingsEntry.objects.filter(eve_entity=entity).exists():
                    results.append(
                        {
                            "entity_id": entity_id,
                            "entity_name": entity.name,
                            "success": False,
                            "error": "No standing exists for this entity.",
                        }
                    )
                    error_count += 1
                    continue

                # Check if user owns this entity (for characters)
                if entity.category == EveEntity.CATEGORY_CHARACTER:
                    try:
                        CharacterOwnership.objects.get(
                            user=request.user, character__character_id=entity_id
                        )
                    except CharacterOwnership.DoesNotExist:
                        results.append(
                            {
                                "entity_id": entity_id,
                                "entity_name": entity.name,
                                "success": False,
                                "error": "You can only request removal of your own standings.",
                            }
                        )
                        error_count += 1
                        continue

                # Create revocation
                try:
                    revocation = StandingRevocation.objects.create_for_entity(
                        entity,
                        reason=StandingRevocation.RevocationReason.USER_REQUEST,
                        user=request.user,
                    )
                except ValidationError as e:
                    # Handle Django ValidationError message extraction
                    if hasattr(e, "messages") and e.messages:
                        error_msg = str(e.messages[0])
                    elif hasattr(e, "message"):
                        error_msg = str(e.message)
                    else:
                        error_msg = str(e)
                    results.append(
                        {
                            "entity_id": entity_id,
                            "entity_name": entity.name,
                            "success": False,
                            "error": error_msg,
                        }
                    )
                    error_count += 1
                    continue

                logger.info(
                    f"User {request.user.username} created revocation request "
                    f"for {entity.name}"
                )

                results.append(
                    {
                        "entity_id": entity_id,
                        "entity_name": entity.name,
                        "success": True,
                        "revocation_pk": revocation.pk,
                    }
                )
                success_count += 1

            except Exception as e:
                logger.exception(
                    f"Error creating revocation request for entity {entity_id}: {e}"
                )
                results.append(
                    {
                        "entity_id": entity_id,
                        "success": False,
                        "error": "An unexpected error occurred.",
                    }
                )
                error_count += 1

        message = f"Requested revocation for {success_count} entity(ies)"
        if error_count > 0:
            message += f", {error_count} failed"

        return JsonResponse(
            {
                "success": error_count == 0,
                "message": message,
                "results": results,
                "success_count": success_count,
                "error_count": error_count,
            }
        )

    except Exception as e:
        logger.exception(f"Error in bulk revocation request: {e}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )


@login_required
@permission_required("standingsmanager.add_syncedcharacter")
@require_http_methods(["POST"])
def api_add_character_to_sync(request, character_id):
    """
    API endpoint to add a character to sync.

    Args:
        character_id: EVE character ID

    Returns:
        JSON response with success/error status
    """
    try:
        # Get character
        character = get_object_or_404(EveCharacter, character_id=character_id)

        # Check if user owns character
        try:
            character_ownership = CharacterOwnership.objects.get(
                user=request.user, character=character
            )
        except CharacterOwnership.DoesNotExist:
            return JsonResponse(
                {"success": False, "error": "You do not own this character."},
                status=403,
            )

        # Check if character has standing
        try:
            entity = EveEntity.objects.get(
                id=character_id, category=EveEntity.CATEGORY_CHARACTER
            )
            has_standing = StandingsEntry.objects.filter(eve_entity=entity).exists()
        except EveEntity.DoesNotExist:
            has_standing = False

        if not has_standing:
            return JsonResponse(
                {
                    "success": False,
                    "error": "Character must have an approved standing before adding to sync.",
                },
                status=400,
            )

        # Check if already synced
        if SyncedCharacter.objects.filter(
            character_ownership=character_ownership
        ).exists():
            return JsonResponse(
                {"success": False, "error": "Character is already synced."}, status=400
            )

        # Create synced character
        synced_char = SyncedCharacter.objects.create(
            character_ownership=character_ownership
        )

        # Trigger initial sync
        tasks.sync_character.delay(synced_char.pk)

        logger.info(
            f"User {request.user.username} added character {character.character_name} to sync"
        )

        return JsonResponse(
            {
                "success": True,
                "message": f"{character.character_name} added to sync",
                "synced_char_pk": synced_char.pk,
            }
        )

    except Exception as e:
        logger.exception(f"Error adding character to sync: {e}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )


@login_required
@permission_required("standingsmanager.add_syncedcharacter")
@require_http_methods(["POST"])
def api_remove_character_from_sync(request, synced_char_pk):
    """
    API endpoint to remove a character from sync.

    Args:
        synced_char_pk: SyncedCharacter primary key

    Returns:
        JSON response with success/error status
    """
    try:
        # Get synced character
        synced_char = get_object_or_404(SyncedCharacter, pk=synced_char_pk)

        # Verify ownership
        if synced_char.character_ownership.user != request.user:
            return JsonResponse(
                {
                    "success": False,
                    "error": "You do not own this synced character.",
                },
                status=403,
            )

        character_name = synced_char.character.character_name

        # Delete synced character
        synced_char.delete()

        logger.info(
            f"User {request.user.username} removed character {character_name} from sync"
        )

        return JsonResponse(
            {"success": True, "message": f"{character_name} removed from sync"}
        )

    except Exception as e:
        logger.exception(f"Error removing character from sync: {e}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )


@login_required
@permission_required("standingsmanager.add_syncedcharacter")
@require_http_methods(["POST"])
def api_bulk_add_to_sync(request):
    """
    API endpoint to add multiple characters to sync.

    Expects JSON body with:
        character_ids: list of EVE character IDs

    Returns:
        JSON response with success/error status and details for each character
    """
    try:
        # Parse JSON body
        try:
            data = json.loads(request.body)
            character_ids = data.get("character_ids", [])
        except json.JSONDecodeError:
            return JsonResponse(
                {"success": False, "error": "Invalid JSON body."}, status=400
            )

        if not character_ids:
            return JsonResponse(
                {"success": False, "error": "No characters specified."}, status=400
            )

        results = []
        success_count = 0
        error_count = 0

        for character_id in character_ids:
            try:
                # Get character
                try:
                    character = EveCharacter.objects.get(character_id=character_id)
                except EveCharacter.DoesNotExist:
                    results.append(
                        {
                            "character_id": character_id,
                            "success": False,
                            "error": "Character not found.",
                        }
                    )
                    error_count += 1
                    continue

                # Check if user owns character
                try:
                    character_ownership = CharacterOwnership.objects.get(
                        user=request.user, character=character
                    )
                except CharacterOwnership.DoesNotExist:
                    results.append(
                        {
                            "character_id": character_id,
                            "character_name": character.character_name,
                            "success": False,
                            "error": "You do not own this character.",
                        }
                    )
                    error_count += 1
                    continue

                # Check if character has standing
                try:
                    entity = EveEntity.objects.get(
                        id=character_id, category=EveEntity.CATEGORY_CHARACTER
                    )
                    has_standing = StandingsEntry.objects.filter(
                        eve_entity=entity
                    ).exists()
                except EveEntity.DoesNotExist:
                    has_standing = False

                if not has_standing:
                    results.append(
                        {
                            "character_id": character_id,
                            "character_name": character.character_name,
                            "success": False,
                            "error": "Character must have an approved standing.",
                        }
                    )
                    error_count += 1
                    continue

                # Check if already synced
                if SyncedCharacter.objects.filter(
                    character_ownership=character_ownership
                ).exists():
                    results.append(
                        {
                            "character_id": character_id,
                            "character_name": character.character_name,
                            "success": False,
                            "error": "Character is already synced.",
                        }
                    )
                    error_count += 1
                    continue

                # Create synced character
                synced_char = SyncedCharacter.objects.create(
                    character_ownership=character_ownership
                )

                # Trigger initial sync
                tasks.sync_character.delay(synced_char.pk)

                logger.info(
                    f"User {request.user.username} added character "
                    f"{character.character_name} to sync"
                )

                results.append(
                    {
                        "character_id": character_id,
                        "character_name": character.character_name,
                        "success": True,
                        "synced_char_pk": synced_char.pk,
                    }
                )
                success_count += 1

            except Exception as e:
                logger.exception(f"Error adding character {character_id} to sync: {e}")
                results.append(
                    {
                        "character_id": character_id,
                        "success": False,
                        "error": "An unexpected error occurred.",
                    }
                )
                error_count += 1

        message = f"Added {success_count} character(s) to sync"
        if error_count > 0:
            message += f", {error_count} failed"

        return JsonResponse(
            {
                "success": error_count == 0,
                "message": message,
                "results": results,
                "success_count": success_count,
                "error_count": error_count,
            }
        )

    except Exception as e:
        logger.exception(f"Error in bulk add to sync: {e}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )


@login_required
@permission_required("standingsmanager.add_syncedcharacter")
@require_http_methods(["POST"])
def api_bulk_remove_from_sync(request):
    """
    API endpoint to remove multiple characters from sync.

    Expects JSON body with:
        synced_char_pks: list of SyncedCharacter primary keys

    Returns:
        JSON response with success/error status and details for each character
    """
    try:
        # Parse JSON body
        try:
            data = json.loads(request.body)
            synced_char_pks = data.get("synced_char_pks", [])
        except json.JSONDecodeError:
            return JsonResponse(
                {"success": False, "error": "Invalid JSON body."}, status=400
            )

        if not synced_char_pks:
            return JsonResponse(
                {"success": False, "error": "No characters specified."}, status=400
            )

        results = []
        success_count = 0
        error_count = 0

        for synced_char_pk in synced_char_pks:
            try:
                # Get synced character
                try:
                    synced_char = SyncedCharacter.objects.get(pk=synced_char_pk)
                except SyncedCharacter.DoesNotExist:
                    results.append(
                        {
                            "synced_char_pk": synced_char_pk,
                            "success": False,
                            "error": "Synced character not found.",
                        }
                    )
                    error_count += 1
                    continue

                # Verify ownership
                if synced_char.character_ownership.user != request.user:
                    results.append(
                        {
                            "synced_char_pk": synced_char_pk,
                            "character_name": synced_char.character.character_name,
                            "success": False,
                            "error": "You do not own this synced character.",
                        }
                    )
                    error_count += 1
                    continue

                character_name = synced_char.character.character_name

                # Delete synced character
                synced_char.delete()

                logger.info(
                    f"User {request.user.username} removed character "
                    f"{character_name} from sync"
                )

                results.append(
                    {
                        "synced_char_pk": synced_char_pk,
                        "character_name": character_name,
                        "success": True,
                    }
                )
                success_count += 1

            except Exception as e:
                logger.exception(
                    f"Error removing synced character {synced_char_pk} from sync: {e}"
                )
                results.append(
                    {
                        "synced_char_pk": synced_char_pk,
                        "success": False,
                        "error": "An unexpected error occurred.",
                    }
                )
                error_count += 1

        message = f"Removed {success_count} character(s) from sync"
        if error_count > 0:
            message += f", {error_count} failed"

        return JsonResponse(
            {
                "success": error_count == 0,
                "message": message,
                "results": results,
                "success_count": success_count,
                "error_count": error_count,
            }
        )

    except Exception as e:
        logger.exception(f"Error in bulk remove from sync: {e}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )


# ============================================================================
# Approver API Endpoints
# ============================================================================


@login_required
@permission_required("standingsmanager.approve_standings")
@require_http_methods(["POST"])
def api_approve_request(request, request_pk):
    """
    API endpoint to approve a standing request.

    Args:
        request_pk: StandingRequest primary key

    Returns:
        JSON response with success/error status
    """
    try:
        # Get request
        standing_request = get_object_or_404(StandingRequest, pk=request_pk)

        # Check if still pending
        if standing_request.state != StandingRequest.State.PENDING:
            return JsonResponse(
                {"success": False, "error": "Request is not pending."}, status=400
            )

        # Approve request
        standing_request.approve(request.user)

        # Trigger sync for all synced characters
        tasks.trigger_sync_after_approval.delay()

        logger.info(
            f"User {request.user.username} approved standing request for {standing_request.eve_entity.name}"
        )

        return JsonResponse(
            {
                "success": True,
                "message": f"Standing request for {standing_request.eve_entity.name} approved",
            }
        )

    except Exception as e:
        logger.exception(f"Error approving standing request: {e}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )


@login_required
@permission_required("standingsmanager.approve_standings")
@require_http_methods(["POST"])
def api_reject_request(request, request_pk):
    """
    API endpoint to reject a standing request.

    Args:
        request_pk: StandingRequest primary key

    Returns:
        JSON response with success/error status
    """
    try:
        # Get request
        standing_request = get_object_or_404(StandingRequest, pk=request_pk)

        # Check if still pending
        if standing_request.state != StandingRequest.State.PENDING:
            return JsonResponse(
                {"success": False, "error": "Request is not pending."}, status=400
            )

        entity_name = standing_request.eve_entity.name

        # Reject request
        standing_request.reject(request.user)

        logger.info(
            f"User {request.user.username} rejected standing request for {entity_name}"
        )

        return JsonResponse(
            {"success": True, "message": f"Standing request for {entity_name} rejected"}
        )

    except Exception as e:
        logger.exception(f"Error rejecting standing request: {e}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )


@login_required
@permission_required("standingsmanager.approve_standings")
@require_http_methods(["POST"])
def api_approve_revocation(request, revocation_pk):
    """
    API endpoint to approve a standing revocation.

    Args:
        revocation_pk: StandingRevocation primary key

    Returns:
        JSON response with success/error status
    """
    try:
        # Get revocation
        revocation = get_object_or_404(StandingRevocation, pk=revocation_pk)

        # Check if still pending
        if revocation.state != StandingRevocation.State.PENDING:
            return JsonResponse(
                {"success": False, "error": "Revocation is not pending."}, status=400
            )

        # Approve revocation
        revocation.approve(request.user)

        # Trigger sync for all synced characters
        tasks.trigger_sync_after_revocation.delay()

        logger.info(
            f"User {request.user.username} approved standing revocation for {revocation.eve_entity.name}"
        )

        return JsonResponse(
            {
                "success": True,
                "message": f"Standing revocation for {revocation.eve_entity.name} approved",
            }
        )

    except Exception as e:
        logger.exception(f"Error approving standing revocation: {e}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )


@login_required
@permission_required("standingsmanager.approve_standings")
@require_http_methods(["POST"])
def api_reject_revocation(request, revocation_pk):
    """
    API endpoint to reject a standing revocation.

    Args:
        revocation_pk: StandingRevocation primary key

    Returns:
        JSON response with success/error status
    """
    try:
        # Get revocation
        revocation = get_object_or_404(StandingRevocation, pk=revocation_pk)

        # Check if still pending
        if revocation.state != StandingRevocation.State.PENDING:
            return JsonResponse(
                {"success": False, "error": "Revocation is not pending."}, status=400
            )

        entity_name = revocation.eve_entity.name

        # Reject revocation
        revocation.reject(request.user)

        logger.info(
            f"User {request.user.username} rejected standing revocation for {entity_name}"
        )

        return JsonResponse(
            {
                "success": True,
                "message": f"Standing revocation for {entity_name} rejected",
            }
        )

    except Exception as e:
        logger.exception(f"Error rejecting standing revocation: {e}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )


@login_required
@permission_required("standingsmanager.approve_standings")
@require_http_methods(["POST"])
def api_bulk_approve_requests(request):
    """
    API endpoint to approve multiple standing requests.

    Expects JSON body with:
        request_pks: list of StandingRequest primary keys

    Returns:
        JSON response with success/error status and details for each request
    """
    try:
        # Parse JSON body
        try:
            data = json.loads(request.body)
            request_pks = data.get("request_pks", [])
        except json.JSONDecodeError:
            return JsonResponse(
                {"success": False, "error": "Invalid JSON body."}, status=400
            )

        if not request_pks:
            return JsonResponse(
                {"success": False, "error": "No requests specified."}, status=400
            )

        results = []
        success_count = 0
        error_count = 0

        for request_pk in request_pks:
            try:
                # Get request
                try:
                    standing_request = StandingRequest.objects.get(pk=request_pk)
                except StandingRequest.DoesNotExist:
                    results.append(
                        {
                            "request_pk": request_pk,
                            "success": False,
                            "error": "Request not found.",
                        }
                    )
                    error_count += 1
                    continue

                # Check if still pending
                if standing_request.state != StandingRequest.State.PENDING:
                    results.append(
                        {
                            "request_pk": request_pk,
                            "entity_name": standing_request.eve_entity.name,
                            "success": False,
                            "error": "Request is not pending.",
                        }
                    )
                    error_count += 1
                    continue

                entity_name = standing_request.eve_entity.name

                # Approve request
                standing_request.approve(request.user)

                logger.info(
                    f"User {request.user.username} approved standing request "
                    f"for {entity_name}"
                )

                results.append(
                    {
                        "request_pk": request_pk,
                        "entity_name": entity_name,
                        "success": True,
                    }
                )
                success_count += 1

            except Exception as e:
                logger.exception(f"Error approving standing request {request_pk}: {e}")
                results.append(
                    {
                        "request_pk": request_pk,
                        "success": False,
                        "error": "An unexpected error occurred.",
                    }
                )
                error_count += 1

        # Trigger sync for all synced characters once after all approvals
        if success_count > 0:
            tasks.trigger_sync_after_approval.delay()

        message = f"Approved {success_count} request(s)"
        if error_count > 0:
            message += f", {error_count} failed"

        return JsonResponse(
            {
                "success": error_count == 0,
                "message": message,
                "results": results,
                "success_count": success_count,
                "error_count": error_count,
            }
        )

    except Exception as e:
        logger.exception(f"Error in bulk approve requests: {e}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )


@login_required
@permission_required("standingsmanager.approve_standings")
@require_http_methods(["POST"])
def api_bulk_reject_requests(request):
    """
    API endpoint to reject multiple standing requests.

    Expects JSON body with:
        request_pks: list of StandingRequest primary keys

    Returns:
        JSON response with success/error status and details for each request
    """
    try:
        # Parse JSON body
        try:
            data = json.loads(request.body)
            request_pks = data.get("request_pks", [])
        except json.JSONDecodeError:
            return JsonResponse(
                {"success": False, "error": "Invalid JSON body."}, status=400
            )

        if not request_pks:
            return JsonResponse(
                {"success": False, "error": "No requests specified."}, status=400
            )

        results = []
        success_count = 0
        error_count = 0

        for request_pk in request_pks:
            try:
                # Get request
                try:
                    standing_request = StandingRequest.objects.get(pk=request_pk)
                except StandingRequest.DoesNotExist:
                    results.append(
                        {
                            "request_pk": request_pk,
                            "success": False,
                            "error": "Request not found.",
                        }
                    )
                    error_count += 1
                    continue

                # Check if still pending
                if standing_request.state != StandingRequest.State.PENDING:
                    results.append(
                        {
                            "request_pk": request_pk,
                            "entity_name": standing_request.eve_entity.name,
                            "success": False,
                            "error": "Request is not pending.",
                        }
                    )
                    error_count += 1
                    continue

                entity_name = standing_request.eve_entity.name

                # Reject request
                standing_request.reject(request.user)

                logger.info(
                    f"User {request.user.username} rejected standing request "
                    f"for {entity_name}"
                )

                results.append(
                    {
                        "request_pk": request_pk,
                        "entity_name": entity_name,
                        "success": True,
                    }
                )
                success_count += 1

            except Exception as e:
                logger.exception(f"Error rejecting standing request {request_pk}: {e}")
                results.append(
                    {
                        "request_pk": request_pk,
                        "success": False,
                        "error": "An unexpected error occurred.",
                    }
                )
                error_count += 1

        message = f"Rejected {success_count} request(s)"
        if error_count > 0:
            message += f", {error_count} failed"

        return JsonResponse(
            {
                "success": error_count == 0,
                "message": message,
                "results": results,
                "success_count": success_count,
                "error_count": error_count,
            }
        )

    except Exception as e:
        logger.exception(f"Error in bulk reject requests: {e}")
        return JsonResponse(
            {"success": False, "error": "An unexpected error occurred."}, status=500
        )
