"""KYC document review helpers: profile sync and rejection notify."""
from django.utils import timezone

from accounts.models import KYCDocument, ShipperProfile, TransporterProfile


def shipper_required_doc_types(account_type):
    if account_type == ShipperProfile.AccountType.BUSINESS:
        return {KYCDocument.DocumentType.BUSINESS_REGISTRATION}
    return {KYCDocument.DocumentType.ID}


def transporter_required_doc_types(account_type):
    if account_type == TransporterProfile.AccountType.FLEET_OWNER:
        return set(KYCDocument.FLEET_OWNER_DOC_TYPES)
    # Vehicle registration is reviewed on Vehicle documents, not KYC verification.
    return set(KYCDocument.DRIVER_PERSON_KYC_TYPES)


def sync_user_kyc_verified(user) -> bool:
    """
    Set profile verification from required KYC docs.

    Transporter: documents_verified True iff every required type has APPROVED.
    Shipper: kyc_verified True iff every required type has APPROVED.
    Returns the new verified flag when a matching profile exists, else False.
    """
    try:
        profile = user.transporter_profile
    except TransporterProfile.DoesNotExist:
        profile = None

    if profile is not None:
        required = transporter_required_doc_types(profile.account_type)
        approved = set(
            KYCDocument.objects.filter(
                user=user,
                document_type__in=required,
                review_status=KYCDocument.ReviewStatus.APPROVED,
            ).values_list('document_type', flat=True)
        )
        verified = bool(required) and required.issubset(approved)
        if profile.documents_verified != verified:
            profile.documents_verified = verified
            profile.save(update_fields=['documents_verified', 'updated_at'])
        return verified

    try:
        shipper = user.shipper_profile
    except ShipperProfile.DoesNotExist:
        return False

    required = shipper_required_doc_types(shipper.account_type)
    approved = set(
        KYCDocument.objects.filter(
            user=user,
            document_type__in=required,
            review_status=KYCDocument.ReviewStatus.APPROVED,
        ).values_list('document_type', flat=True)
    )
    verified = bool(required) and required.issubset(approved)
    if shipper.kyc_verified != verified:
        shipper.kyc_verified = verified
        shipper.save(update_fields=['kyc_verified', 'updated_at'])
    return verified


def apply_kyc_review(doc, *, review_status, review_notes='', reviewer=None, notify=True):
    """
    Apply APPROVED/REJECTED/PENDING review. REJECTED requires non-empty notes.
    Syncs verified flag and profile; notifies user on REJECTED when notify=True.
    """
    notes = (review_notes or '').strip()
    if review_status == KYCDocument.ReviewStatus.REJECTED and not notes:
        raise ValueError('Rejection reason is required.')

    previous = doc.review_status
    doc.review_status = review_status
    doc.review_notes = notes if review_status == KYCDocument.ReviewStatus.REJECTED else (
        notes if notes else ''
    )
    if review_status == KYCDocument.ReviewStatus.APPROVED:
        doc.review_notes = notes  # optional approve comment
        doc.reviewed_at = timezone.now()
        doc.reviewed_by = reviewer
    elif review_status == KYCDocument.ReviewStatus.REJECTED:
        doc.reviewed_at = timezone.now()
        doc.reviewed_by = reviewer
    else:
        doc.review_notes = ''
        doc.reviewed_at = None
        doc.reviewed_by = None

    doc.sync_verified_flag()
    doc.save(update_fields=[
        'review_status', 'review_notes', 'verified', 'reviewed_at', 'reviewed_by',
    ])
    sync_user_kyc_verified(doc.user)

    if (
        notify
        and review_status == KYCDocument.ReviewStatus.REJECTED
        and previous != KYCDocument.ReviewStatus.REJECTED
    ):
        from api.notify import notify_users

        notify_users(
            [doc.user_id],
            'DOCUMENT_REJECTED',
            {
                'kind': 'KYC',
                'document_id': str(doc.pk),
                'document_type': doc.document_type,
                'document_type_display': doc.get_document_type_display(),
                'reason': notes,
            },
            title='Document rejected',
            body=f'Your {doc.get_document_type_display()} was rejected: {notes}',
        )
    return doc


def reset_kyc_document_for_resubmit(doc, *, file_changed=False):
    """When files are re-uploaded, return the doc to PENDING for re-review."""
    if not file_changed:
        return doc
    doc.review_status = KYCDocument.ReviewStatus.PENDING
    doc.review_notes = ''
    doc.verified = False
    doc.reviewed_at = None
    doc.reviewed_by = None
    return doc
