"""workspace commands for cmem command line interface."""

import os
from http import HTTPStatus
from pathlib import Path

import click
from jinja2 import Template
from pygments import highlight
from pygments.formatters import get_formatter_by_name
from pygments.lexers import get_lexer_by_name

from cmem_cmemc import completion
from cmem_cmemc.command import CmemcCommand
from cmem_cmemc.command_group import CmemcGroup
from cmem_cmemc.commands.python import python
from cmem_cmemc.context import ApplicationContext
from cmem_cmemc.parameter_types.path import ClickSmartPath
from cmem_cmemc.smart_path import SmartPath
from cmem_cmemc.utils import check_acl_availability


@click.command(cls=CmemcCommand, name="export")
@click.option(
    "--replace",
    is_flag=True,
    help="Replace existing files. This is a dangerous option, so use it with care.",
)
@click.option(
    "--type",
    "marshalling_plugin",
    default="xmlZip",
    show_default=True,
    type=click.STRING,
    shell_complete=completion.marshalling_plugins,
    help="Type of the exported workspace file.",
)
@click.option(
    "--include-access-conditions",
    is_flag=True,
    help="Include access conditions in the exported archive.",
    hidden=True,
)
@click.option(
    "--filename-template",
    "-t",
    "template",
    default="{{date}}-{{connection}}.workspace",
    show_default=True,
    type=click.STRING,
    shell_complete=completion.workspace_export_templates,
    help="Template for the export file name. "
    "Possible placeholders are (Jinja2): "
    "{{connection}} (from the --connection option) and "
    "{{date}} (the current date as YYYY-MM-DD). "
    "The file suffix will be appended. "
    "Needed directories will be created.",
)
@click.argument(
    "file",
    shell_complete=completion.workspace_files,
    required=False,
    type=ClickSmartPath(writable=True, allow_dash=False, dir_okay=False),
)
@click.pass_obj
def export_command(  # noqa: PLR0913
    app: ApplicationContext,
    replace: bool,
    marshalling_plugin: str,
    include_access_conditions: bool,
    template: str,
    file: str,
) -> None:
    """Export the complete workspace (all projects) to a ZIP file.

    Depending on the requested export type, this ZIP file contains either one
    Turtle file per project (type `rdfTurtle`) or a substructure of resource
    files and XML descriptions (type `xmlZip`).

    The file name is optional and will be generated with by
    the template if absent.
    """
    check_acl_availability(app, include_access_conditions)
    if file is None:
        # prepare the template data and create the actual file incl. suffix
        template_data = app.get_template_data()
        file = Template(template).render(template_data) + ".zip"
    file = os.path.normpath(file)
    app.echo_info(f"Export workspace to {file} ... ", nl=False)
    if SmartPath(file).exists() and replace is not True:
        app.echo_error("file exists")
    else:
        SmartPath(file).parent.mkdir(parents=True, exist_ok=True)
        app.client.workspace.export_to_zip(
            path=Path(file),
            marshalling_plugin=marshalling_plugin,
            include_access_conditions=include_access_conditions,
        )
        app.echo_success("done")


@click.command(cls=CmemcCommand, name="import")
@click.option(
    "--type",
    "marshalling_plugin",
    default="xmlZip",
    show_default=True,
    type=click.STRING,
    shell_complete=completion.marshalling_plugins,
    help="Type of the exported workspace file.",
)
@click.option(
    "--include-access-conditions",
    is_flag=True,
    help="Include access conditions - if present in the workspace archive.",
    hidden=True,
)
@click.argument(
    "file",
    shell_complete=completion.workspace_files,
    type=ClickSmartPath(readable=True, allow_dash=False, dir_okay=False),
)
@click.pass_obj
def import_command(
    app: ApplicationContext, file: str, marshalling_plugin: str, include_access_conditions: bool
) -> None:
    """Import the workspace from a file."""
    check_acl_availability(app, include_access_conditions)
    app.echo_info(f"Import workspace from {file} ... ", nl=False)
    client = app.client
    client.workspace.import_from_zip(
        path=Path(file),
        marshalling_plugin=marshalling_plugin,
        include_access_conditions=include_access_conditions,
    )
    app.echo_success("done")


@click.command(cls=CmemcCommand, name="reload")
@click.pass_obj
def reload_command(app: ApplicationContext) -> None:
    """Reload the workspace from the backend."""
    app.echo_info("Reload workspace  ... ", nl=False)
    app.client.workspace.reload_workspace()
    app.echo_success("done")


@click.command(cls=CmemcCommand, name="thread-dump")
@click.pass_obj
def thread_dump_command(app: ApplicationContext) -> None:
    """Request a thread dump for all live threads."""
    client = app.client
    url = client.config.url_build_api / "/api/core/system/threadDump"
    response = client.http.get(url)
    if response.status_code == HTTPStatus.OK:
        message = highlight(
            response.text, get_lexer_by_name("java"), get_formatter_by_name("terminal")
        )
        app.echo_result(message)
    else:
        app.echo_error(f"Failed to retrieve thread dump. Status code: {response.status_code}")


@click.group(cls=CmemcGroup)
def workspace() -> CmemcGroup:  # type: ignore[empty-body]
    """Import, export and reload the project workspace."""


workspace.add_command(export_command)
workspace.add_command(import_command)
workspace.add_command(reload_command)
workspace.add_command(thread_dump_command)
workspace.add_command(python)
