from .. import context
from ..input_helpers import (
    get_org_from_input_or_ctx,
    strip_none,
    build_updated_model_validate,
)
import agilicus
from ..output.table import (
    spec_column,
    format_table,
    metadata_column,
    column,
    subtable,
)


def add_label(ctx, name, **kwargs):
    token = context.get_token(ctx)
    apiclient = context.get_apiclient(ctx, token)
    kwargs["org_id"] = get_org_from_input_or_ctx(ctx, **kwargs)
    kwargs = strip_none(kwargs)

    spec = agilicus.LabelSpec(name=agilicus.LabelName(name), **kwargs)

    label = agilicus.Label(spec=spec)
    return apiclient.labels_api.create_object_label(label).to_dict()


def list_labels(ctx, name, **kwargs):
    token = context.get_token(ctx)
    apiclient = context.get_apiclient(ctx, token)
    kwargs["org_id"] = get_org_from_input_or_ctx(ctx, **kwargs)
    kwargs = strip_none(kwargs)
    if name is not None:
        kwargs["label_name"] = agilicus.LabelName(name)

    return apiclient.labels_api.list_object_labels(**kwargs).labels


def get_label(ctx, **kwargs):
    token = context.get_token(ctx)
    apiclient = context.get_apiclient(ctx, token)
    kwargs["org_id"] = get_org_from_input_or_ctx(ctx, **kwargs)
    kwargs = strip_none(kwargs)

    return apiclient.labels_api.get_object_label(**kwargs)


def delete_label(ctx, **kwargs):
    token = context.get_token(ctx)
    apiclient = context.get_apiclient(ctx, token)
    kwargs["org_id"] = get_org_from_input_or_ctx(ctx, **kwargs)
    kwargs = strip_none(kwargs)

    apiclient.labels_api.delete_object_label(**kwargs)


def replace_label(ctx, label_id, org_id, **kwargs):
    token = context.get_token(ctx)
    apiclient = context.get_apiclient(ctx, token)
    org_id = get_org_from_input_or_ctx(ctx, org_id=org_id)
    kwargs = strip_none(kwargs)

    label = apiclient.labels_api.get_object_label(label_id=label_id, org_id=org_id)
    kwargs["org_id"] = org_id

    label.spec = build_updated_model_validate(
        agilicus.LabelSpec,
        label.spec,
        kwargs,
        True,
    )

    return apiclient.labels_api.replace_object_label(label_id, label=label)


def format_labels(ctx, labels):
    columns = [
        metadata_column("id"),
        spec_column("org_id"),
        spec_column("name"),
        spec_column("description"),
    ]

    return format_table(ctx, labels, columns)


def add_labelled_object(ctx, label, object_type, **kwargs):
    token = context.get_token(ctx)
    apiclient = context.get_apiclient(ctx, token)
    kwargs["org_id"] = get_org_from_input_or_ctx(ctx, **kwargs)
    kwargs = strip_none(kwargs)

    if object_type is not None:
        kwargs["object_type"] = agilicus.ObjectType(object_type)

    labels = _label_associations_to_list(label, kwargs["org_id"])
    obj = agilicus.LabelledObject(labels=labels, **kwargs)

    return apiclient.labels_api.create_labelled_object(obj).to_dict()


def list_labelled_objects(
    ctx, includes_any_label, excludes_any_label, object_type, **kwargs
):
    token = context.get_token(ctx)
    apiclient = context.get_apiclient(ctx, token)
    kwargs["org_id"] = get_org_from_input_or_ctx(ctx, **kwargs)
    kwargs = strip_none(kwargs)
    if includes_any_label is not None:
        kwargs["includes_any_label"] = _labels_to_list(includes_any_label)
    if excludes_any_label is not None:
        kwargs["excludes_any_label"] = _labels_to_list(excludes_any_label)
    if object_type is not None:
        kwargs["object_type"] = agilicus.ObjectType(object_type)

    return apiclient.labels_api.list_labelled_objects(**kwargs).labelled_objects


def _label_associations_to_list(labels, org_id):
    return [
        agilicus.LabelAssociation(
            label_name=agilicus.LabelName(label),
            org_id=org_id,
        )
        for label in labels
    ]


def _labels_to_list(labels):
    return [agilicus.LabelName(label) for label in labels]


def get_labelled_object(ctx, object_id, **kwargs):
    token = context.get_token(ctx)
    apiclient = context.get_apiclient(ctx, token)
    kwargs["org_id"] = get_org_from_input_or_ctx(ctx, **kwargs)
    kwargs = strip_none(kwargs)

    return apiclient.labels_api.get_labelled_object(
        labelled_object_id=object_id, **kwargs
    )


def delete_labelled_object(ctx, object_id, **kwargs):
    token = context.get_token(ctx)
    apiclient = context.get_apiclient(ctx, token)
    kwargs["org_id"] = get_org_from_input_or_ctx(ctx, **kwargs)
    kwargs = strip_none(kwargs)

    apiclient.labels_api.delete_labelled_object(labelled_object_id=object_id, **kwargs)


def replace_labelled_object(ctx, label, object_id, **kwargs):
    token = context.get_token(ctx)
    apiclient = context.get_apiclient(ctx, token)
    kwargs["org_id"] = get_org_from_input_or_ctx(ctx, **kwargs)
    kwargs = strip_none(kwargs)

    obj = apiclient.labels_api.get_labelled_object(
        labelled_object_id=object_id, **kwargs
    )
    if not label:
        return obj

    obj.labels = _label_associations_to_list(label, kwargs["org_id"])
    return apiclient.labels_api.replace_labelled_object(
        obj.object_id, labelled_object=obj
    )


def format_labelled_objects(ctx, objs):
    labels = [
        column("label_name"),
    ]

    columns = [
        column("org_id"),
        column("object_id"),
        column("object_type"),
        subtable(ctx, "labels", labels),
    ]

    return format_table(ctx, objs, columns)


def add_labelled_object_label(ctx, label, object_id, org_id, **kwargs):
    token = context.get_token(ctx)
    apiclient = context.get_apiclient(ctx, token)
    org_id = get_org_from_input_or_ctx(ctx, org_id=org_id)
    assoc = agilicus.LabelAssociation(
        label_name=agilicus.LabelName(label), org_id=org_id
    )

    return apiclient.labels_api.create_labelled_object_label(object_id, assoc, **kwargs)


def delete_labelled_object_label(ctx, label, object_id, **kwargs):
    token = context.get_token(ctx)
    apiclient = context.get_apiclient(ctx, token)
    kwargs["org_id"] = get_org_from_input_or_ctx(ctx, **kwargs)
    kwargs = strip_none(kwargs)

    return apiclient.labels_api.delete_labelled_object_label(
        labelled_object_id=object_id, label_name=label, **kwargs
    )
