"""
Document Control Service — Celery Tasks.

Background tasks for:
- Cleaning up old versions
- Notifying pending approvals
"""
import logging
from datetime import timedelta

from celery import shared_task
from django.utils import timezone

logger = logging.getLogger('apps')


@shared_task(
    name='document_control.cleanup_old_versions',
    bind=True,
    max_retries=3,
    default_retry_delay=60,
)
def cleanup_old_versions(self, retention_days: int = 365, max_versions_to_keep: int = 10):
    """
    Clean up old document versions beyond retention policy.

    Keeps at least `max_versions_to_keep` versions per document and
    removes non-current versions older than `retention_days`.
    """
    from apps.core.tenant.models import Tenant
    from .models import DocumentVersion

    cutoff = timezone.now() - timedelta(days=retention_days)
    total_deleted = 0

    try:
        for tenant in Tenant.objects.filter(is_active=True):
            # Find documents with more than max_versions_to_keep versions
            from django.db.models import Count
            from .models import Document

            docs_with_many_versions = Document.objects.filter(
                tenant=tenant,
                is_deleted=False,
            ).annotate(
                version_count=Count('versions'),
            ).filter(version_count__gt=max_versions_to_keep)

            for doc in docs_with_many_versions:
                # Get versions to delete: non-current, older than cutoff, beyond keep limit
                versions_to_keep = DocumentVersion.objects.filter(
                    document=doc,
                ).order_by('-version_number')[:max_versions_to_keep].values_list('id', flat=True)

                deletable = DocumentVersion.objects.filter(
                    document=doc,
                    is_current=False,
                    created_at__lt=cutoff,
                ).exclude(id__in=list(versions_to_keep))

                count = deletable.count()
                if count > 0:
                    deletable.delete()
                    total_deleted += count

        logger.info(f'[document_control] Cleaned up {total_deleted} old versions')
    except Exception as exc:
        logger.error(f'[document_control] cleanup_old_versions failed: {exc}')
        raise self.retry(exc=exc)


@shared_task(
    name='document_control.notify_pending_approvals',
    bind=True,
    max_retries=3,
    default_retry_delay=60,
)
def notify_pending_approvals(self, stale_hours: int = 48):
    """
    Notify approvers about pending approval requests that are older than `stale_hours`.

    This task runs periodically (via Celery Beat) to remind approvers.
    """
    from apps.core.tenant.models import Tenant
    from .models import DocumentApproval, ApprovalStatus

    cutoff = timezone.now() - timedelta(hours=stale_hours)
    total_notified = 0

    try:
        for tenant in Tenant.objects.filter(is_active=True):
            stale_approvals = DocumentApproval.objects.filter(
                tenant=tenant,
                status=ApprovalStatus.PENDING,
                created_at__lt=cutoff,
            ).select_related('document', 'approver')

            for approval in stale_approvals:
                # Publish notification event (integration with notification service)
                try:
                    from apps.core.event_bus.bus import event_bus
                    from apps.core.event_bus.events import IntegrationEvent

                    event = IntegrationEvent(
                        event_type='document_control.approval.reminder',
                        tenant_id=str(tenant.id),
                        source_module='document_control',
                        target_module='notification',
                        data={
                            'approval_id': str(approval.id),
                            'document_id': str(approval.document_id),
                            'document_title': approval.document.title,
                            'document_code': approval.document.code,
                            'approver_id': str(approval.approver_id) if approval.approver_id else None,
                            'pending_since': approval.created_at.isoformat(),
                        },
                    )
                    event_bus.publish(event)
                    total_notified += 1
                except Exception as e:
                    logger.warning(f'Failed to send approval reminder: {e}')

        logger.info(f'[document_control] Sent {total_notified} approval reminders')
    except Exception as exc:
        logger.error(f'[document_control] notify_pending_approvals failed: {exc}')
        raise self.retry(exc=exc)


@shared_task(
    name='document_control.cleanup_audit_logs',
    bind=True,
    max_retries=3,
    default_retry_delay=60,
)
def cleanup_audit_logs(self, retention_days: int = 365):
    """
    Clean up old audit logs beyond retention period.
    """
    from apps.core.tenant.models import Tenant
    from .models import DocumentAuditLog

    cutoff = timezone.now() - timedelta(days=retention_days)
    total_deleted = 0

    try:
        for tenant in Tenant.objects.filter(is_active=True):
            count, _ = DocumentAuditLog.objects.filter(
                tenant=tenant,
                created_at__lt=cutoff,
            ).delete()
            total_deleted += count

        logger.info(f'[document_control] Cleaned up {total_deleted} audit log entries')
    except Exception as exc:
        logger.error(f'[document_control] cleanup_audit_logs failed: {exc}')
        raise self.retry(exc=exc)
