"""Platform admin JSON APIs (`/api/admin/...`) for dashboard, users, verification lists, and trip lifecycle."""

from datetime import datetime, timedelta
from decimal import Decimal

from django.conf import settings as django_settings
from django.contrib.auth import get_user_model
from django.db import transaction
from django.db.models import Count, Q, Sum
from django.utils import timezone
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated

from accounts.models import (
    KYCDocument,
    ShipperProfile,
    TransporterProfile,
    UserRole,
    Vehicle,
    VehicleDocument,
)
from billing.models import Payment
from billing.services import ensure_invoice_for_completed_trip
from core.models import AdminTripAction, Bid, Conversation, FreightRoute, Message, ProofOfDelivery, RateRequest, Shipment, Trip, TripLocation
from core.freight_import import bulk_upsert_freight_routes, parse_freight_route_upload
from core.countries import (
    COUNTRY_BY_CODE,
    COUNTRY_CHOICES,
    country_name_to_code,
    normalize_country_code,
)

from .notify import notify_users
from .permissions import IsPlatformAdmin
from .response import api_response
from .trip_status import record_trip_status
from .serializers import (
    AdminConversationDetailSerializer,
    AdminConversationListSerializer,
    AdminShipmentSerializer,
    FreightRouteSerializer,
    KYCDocumentSerializer,
    MessageSerializer,
    PODSerializer,
    RateRequestSerializer,
    TripDetailSerializer,
    TripListSerializer,
    TripLocationSerializer,
    VehicleDocumentSerializer,
    VehicleSerializer,
)
from .views import _sync_shipment_status_from_trip

User = get_user_model()


def _admin_sync_shipment_after_trip_override(trip, new_trip_status):
    """
    Apply the same shipment mapping as driver status updates, plus CLOSED trip -> CLOSED shipment
    (driver helper does not map CLOSED).
    """
    _sync_shipment_status_from_trip(trip, new_trip_status)
    if new_trip_status == Trip.Status.CLOSED:
        shipment = trip.shipment
        if shipment.status != Shipment.Status.CLOSED:
            shipment.status = Shipment.Status.CLOSED
            shipment.save(update_fields=['status', 'updated_at'])
    if new_trip_status == Trip.Status.COMPLETED:
        ensure_invoice_for_completed_trip(trip=trip)


def _parse_dt(value):
    if not value:
        return None
    if isinstance(value, datetime):
        return value if timezone.is_aware(value) else timezone.make_aware(value)
    try:
        dt = datetime.fromisoformat(str(value).replace('Z', '+00:00'))
        return dt if timezone.is_aware(dt) else timezone.make_aware(dt)
    except ValueError:
        return None


def _page_params(request):
    try:
        page = max(1, int(request.query_params.get('page', '1')))
    except ValueError:
        page = 1
    try:
        page_size = min(100, max(1, int(request.query_params.get('page_size', '20'))))
    except ValueError:
        page_size = 20
    return page, page_size


def _paginate(request, qs):
    page, page_size = _page_params(request)
    total = qs.count()
    start = (page - 1) * page_size
    return qs[start : start + page_size], {'page': page, 'page_size': page_size, 'total': total}


def _parse_bool_param(raw):
    if raw is None:
        return None
    s = str(raw).strip().lower()
    if s in ('1', 'true', 'yes', 'on'):
        return True
    if s in ('0', 'false', 'no', 'off'):
        return False
    return None


def _user_list_row(u):
    role = None
    try:
        role = u.role.role
    except UserRole.DoesNotExist:
        pass
    return {
        'id': u.id,
        'email': u.email,
        'username': u.username,
        'first_name': u.first_name,
        'last_name': u.last_name,
        'is_active': u.is_active,
        'is_staff': u.is_staff,
        'date_joined': u.date_joined,
        'role': role,
    }


def _user_detail_payload(user):
    row = _user_list_row(user)
    try:
        sp = user.shipper_profile
        row['shipper_profile'] = {
            'account_type': sp.account_type,
            'company_name': sp.company_name,
            'kyc_verified': sp.kyc_verified,
            'credit_approved': sp.credit_approved,
        }
    except ShipperProfile.DoesNotExist:
        row['shipper_profile'] = None
    try:
        tp = user.transporter_profile
        row['transporter_profile'] = {
            'account_type': tp.account_type,
            'company_name': tp.company_name,
            'documents_verified': tp.documents_verified,
        }
    except TransporterProfile.DoesNotExist:
        row['transporter_profile'] = None

    role = row.get('role')
    if role == UserRole.Role.SHIPPER:
        row['counts'] = {
            'shipments': Shipment.objects.filter(shipper=user).count(),
        }
        recent = Shipment.objects.filter(shipper=user).order_by('-id')[:10]
        row['recent_shipments'] = AdminShipmentSerializer(recent, many=True).data
    elif role == UserRole.Role.TRANSPORTER:
        row['counts'] = {
            'bids': Bid.objects.filter(transporter=user).count(),
            'trips': Trip.objects.filter(transporter=user).count(),
        }
        recent = Trip.objects.filter(transporter=user).select_related('shipment').order_by('-id')[:10]
        row['recent_trips'] = TripListSerializer(recent, many=True).data
    else:
        row['counts'] = {}
        row['recent_shipments'] = []
        row['recent_trips'] = []
    return row


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_dashboard(request):
    since = _parse_dt(request.query_params.get('since'))
    stale_hours = int(getattr(django_settings, 'ADMIN_STALE_TRIP_HOURS', 48) or 48)
    stale_cutoff = timezone.now() - timedelta(hours=stale_hours)

    trip_terminal = {Trip.Status.CLOSED, Trip.Status.COMPLETED}
    trip_active_q = ~Q(status__in=trip_terminal)
    active_trips = Trip.objects.filter(trip_active_q).count()

    stale_trips = Trip.objects.filter(
        status__in=[Trip.Status.EN_ROUTE, Trip.Status.IN_TRANSIT],
        updated_at__lt=stale_cutoff,
    ).count()

    trip_by_status = {
        row['status']: row['c']
        for row in Trip.objects.values('status').annotate(c=Count('id'))
    }
    shipment_by_status = {
        row['status']: row['c']
        for row in Shipment.objects.values('status').annotate(c=Count('id'))
    }

    pay_qs = Payment.objects.filter(status=Payment.Status.CAPTURED)
    if since:
        pay_qs = pay_qs.filter(created_at__gte=since)
    agg = pay_qs.aggregate(total=Sum('amount'), n=Count('id'))
    revenue_total = agg['total'] or Decimal('0')
    payments_captured_count = agg['n'] or 0

    vehicles_total = Vehicle.objects.count()
    vehicles_verified = Vehicle.objects.filter(is_verified=True).count()
    vehicles_active_verified = Vehicle.objects.filter(is_verified=True, is_active=True).count()
    transporters_verified_docs = TransporterProfile.objects.filter(documents_verified=True).count()

    return api_response(
        200,
        'Dashboard KPIs retrieved successfully.',
        data={
            'trips': {
                'active_count': active_trips,
                'stale_trips_count': stale_trips,
                'stale_trip_hours_threshold': stale_hours,
                'by_status': trip_by_status,
            },
            'shipments': {'by_status': shipment_by_status},
            'revenue': {
                'captured_payments_total': str(revenue_total),
                'captured_payments_count': payments_captured_count,
                'since': request.query_params.get('since'),
            },
            'commission': None,
            'availability': {
                'vehicles_total': vehicles_total,
                'vehicles_verified': vehicles_verified,
                'vehicles_active_and_verified': vehicles_active_verified,
                'transporters_documents_verified': transporters_verified_docs,
            },
        },
    )


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_shipment_list(request):
    qs = Shipment.objects.select_related('shipper').order_by('-id')
    st = request.query_params.get('status')
    if st:
        qs = qs.filter(status=st)
    sid = request.query_params.get('shipper_id')
    if sid:
        try:
            qs = qs.filter(shipper_id=int(sid))
        except ValueError:
            return api_response(400, 'Invalid shipper_id.', error='Invalid shipper_id.')
    cf, ct = request.query_params.get('created_from'), request.query_params.get('created_to')
    df, dt = _parse_dt(cf), _parse_dt(ct)
    if cf and df is None:
        return api_response(400, 'created_from must be a valid ISO-8601 datetime.', error='Invalid date.')
    if ct and dt is None:
        return api_response(400, 'created_to must be a valid ISO-8601 datetime.', error='Invalid date.')
    if df:
        qs = qs.filter(created_at__gte=df)
    if dt:
        qs = qs.filter(created_at__lte=dt)

    page_qs, meta = _paginate(request, qs)
    ser = AdminShipmentSerializer(page_qs, many=True)
    return api_response(200, 'Shipments retrieved successfully.', data={'results': ser.data, **meta})


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_shipment_detail(request, shipment_id):
    try:
        sh = Shipment.objects.select_related('shipper').get(pk=shipment_id)
    except Shipment.DoesNotExist:
        return api_response(404, 'Shipment not found.', error='Not found.')
    data = AdminShipmentSerializer(sh).data
    try:
        data['trip_id'] = sh.trip.id
    except Trip.DoesNotExist:
        data['trip_id'] = None
    return api_response(200, 'Shipment retrieved successfully.', data=data)


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_trip_list(request):
    qs = Trip.objects.select_related('shipment', 'transporter', 'accepted_bid').order_by('-id')
    st = request.query_params.get('status')
    if st:
        qs = qs.filter(status=st)
    tid = request.query_params.get('transporter_id')
    if tid:
        try:
            qs = qs.filter(transporter_id=int(tid))
        except ValueError:
            return api_response(400, 'Invalid transporter_id.', error='Invalid transporter_id.')
    spk = request.query_params.get('shipment_id')
    if spk:
        try:
            qs = qs.filter(shipment_id=int(spk))
        except ValueError:
            return api_response(400, 'Invalid shipment_id.', error='Invalid shipment_id.')

    page_qs, meta = _paginate(request, qs)
    ser = TripListSerializer(page_qs, many=True)
    return api_response(200, 'Trips retrieved successfully.', data={'results': ser.data, **meta})


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_trip_detail(request, trip_id):
    try:
        trip = Trip.objects.select_related('shipment', 'transporter', 'accepted_bid').get(pk=trip_id)
    except Trip.DoesNotExist:
        return api_response(404, 'Trip not found.', error='Not found.')
    data = TripDetailSerializer(trip).data
    try:
        ProofOfDelivery.objects.get(trip=trip)
        data['has_pod'] = True
    except ProofOfDelivery.DoesNotExist:
        data['has_pod'] = False
    return api_response(200, 'Trip retrieved successfully.', data=data)


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_trip_locations(request, trip_id):
    if not Trip.objects.filter(pk=trip_id).exists():
        return api_response(404, 'Trip not found.', error='Not found.')
    qs = TripLocation.objects.filter(trip_id=trip_id).order_by('-recorded_at')
    page_qs, meta = _paginate(request, qs)
    ser = TripLocationSerializer(page_qs, many=True)
    return api_response(200, 'Trip locations retrieved successfully.', data={'results': ser.data, **meta})


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_trip_pod(request, trip_id):
    if not Trip.objects.filter(pk=trip_id).exists():
        return api_response(404, 'Trip not found.', error='Not found.')
    try:
        pod = ProofOfDelivery.objects.get(trip_id=trip_id)
    except ProofOfDelivery.DoesNotExist:
        return api_response(404, 'POD not yet submitted.', error='Not found.')
    return api_response(200, 'POD retrieved successfully.', data=PODSerializer(pod, context={'request': request}).data)


@api_view(['POST'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_trip_status_override(request, trip_id):
    try:
        trip = Trip.objects.select_related('shipment').get(pk=trip_id)
    except Trip.DoesNotExist:
        return api_response(404, 'Trip not found.', error='Not found.')

    new_status = (request.data.get('new_status') or '').strip()
    justification = (request.data.get('justification') or '').strip()
    if not justification:
        return api_response(400, 'justification is required and must be non-empty.', error='Missing justification.')
    if new_status not in Trip.Status.values:
        return api_response(400, 'Invalid new_status for trip.', error='Invalid status.')

    prev = trip.status
    if prev == new_status:
        return api_response(400, 'Trip is already in this status.', error='No change.')

    with transaction.atomic():
        trip.status = new_status
        trip.save(update_fields=['status', 'updated_at'])
        record_trip_status(trip, new_status)
        _admin_sync_shipment_after_trip_override(trip, new_status)
        AdminTripAction.objects.create(
            trip=trip,
            performed_by=request.user,
            previous_status=prev,
            new_status=new_status,
            justification=justification,
        )

    notify_users(
        [trip.shipment.shipper_id, trip.transporter_id],
        'TRIP_STATUS',
        {
            'trip_id': str(trip.id),
            'shipment_id': str(trip.shipment_id),
            'status': str(new_status),
            'admin_override': True,
        },
        title='Trip update (admin)',
        body=f'Trip status set to {new_status}',
    )
    return api_response(
        200,
        'Trip status overridden successfully.',
        data=TripListSerializer(trip).data,
    )


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_user_list(request):
    qs = User.objects.select_related('role').order_by('-id')
    role = request.query_params.get('role')
    if role:
        if role not in UserRole.Role.values:
            return api_response(400, 'Invalid role filter.', error='Invalid role.')
        qs = qs.filter(role__role=role)
    active = _parse_bool_param(request.query_params.get('is_active'))
    if active is not None:
        qs = qs.filter(is_active=active)
    search = (request.query_params.get('search') or '').strip()
    if search:
        qs = qs.filter(Q(email__icontains=search) | Q(username__icontains=search))
    kyc = _parse_bool_param(request.query_params.get('kyc_verified'))
    if kyc is not None:
        qs = qs.filter(shipper_profile__kyc_verified=kyc)
    docs = _parse_bool_param(request.query_params.get('documents_verified'))
    if docs is not None:
        qs = qs.filter(transporter_profile__documents_verified=docs)

    page_qs, meta = _paginate(request, qs)
    return api_response(
        200,
        'Users retrieved successfully.',
        data={'results': [_user_list_row(u) for u in page_qs], **meta},
    )


@api_view(['GET', 'PATCH'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_user_detail(request, user_id):
    try:
        user = User.objects.select_related('role').get(pk=user_id)
    except User.DoesNotExist:
        return api_response(404, 'User not found.', error='Not found.')

    if request.method == 'GET':
        return api_response(200, 'User retrieved successfully.', data=_user_detail_payload(user))

    body = request.data
    if not isinstance(body, dict):
        return api_response(400, 'JSON object body required.', error='Invalid body.')

    if user_id == request.user.id and body.get('is_active') is False:
        return api_response(400, 'You cannot deactivate your own account via this API.', error='Forbidden self-change.')

    if 'role' in body:
        new_role = body.get('role')
        if new_role not in UserRole.Role.values:
            return api_response(400, 'Invalid role value.', error='Invalid role.')
        if new_role == UserRole.Role.ADMIN and not request.user.is_superuser:
            return api_response(
                403,
                'Only Django superusers may assign the ADMIN role via API.',
                error='Forbidden.',
            )
        ur, created = UserRole.objects.get_or_create(
            user=user,
            defaults={'role': new_role, 'phone': '', 'language': 'en'},
        )
        if not created:
            ur.role = new_role
            ur.save(update_fields=['role', 'updated_at'])

    if 'is_active' in body:
        val = body.get('is_active')
        if not isinstance(val, bool):
            return api_response(400, 'is_active must be a boolean.', error='Invalid is_active.')
        user.is_active = val
        user.save(update_fields=['is_active'])

    if 'kyc_verified' in body:
        val = body.get('kyc_verified')
        if not isinstance(val, bool):
            return api_response(400, 'kyc_verified must be a boolean.', error='Invalid field.')
        try:
            sp = user.shipper_profile
        except ShipperProfile.DoesNotExist:
            return api_response(400, 'User has no shipper profile.', error='Invalid target.')
        sp.kyc_verified = val
        sp.save(update_fields=['kyc_verified', 'updated_at'])

    if 'credit_approved' in body:
        val = body.get('credit_approved')
        if not isinstance(val, bool):
            return api_response(400, 'credit_approved must be a boolean.', error='Invalid field.')
        try:
            sp = user.shipper_profile
        except ShipperProfile.DoesNotExist:
            return api_response(400, 'User has no shipper profile.', error='Invalid target.')
        sp.credit_approved = val
        sp.save(update_fields=['credit_approved', 'updated_at'])

    if 'documents_verified' in body:
        val = body.get('documents_verified')
        if not isinstance(val, bool):
            return api_response(400, 'documents_verified must be a boolean.', error='Invalid field.')
        try:
            tp = user.transporter_profile
        except TransporterProfile.DoesNotExist:
            return api_response(400, 'User has no transporter profile.', error='Invalid target.')
        tp.documents_verified = val
        tp.save(update_fields=['documents_verified', 'updated_at'])

    user.refresh_from_db()
    return api_response(200, 'User updated successfully.', data=_user_detail_payload(user))


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_vehicle_document_list(request):
    qs = VehicleDocument.objects.select_related('vehicle', 'vehicle__owner', 'reviewed_by').order_by('-submitted_at')
    rs = request.query_params.get('review_status')
    if rs:
        qs = qs.filter(review_status=rs)
    vid = request.query_params.get('vehicle_id')
    if vid:
        try:
            qs = qs.filter(vehicle_id=int(vid))
        except ValueError:
            return api_response(400, 'Invalid vehicle_id.', error='Invalid vehicle_id.')

    page_qs, meta = _paginate(request, qs)
    ser = VehicleDocumentSerializer(page_qs, many=True, context={'request': request})
    rows = []
    for item, doc in zip(ser.data, page_qs):
        row = dict(item)
        row['vehicle_owner_id'] = doc.vehicle.owner_id
        row['vehicle_owner_email'] = getattr(doc.vehicle.owner, 'email', '') or ''
        rows.append(row)
    return api_response(200, 'Vehicle documents retrieved successfully.', data={'results': rows, **meta})


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_vehicle_list(request):
    qs = Vehicle.objects.select_related('owner', 'assigned_driver', 'verified_by').order_by('-id')
    iv = _parse_bool_param(request.query_params.get('is_verified'))
    if iv is not None:
        qs = qs.filter(is_verified=iv)
    ia = _parse_bool_param(request.query_params.get('is_active'))
    if ia is not None:
        qs = qs.filter(is_active=ia)
    oid = request.query_params.get('owner_id')
    if oid:
        try:
            qs = qs.filter(owner_id=int(oid))
        except ValueError:
            return api_response(400, 'Invalid owner_id.', error='Invalid owner_id.')

    page_qs, meta = _paginate(request, qs)
    ser = VehicleSerializer(page_qs, many=True)
    return api_response(200, 'Vehicles retrieved successfully.', data={'results': ser.data, **meta})


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_kyc_document_list(request):
    qs = KYCDocument.objects.select_related('user').exclude(
        document_type__in=KYCDocument.LEGACY_VEHICLE_KYC_TYPES,
    ).order_by('-submitted_at')
    verified = _parse_bool_param(request.query_params.get('verified'))
    if verified is not None:
        qs = qs.filter(verified=verified)
    uid = request.query_params.get('user_id')
    if uid:
        try:
            qs = qs.filter(user_id=int(uid))
        except ValueError:
            return api_response(400, 'Invalid user_id.', error='Invalid user_id.')

    page_qs, meta = _paginate(request, qs)
    ser = KYCDocumentSerializer(page_qs, many=True, context={'request': request})
    return api_response(200, 'KYC documents retrieved successfully.', data={'results': ser.data, **meta})


def _country_codes_matching_search(search):
    """Resolve search text to ISO codes using core.countries as the source of truth."""
    needle = (search or '').strip()
    if not needle:
        return []
    codes = set()
    exact = country_name_to_code(needle)
    if exact:
        codes.add(exact)
    lowered = needle.lower()
    for code, name in COUNTRY_BY_CODE.items():
        if lowered in code.lower() or lowered in name.lower():
            codes.add(code)
    return list(codes)


def _freight_route_queryset(request):
    qs = FreightRoute.objects.all()
    origin = normalize_country_code(request.query_params.get('origin'))
    destination = normalize_country_code(request.query_params.get('destination'))
    if origin:
        qs = qs.filter(origin_country_code=origin)
    if destination:
        qs = qs.filter(destination_country_code=destination)
    search = (request.query_params.get('search') or '').strip()
    if search:
        matched_codes = _country_codes_matching_search(search)
        name_q = Q()
        if matched_codes:
            name_q = (
                Q(origin_country_code__in=matched_codes)
                | Q(destination_country_code__in=matched_codes)
            )
        qs = qs.filter(
            Q(origin_country_code__icontains=search)
            | Q(destination_country_code__icontains=search)
            | name_q
        )
    ordering = (request.query_params.get('ordering') or '-updated_at').strip()
    allowed = {
        'updated_at', '-updated_at',
        'min_freight', '-min_freight',
        'origin_country_code', '-origin_country_code',
        'destination_country_code', '-destination_country_code',
    }
    if ordering not in allowed:
        ordering = '-updated_at'
    return qs.order_by(ordering)


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_country_list(request):
    search = (request.query_params.get('search') or '').strip().lower()
    results = []
    for code, name in COUNTRY_CHOICES:
        if search and search not in code.lower() and search not in name.lower():
            continue
        results.append({'code': code, 'name': name})
    return api_response(200, 'Countries retrieved successfully.', data=results)


@api_view(['GET', 'POST'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_freight_route_list_create(request):
    if request.method == 'GET':
        qs = _freight_route_queryset(request)
        page_qs, meta = _paginate(request, qs)
        ser = FreightRouteSerializer(page_qs, many=True)
        return api_response(
            200,
            'Freight routes retrieved successfully.',
            data={'results': ser.data, **meta},
        )

    ser = FreightRouteSerializer(data=request.data)
    if not ser.is_valid():
        return api_response(400, 'Validation failed.', error=ser.errors)
    route = ser.save()
    return api_response(
        201,
        'Freight route created successfully.',
        data=FreightRouteSerializer(route).data,
    )


@api_view(['GET', 'PATCH', 'PUT', 'DELETE'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_freight_route_detail(request, pk):
    try:
        route = FreightRoute.objects.get(pk=pk)
    except FreightRoute.DoesNotExist:
        return api_response(404, 'Freight route not found.', error='Not found.')

    if request.method == 'GET':
        return api_response(
            200,
            'Freight route retrieved successfully.',
            data=FreightRouteSerializer(route).data,
        )

    if request.method == 'DELETE':
        route.delete()
        return api_response(200, 'Freight route deleted successfully.', data={'id': pk})

    partial = request.method == 'PATCH'
    ser = FreightRouteSerializer(route, data=request.data, partial=partial)
    if not ser.is_valid():
        return api_response(400, 'Validation failed.', error=ser.errors)
    route = ser.save()
    return api_response(
        200,
        'Freight route updated successfully.',
        data=FreightRouteSerializer(route).data,
    )


@api_view(['POST'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_freight_route_bulk_import(request):
    uploaded = request.FILES.get('file')
    if not uploaded:
        return api_response(400, 'Validation failed.', error='file is required.')

    try:
        rows = parse_freight_route_upload(uploaded)
    except ValueError as exc:
        return api_response(400, 'Unable to parse upload.', error=str(exc))

    summary = bulk_upsert_freight_routes(rows)
    return api_response(200, 'Freight route bulk import completed.', data=summary)


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_conversations_list(request):
    qs = (
        Conversation.objects.select_related(
            'shipment',
            'shipper',
            'shipper__role',
            'shipper__shipper_profile',
            'transporter',
            'transporter__role',
            'transporter__transporter_profile',
            'trip',
            'trip__assigned_driver',
        )
        .prefetch_related('messages')
        .order_by('-created_at')
    )

    shipment_id = (request.GET.get('shipment_id') or '').strip()
    if shipment_id:
        try:
            qs = qs.filter(Q(shipment_id=int(shipment_id)) | Q(shipment__unique_id__iexact=shipment_id))
        except (ValueError, TypeError):
            qs = qs.filter(shipment__unique_id__iexact=shipment_id)

    trip_id = (request.GET.get('trip_id') or '').strip()
    if trip_id:
        try:
            qs = qs.filter(trip_id=int(trip_id))
        except (ValueError, TypeError):
            pass

    shipper_id = (request.GET.get('shipper_id') or '').strip()
    if shipper_id:
        try:
            qs = qs.filter(shipper_id=int(shipper_id))
        except (ValueError, TypeError):
            pass

    transporter_id = (request.GET.get('transporter_id') or '').strip()
    if transporter_id:
        try:
            qs = qs.filter(transporter_id=int(transporter_id))
        except (ValueError, TypeError):
            pass

    status_filter = (request.GET.get('status') or '').strip()
    if status_filter:
        if status_filter == 'PRE_TRIP':
            qs = qs.filter(trip__isnull=True)
        else:
            qs = qs.filter(trip__status=status_filter)

    search = (request.GET.get('search') or '').strip()
    if search:
        qs = qs.filter(
            Q(shipment__unique_id__icontains=search)
            | Q(shipment__pickup_address__icontains=search)
            | Q(shipment__delivery_address__icontains=search)
            | Q(shipment__cargo_type__icontains=search)
            | Q(shipper__email__icontains=search)
            | Q(shipper__first_name__icontains=search)
            | Q(shipper__last_name__icontains=search)
            | Q(transporter__email__icontains=search)
            | Q(transporter__first_name__icontains=search)
            | Q(transporter__last_name__icontains=search)
            | Q(transporter__transporter_profile__company_name__icontains=search)
            | Q(trip__assigned_driver__email__icontains=search)
            | Q(messages__text__icontains=search)
        ).distinct()

    try:
        page_size = min(int(request.GET.get('page_size', 20)), 100)
    except (ValueError, TypeError):
        page_size = 20
    try:
        page_num = max(int(request.GET.get('page', 1)), 1)
    except (ValueError, TypeError):
        page_num = 1
    offset = (page_num - 1) * page_size
    total = qs.count()
    items = qs[offset:offset + page_size]

    serializer = AdminConversationListSerializer(items, many=True, context={'request': request})
    return api_response(
        200,
        'Conversations retrieved successfully.',
        data={
            'total': total,
            'page': page_num,
            'page_size': page_size,
            'conversations': serializer.data,
        },
    )


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_conversation_messages(request, conversation_id):
    try:
        conv = (
            Conversation.objects.select_related(
                'shipment',
                'shipper',
                'transporter',
                'trip',
                'trip__assigned_driver',
            )
            .prefetch_related('messages', 'messages__sender')
            .get(pk=conversation_id)
        )
    except Conversation.DoesNotExist:
        return api_response(404, 'Conversation not found.', error='Not found.')

    serializer = AdminConversationDetailSerializer(conv, context={'request': request})
    return api_response(
        200,
        'Conversation messages retrieved successfully.',
        data=serializer.data,
    )


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_shipment_rate_requests(request, shipment_id):
    """List all rate requests distributed for a specific shipment."""
    try:
        shipment = Shipment.objects.get(pk=shipment_id)
    except Shipment.DoesNotExist:
        return api_response(404, 'Shipment not found.', error='Not found.')

    requests_qs = RateRequest.objects.filter(shipment=shipment).select_related('driver', 'shipment').order_by('batch_number', 'created_at')
    ser = RateRequestSerializer(requests_qs, many=True, context={'request': request})
    return api_response(200, 'Rate requests retrieved successfully.', data={
        'shipment_id': shipment.id,
        'unique_id': shipment.unique_id,
        'shipment_status': shipment.status,
        'count': len(ser.data),
        'rate_requests': ser.data,
    })


@api_view(['POST'])
@permission_classes([IsAuthenticated, IsPlatformAdmin])
def admin_shipment_dispatch_next_batch(request, shipment_id):
    """Admin triggers dispatch of the next batch of rate requests for a shipment."""
    try:
        shipment = Shipment.objects.get(pk=shipment_id)
    except Shipment.DoesNotExist:
        return api_response(404, 'Shipment not found.', error='Not found.')

    if shipment.status != Shipment.Status.PUBLISHED:
        return api_response(400, f'Cannot dispatch batch for shipment in status {shipment.status}.', error='Invalid status.')

    from core.rate_distribution import dispatch_rate_requests_for_shipment
    created = dispatch_rate_requests_for_shipment(shipment)
    ser = RateRequestSerializer(created, many=True, context={'request': request})
    return api_response(200, f'Dispatched {len(created)} rate requests.', data={
        'shipment_id': shipment.id,
        'dispatched_count': len(created),
        'rate_requests': ser.data,
    })


