"""GDPR data deletion / anonymization service (Right to Erasure).

⚠️ AUTO-GENERATED BY PRISM — DO NOT EDIT
This file is regenerated on every `prisme generate`.
"""

from __future__ import annotations

import logging
from datetime import datetime, timezone
from typing import Any

from sqlalchemy import update
from sqlalchemy.ext.asyncio import AsyncSession

from {{ package_name }}.privacy.audit_service import AuditService
{% for model in personal_data_models %}
from {{ package_name }}.models.{{ model.snake_name }} import {{ model.name }}
{% endfor %}

logger = logging.getLogger(__name__)

# Anonymization replacement values by field type
_ANON_DEFAULTS: dict[str, Any] = {
    "string": "[REDACTED]",
    "text": "[REDACTED]",
    "integer": 0,
    "float": 0.0,
    "boolean": False,
    "json": None,
}


class DataDeletionService:
    """Handles GDPR right to erasure (Article 17) requests.

    Supports both hard deletion and anonymization of personal data.
    All operations are recorded in the audit log.
    """

    def __init__(self, session: AsyncSession) -> None:
        self.session = session
        self.audit = AuditService(session)

    async def erase_subject_data(
        self,
        *,
        subject_id: str,
        subject_field: str = "id",
        anonymize: bool = False,
        requesting_user_id: str | None = None,
        ip_address: str | None = None,
    ) -> dict[str, Any]:
        """Erase or anonymize all personal data for a data subject.

        Args:
            subject_id: The identifier of the data subject.
            subject_field: The field name to match (default: 'id').
            anonymize: If True, anonymize PII fields instead of deleting records.
            requesting_user_id: User who initiated the request (for audit).
            ip_address: Client IP address (for audit).

        Returns:
            Summary of what was erased/anonymized per model.
        """
        summary: dict[str, dict[str, int]] = {}
{% for model in personal_data_models %}

        # Process {{ model.name }}
{% if model.anonymize_on_delete or "True" == "True" %}
        if anonymize:
            count = await self._anonymize_{{ model.snake_name }}(subject_id, subject_field)
            summary["{{ model.snake_name }}"] = {"anonymized": count}
        else:
            count = await self._delete_{{ model.snake_name }}(subject_id, subject_field)
            summary["{{ model.snake_name }}"] = {"deleted": count}
{% else %}
        count = await self._delete_{{ model.snake_name }}(subject_id, subject_field)
        summary["{{ model.snake_name }}"] = {"deleted": count}
{% endif %}
{% endfor %}

        # Audit the erasure
        await self.audit.log(
            operation="erase",
            model_name="*",
            record_id=subject_id,
            user_id=requesting_user_id,
            ip_address=ip_address,
            details=f"Data subject erasure (anonymize={anonymize}): {summary}",
        )

        return {
            "erased_at": datetime.now(timezone.utc).isoformat(),
            "subject_id": subject_id,
            "anonymized": anonymize,
            "summary": summary,
        }
{% for model in personal_data_models %}

    async def _delete_{{ model.snake_name }}(
        self, subject_id: str, subject_field: str
    ) -> int:
        """Hard-delete {{ model.name }} records for a subject."""
        from sqlalchemy import delete as sa_delete

        stmt = sa_delete({{ model.name }}).where(
            getattr({{ model.name }}, subject_field) == subject_id
        )
        result = await self.session.execute(stmt)
        return result.rowcount  # type: ignore[return-value]

    async def _anonymize_{{ model.snake_name }}(
        self, subject_id: str, subject_field: str
    ) -> int:
        """Anonymize PII fields in {{ model.name }} records for a subject."""
        anon_values: dict[str, Any] = {}
{% for field_name, field_type in model.pii_field_types.items() %}
        anon_values["{{ field_name }}"] = _ANON_DEFAULTS.get("{{ field_type }}", "[REDACTED]")
{% endfor %}

        if not anon_values:
            return 0

        stmt = (
            update({{ model.name }})
            .where(getattr({{ model.name }}, subject_field) == subject_id)
            .values(**anon_values)
        )
        result = await self.session.execute(stmt)
        return result.rowcount  # type: ignore[return-value]
{% endfor %}
