"""
Solves some problems that can appear when transactions are not used and
a piece of code breaks, leaving the tree in an inconsistent state.

The problems this method solves are:

   1. Nodes with an incorrect ``depth`` or ``numchild`` values due to
      incorrect code and lack of database transactions.
   2. "Holes" in the tree. This is normal if you move/delete nodes a
      lot. Holes in a tree don't affect performance,
   3. Incorrect ordering of nodes when ``node_order_by`` is enabled.
      Ordering is enforced on *node insertion*, so if an attribute in
      ``node_order_by`` is modified after the node is inserted, the
      tree ordering will be inconsistent.
   4. Fix up parents_are_public state for categories.

:param destructive:

    A boolean value. If True, a more agressive fix_tree method will be
    attempted. If False (the default), it will use a safe (and fast!)
    fix approach, but it will only solve the ``depth`` and
    ``numchild`` nodes, it won't fix the tree holes or broken path
    ordering.

    .. warning::

       Currently what the ``destructive`` method does is:

       1. Backup the tree with :meth:`dump_data`
       2. Remove all nodes in the tree.
       3. Restore the tree with :meth:`load_data`

       So, even when the primary keys of your nodes will be preserved,
       this method isn't foreign-key friendly. That needs complex
       in-place tree reordering, not available at the moment (hint:
       patches are welcome).
"""

from django.core.management.base import BaseCommand

from oscar.core.loading import get_model

Category = get_model("catalogue", "Category")


class Command(BaseCommand):
    help = __doc__

    def add_arguments(self, parser):
        parser.add_argument(
            "--destructive",
            action="store_true",
            help="make sure to read the help before you use this",
        )

    def handle(self, *args, **options):
        Category.fix_tree(options["destructive"])
