from kinto.core.errors import http_error
from kinto.core.events import ACTIONS, ResourceChanged
from pyramid.events import subscriber
from pyramid.exceptions import HTTPBadRequest
from pyramid.settings import asbool

from . import utils


# XXX: Use AfterResourceChanged when implemented.
@subscriber(
    ResourceChanged,
    for_resources=("record", "collection", "bucket"),
    for_actions=(ACTIONS.DELETE,),
)
def on_delete_record(event):
    """When a resource record is deleted, delete all related attachments.
    When a bucket or collection is deleted, it removes the attachments of
    every underlying records.
    """
    keep_old_files = asbool(utils.setting_value(event.request, "keep_old_files", default=False))

    # Retrieve attachments for these records using links.
    resource_name = event.payload["resource_name"]
    filter_field = "%s_uri" % resource_name
    uri = event.payload["uri"]
    utils.delete_attachment(
        event.request, link_field=filter_field, uri=uri, keep_old_files=keep_old_files
    )


@subscriber(ResourceChanged, for_resources=("record",), for_actions=(ACTIONS.UPDATE,))
def on_update_record(event):
    if getattr(event.request, "_attachment_auto_save", False):
        # Record attributes are being updated by the plugin itself.
        return

    # A user is changing the record, make sure attachment metadata is not
    # altered manually.
    for change in event.impacted_objects:
        attachment_before = change["old"].get("attachment")
        attachment_after = change["new"].get("attachment")
        if attachment_before and attachment_after:
            if attachment_before != attachment_after:
                error_msg = "Attachment metadata cannot be modified."
                raise http_error(HTTPBadRequest(), message=error_msg)
