# -*- coding: utf-8 -*-
import click
import os
import sys
import typing
from rich import box
from rich.panel import Panel
from rich.table import Table

from kiara import Kiara
from kiara.operations import OperationType
from kiara.utils import log_message
from kiara.utils.output import rich_print


@click.group()
@click.pass_context
def operation(ctx):
    """Metadata-related sub-commands."""


@operation.command(name="list")
@click.option(
    "--by-type", "-t", is_flag=True, help="List the operations by operation type."
)
@click.argument("filter", nargs=-1, required=False)
@click.option(
    "--full-doc", "-d", is_flag=True, help="Display the full doc for all operations."
)
@click.option(
    "--omit-default",
    "-o",
    is_flag=True,
    help="Don't list operations that have no specific operation type associated with them.",
)
@click.pass_context
def list(
    ctx, by_type: bool, filter: typing.Iterable[str], full_doc: bool, omit_default: bool
):

    kiara_obj: Kiara = ctx.obj["kiara"]

    if by_type:
        title = "Operations by type"
        all_operations_types = kiara_obj.operation_mgmt.operation_types

        table = Table(box=box.SIMPLE, show_header=True)
        table.add_column("Type", no_wrap=True, style="b green")
        table.add_column("Id", no_wrap=True)
        table.add_column("Description", no_wrap=False, style="i")

        for operation_name in sorted(all_operations_types.keys()):

            if operation_name == "all":
                continue

            operation_details: OperationType = all_operations_types[operation_name]
            first_line_value = True

            for op_id, op_config in sorted(operation_details.operation_configs.items()):

                if full_doc:
                    desc = op_config.doc.full_doc
                else:
                    desc = op_config.doc.description

                if filter:
                    match = True
                    for f in filter:
                        if (
                            f.lower() not in operation_name.lower()
                            and f.lower() not in op_id.lower()
                            and f.lower() not in desc.lower()
                        ):
                            match = False
                            break
                    if not match:
                        continue

                row = []
                if first_line_value:
                    row.append(operation_name)
                else:
                    row.append("")

                row.append(op_id)
                row.append(desc)

                table.add_row(*row)
                first_line_value = False

    else:
        title = "All operations"
        table = Table(box=box.SIMPLE, show_header=True)
        table.add_column("Id", no_wrap=True, style="b")
        table.add_column("Type(s)", style="green")
        table.add_column("Description", style="i")

        for op_id, config in kiara_obj.operation_mgmt.profiles.items():

            types = kiara_obj.operation_mgmt.get_types_for_id(op_id)

            if omit_default and len(types) == 1:
                continue

            types.remove("all")

            if full_doc:
                desc = config.doc.full_doc
            else:
                desc = config.doc.description
            # desc = config.module_cls.get_type_metadata().documentation.description
            if filter:
                match = True
                for f in filter:
                    if f.lower() not in op_id.lower() and f.lower() not in desc.lower():
                        match = False
                        break
                if match:
                    table.add_row(op_id, ", ".join(types), desc)

            else:
                table.add_row(op_id, ", ".join(types), desc)

    panel = Panel(table, title=title, title_align="left", box=box.ROUNDED)
    rich_print(panel)


@operation.command()
@click.argument("operation_id", nargs=1, required=True)
@click.option(
    "--source",
    "-s",
    help="Show module source code (or pipeline configuration).",
    is_flag=True,
)
@click.pass_context
def explain(ctx, operation_id: str, source: bool):

    kiara_obj: Kiara = ctx.obj["kiara"]

    if os.path.isfile(os.path.realpath(operation_id)):
        try:
            _operation_id = kiara_obj.register_pipeline_description(data=operation_id)
            if _operation_id is None:
                print(
                    f"Unknown error when trying to import '{operation_id}' as pipeline."
                )
                sys.exit(1)
            else:
                operation_id = _operation_id
        except Exception as e:
            log_message(f"Tried to import '{operation_id}' as pipeline, failed: {e}")

    op_config = kiara_obj.operation_mgmt.profiles.get(operation_id)
    if not op_config:
        print()
        print(f"No operation with id '{operation_id}' registered.")
        sys.exit(1)

    print()
    rich_print(
        op_config.create_panel(
            title=f"Operation: [b i]{operation_id}[/b i]", include_src=source
        )
    )
