"""Helpers to link legacy KYC vehicle registration onto Vehicle NOC documents."""
import logging

from django.core.files.base import ContentFile
from django.db.models import Exists, OuterRef

from accounts.models import KYCDocument, Vehicle, VehicleDocument

logger = logging.getLogger(__name__)


def copy_kyc_vehicle_registration_to_vehicle(vehicle):
    """
    If the vehicle owner has a legacy KYC VEHICLE_REGISTRATION and this vehicle
    has no NOC VehicleDocument yet, create one.

    Prefer copying file bytes when available. If the media file is missing on
    this host, still create the VehicleDocument and point its FileField at the
    same storage path so the row appears in admin Vehicle documents (and works
    wherever media is present).
    """
    if vehicle is None or not vehicle.owner_id:
        return None

    if VehicleDocument.objects.filter(
        vehicle=vehicle,
        document_type=VehicleDocument.DocumentType.NOC,
    ).exists():
        return None

    kyc = (
        KYCDocument.objects.filter(
            user_id=vehicle.owner_id,
            document_type=KYCDocument.DocumentType.VEHICLE_REGISTRATION,
        )
        .exclude(file='')
        .order_by('-submitted_at')
        .first()
    )
    if kyc is None or not kyc.file or not kyc.file.name:
        return None

    doc = VehicleDocument(
        vehicle=vehicle,
        document_type=VehicleDocument.DocumentType.NOC,
        review_status=kyc.review_status or VehicleDocument.ReviewStatus.PENDING,
        review_notes=kyc.review_notes or '',
        expiry_date=kyc.expiry_date,
        reviewed_at=kyc.reviewed_at,
        reviewed_by_id=kyc.reviewed_by_id,
    )

    content = None
    try:
        if kyc.file.storage.exists(kyc.file.name):
            kyc.file.open('rb')
            try:
                content = kyc.file.read()
            finally:
                kyc.file.close()
    except (FileNotFoundError, OSError) as exc:
        logger.warning(
            'KYC file unreadable for vehicle %s (%s); linking path %s instead',
            vehicle.pk,
            exc,
            kyc.file.name,
        )

    if content:
        filename = kyc.file.name.rsplit('/', 1)[-1] or 'vehicle-noc'
        doc.file.save(filename, ContentFile(content), save=False)
    else:
        # Reuse the same storage key so admin lists the row without duplicating bytes.
        doc.file.name = kyc.file.name

    doc.save()
    if kyc.submitted_at:
        VehicleDocument.objects.filter(pk=doc.pk).update(submitted_at=kyc.submitted_at)
        doc.submitted_at = kyc.submitted_at

    logger.info(
        'Created VehicleDocument NOC id=%s for vehicle %s from KYC %s',
        doc.pk,
        vehicle.pk,
        kyc.pk,
    )
    return doc


def sync_missing_kyc_vehicle_registrations():
    """
    Backfill VehicleDocument NOC from legacy KYC VEHICLE_REGISTRATION for any
    owned vehicles still missing a NOC document.
    """
    has_noc = VehicleDocument.objects.filter(
        vehicle_id=OuterRef('pk'),
        document_type=VehicleDocument.DocumentType.NOC,
    )
    vehicles = (
        Vehicle.objects.filter(
            Exists(
                KYCDocument.objects.filter(
                    user_id=OuterRef('owner_id'),
                    document_type=KYCDocument.DocumentType.VEHICLE_REGISTRATION,
                ).exclude(file='')
            )
        )
        .exclude(Exists(has_noc))
        .select_related('owner', 'owner__transporter_profile')
    )
    created = []
    for vehicle in vehicles:
        try:
            doc = copy_kyc_vehicle_registration_to_vehicle(vehicle)
        except Exception:
            logger.exception(
                'Unexpected error syncing KYC vehicle registration for vehicle %s',
                vehicle.pk,
            )
            continue
        if doc is not None:
            created.append(doc)
    return created
