import logging

from django.core.management import call_command
from django.db import connection
from uwsgidecoratorsfallback import spool

from oscar.core.loading import get_classes

logger = logging.getLogger(__name__)
(
    update_index_product,
    _update_index_products,
    update_index_category,
    _update_index_categories,
) = get_classes(
    "search.helpers",
    [
        "update_index_product",
        "update_index_products",
        "update_index_category",
        "update_index_categories",
    ],
)


@spool(pass_arguments=True)
def update_index_products(*product_ids):
    # the spooler is forked so the db connection might be closed
    try:
        if not connection.is_usable():
            connection.close()
    except AttributeError:
        connection.close_if_unusable_or_obsolete()

    _update_index_products(product_ids)


@spool(pass_arguments=True)
def update_index_categories(*category_ids):
    # the spooler is forked so the db connection might be closed
    try:
        if not connection.is_usable():
            connection.close()
    except AttributeError:
        connection.close_if_unusable_or_obsolete()

    _update_index_categories(category_ids)


@spool(pass_arguments=True)
def update_index(**kwargs):
    # the spooler is forked so the db connection might be closed
    try:
        if not connection.is_usable():
            connection.close()
    except AttributeError:
        connection.close_if_unusable_or_obsolete()

    category_id = kwargs.get("category_id")
    product_id = kwargs.get("product_id")

    if category_id is not None:
        update_index_category(category_id)

    if product_id is not None:
        update_index_product(product_id)


# pylint: disable=unused-argument
@spool
def update_oscar_index(arguments):
    # the spooler is forked so the db connection might be closed
    try:
        if not connection.is_usable():
            connection.close()
    except AttributeError:
        connection.close_if_unusable_or_obsolete()

    try:
        call_command("update_oscar_index")
    except Exception as e:  # pylint: disable=broad-except
        logger.exception(e)
