from django.db.models import Q
from django.shortcuts import get_object_or_404
from django.utils import timezone

from structures.models import Structure

from .integration_serializers import IstatSyncHistorySerializer
from .models import IstatAuditLog, IstatCredential, IstatSyncHistory


def get_accessible_structure(*, user, structure_id):
    queryset = Structure.objects.filter(
        Q(user=user) | Q(structure_users__user=user)
    ).distinct()
    return get_object_or_404(queryset, id=structure_id)


def create_istat_audit_log(
    *,
    structure,
    action,
    message,
    actor=None,
    credential=None,
    sync_record=None,
    metadata=None,
):
    return IstatAuditLog.objects.create(
        structure=structure,
        credential=credential,
        sync_record=sync_record,
        actor=actor,
        action=action,
        message=message,
        metadata=metadata or {},
    )


def get_latest_sync(structure):
    return structure.istat_sync_history.first()


def get_credential_for_structure(structure):
    return IstatCredential.objects.filter(structure=structure).first()


def build_connection_payload(structure):
    credential = get_credential_for_structure(structure)
    latest_sync = get_latest_sync(structure)

    return {
        "structure_id": structure.id,
        "credential_type": "ISTAT",
        "provider": "Ross1000",
        "connected": credential is not None,
        "connection_status": (
            "connected" if credential is not None else "not_connected"
        ),
        "username": credential.username if credential is not None else None,
        "password_masked": (
            credential.masked_password if credential is not None else None
        ),
        "last_sync": (
            IstatSyncHistorySerializer(latest_sync).data
            if latest_sync is not None
            else None
        ),
        "created_at": credential.created_at if credential is not None else None,
        "updated_at": credential.updated_at if credential is not None else None,
    }


def trigger_manual_sync(
    *,
    structure,
    actor,
    requested_period,
    request_payload=None,
):
    credential = get_credential_for_structure(structure)
    if credential is None:
        raise ValueError("ISTAT credentials are not connected for this structure.")

    sync_record = IstatSyncHistory.objects.create(
        structure=structure,
        credential=credential,
        triggered_by=actor,
        status=IstatSyncHistory.Status.PENDING,
        requested_period=requested_period or {},
        request_payload=request_payload or {},
    )

    create_istat_audit_log(
        structure=structure,
        credential=credential,
        sync_record=sync_record,
        actor=actor,
        action=IstatAuditLog.Action.SYNC_TRIGGERED,
        message=(
            f"User {actor.username} triggered ISTAT sync for structure "
            f"{structure.name}"
        ),
        metadata={
            "requested_period": requested_period or {},
            "status": IstatSyncHistory.Status.PENDING,
        },
    )

    completed_at = timezone.now()
    response_payload = {
        "status": IstatSyncHistory.Status.SUCCESS,
        "message": "Report sent successfully (stub)",
        "timestamp": completed_at,
        "requested_period": requested_period or {},
    }

    sync_record.status = IstatSyncHistory.Status.SUCCESS
    sync_record.message = response_payload["message"]
    sync_record.completed_at = completed_at
    sync_record.response_payload = {
        "status": response_payload["status"],
        "message": response_payload["message"],
        "timestamp": completed_at.isoformat(),
        "requested_period": requested_period or {},
    }
    sync_record.save(
        update_fields=[
            "status",
            "message",
            "completed_at",
            "response_payload",
        ]
    )

    return sync_record, response_payload
