# © 2016 Antiun Ingeniería S.L. - Jairo Llopis
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

import logging

from odoo import SUPERUSER_ID, api

_logger = logging.getLogger(__name__)


def post_init_hook_for_submodules(cr, model, field):
    """Moves images from single to multi mode.

    Feel free to use this as a ``post_init_hook`` for submodules.

    :param odoo.sql_db.Cursor cr:
        Database cursor.

    :param str model:
        Model name, like ``product.template``.

    :param str field:
        Binary field that had the images in that :param:`model`, like
        ``image``.
    """
    env = api.Environment(cr, SUPERUSER_ID, {})
    table = env[model]._table
    image_obj = env["base_multi_image.image"]
    with cr.savepoint():
        column_exists = table_has_column(cr, table, field)
        if column_exists:
            cr.execute(
                "SELECT id FROM %(table)s WHERE %(field)s IS NOT NULL"
            )  # pylint: disable=sql-injection
        else:
            cr.execute(
                """
                    SELECT res_id
                    FROM ir_attachment
                    WHERE
                        res_field=%(field)s
                        AND res_model=%(model)s
                """,
                {
                    "field": field,
                    "model": model,
                },
            )
        record_ids = [row[0] for row in cr.fetchall()]
        for record in env[model].browse(record_ids):
            image_obj.create(
                {
                    "owner_id": record.id,
                    "owner_model": model,
                    "owner_ref_id": "%s,%s" % (model, record.id),
                    "image_1920": record[field],
                },
            )


def uninstall_hook_for_submodules(cr, model, field=None):
    """Moves images from multi to single mode and remove multi-images for a
    given model.

    :param odoo.sql_db.Cursor cr:
        Database cursor.

    :param odoo.modules.registry.RegistryManager registry:
        Database registry, using v7 api.

    :param str model:
        Model technical name, like "res.partner". All multi-images for that
        model will be deleted

    :param str field:
        Binary field that had the images in that :param:`model`, like
        ``image``.
    """
    env = api.Environment(cr, SUPERUSER_ID, {})
    with cr.savepoint():
        image_obj = env["base_multi_image.image"]
        images = image_obj.search([("owner_model", "=", model)], order="sequence, id")
        if images and field:
            main_images = {}
            for image in images:
                if image.owner_id not in main_images:
                    main_images[image.owner_id] = image
            main_images = main_images.values()
            model_obj = env[model]
            field_field = model_obj._fields[field]

            # fields.Binary(), save the binary content directly to the table
            if not field_field.attachment:
                save_directly_to_table(
                    cr,
                    model_obj,
                    field,
                    field_field,
                    main_images,
                )
            # fields.Binary(attachment=True), save the ir_attachment record ID
            if field and field_field.attachment:
                for main_image in main_images:
                    owner = model_obj.browse(main_image.owner_id)
                    field_field.write(owner, main_image.image_1920)
        images.unlink()


def save_directly_to_table(cr, Model, field, Field, main_images):
    fields = []
    if field and not Field.attachment:
        fields.append(field + " = " + "%(image)s")
    query = """
        UPDATE %(table)s
        SET %(fields)s
        WHERE id = %%(id)s
    """ % {
        "table": Model._table,
        "fields": ", ".join(fields),
    }
    for main_image in main_images:
        params = {"id": main_image.owner_id}
        if field and not Field.attachment:
            params["image"] = main_image.image_1920
        cr.execute(query, params)  # pylint: disable=sql-injection


def table_has_column(cr, table, field):
    query = """
        SELECT %(field)s
        FROM information_schema.columns
        WHERE table_name=%(table)s and column_name=%(field)s;
    """
    cr.execute(query, {"table": table, "field": field})
    return bool(cr.fetchall())
