from django.template.loader import render_to_string

from oscar_odin.exceptions import OscarOdinException

from ocyan.core.utils import merge_dicts


def get_error_message_dict(error, error_dict, related_field=None):
    identifier_values = getattr(error, "identifier_values", [])
    return {
        field: {
            "related_field": related_field,
            "message": str(error_dict[field]),
            "records": [", ".join(identifier_values)],
        }
        for field in error_dict
    }


def add_related_field_errors(merged_errors, related_fields, error):
    """
    Adds related field from error in merged_errors and removes it from error
    """
    for field in related_fields:
        if field in error.message_dict:
            field_errors = error.message_dict.pop(field)[0]
            try:
                field_errors = field_errors.get("0", field_errors)
            except AttributeError:
                field_errors = error.message_dict
            merge_dicts(
                merged_errors,
                get_error_message_dict(error, field_errors, field),
                deduplicate_iterables=True,
            )


def get_sync_error_message(errors, related_fields=[], error_identifiers=None):  # pylint:disable=W0102
    """
    input(errors): [
        ValidationError({'price': ['Zorg dat er niet meer dan 12 cijfers zijn.']}),
        ValidationError({'price': ['Zorg dat er niet meer dan 12 cijfers zijn.']})
    ]
    output:
        Price: Zorg dat er niet meer dan 12 cijfers zijn.
        OR
        An html table if error_identifiers are given
    """
    merged_errors = dict()
    for error in errors:
        add_related_field_errors(merged_errors, related_fields, error)
        if isinstance(error, OscarOdinException):
            error_messages = get_error_message_dict(error, error.args[0])
        else:
            error_messages = get_error_message_dict(error, error.message_dict)
        merge_dicts(
            merged_errors,
            error_messages,
            deduplicate_iterables=True,
        )

    if error_identifiers is not None:
        return render_to_string(
            "admin/task/error_table.html",
            {
                "errors": merged_errors,
                "identifiers": error_identifiers,
                "is_single_column": len(error_identifiers) == 1,
            },
        )

    message = ""
    for field, details in merged_errors.items():
        message += f" '{field.capitalize()}': {details['message']}"
    return message
