"""Some utils for the ``django_instances_graph`` package."""

from django.db import models


def get_through_info(model, accessor_name):
    """Get some info about the through model in a m2m relation

    Parameters
    ----------
    model: type of models.Model
        The model on which we'll check a m2m or reverse m2m
    accessor_name: str
        The name of the attribute on `model` to access the m2m field or reverse m2m field.

    Returns
    -------
    tuple(type of models.Model, models.Field, models.Field, type of models.Model, str)
        0/ type of models.Model: ``through_model``: the django model representing the through
            relationship between the model and the m2m target, the through model being manually
            defined or auto-generated
        1/ models.Field: ``through_source_field``: the field on the through model which links to
            the source model (ie the `model` passed in argument)
        2/ models.Field: ``through_target_field``: the field on the through model which links to
            the target model (ie the model on the other side of the m2m relation)
        3/ type of models.Model: ``target_model``: the django model on the other side of the m2m
            relation
        4/ str:  ``target_accessor_name``: the name of the attribute on ``target_model`` to access
            the m2m field

    For ``through_source_field`` and ``through_target_field``, use ``.name`` to have the accessor
    name from the through model to the model, and ``.remote_field.get_accessor_name()`` to have
    the accessor name from the model to the through model.

    """

    # Get the field from the model
    field = model._meta.get_field(accessor_name)

    # The model on the other side of the m2m relation
    target_model = field.related_model

    # Different way to get the through model and the field name on ``target_model`` depending
    # on the "field" being a m2m field or a reverse m2m field

    if isinstance(field, models.ManyToManyField):
        # The field is defined on the model
        through_model = field.remote_field.through
        target_accessor_name = field.remote_field.related_name
    else:
        # We access a reverse m2m
        through_model = field.through
        target_accessor_name = field.field.name

    # ``get_path_info`` is the wah to get the fields on the through model to access the two models
    # on each side of the m2m relation
    path_info = field.get_path_info()
    through_source_field = path_info[0].join_field.field
    through_target_field = path_info[1].join_field

    # We return the whole information
    return (
        through_model,
        through_source_field,
        through_target_field,
        target_model,
        target_accessor_name,
    )


def is_through_model(source_model, accessor_name, through_model):
    """Helper to check if a model is the through model for a m2m relation

    Parameters
    ----------
    source_model: type of models.Model
        The model on which we'll check a m2m or reverse m2m
    accessor_name: str
        The name of the attribute on `model` to access the m2m field or reverse m2m field.
    through_model: models.Model
        The model to check.

    Returns
    -------
    bool
        ``True`` if `through_model` is the "through" model used for the `accessor_name` m2m (or
        reverse m2m) from `source_model`

    """
    return through_model is get_through_info(source_model, accessor_name)[0]
