from __future__ import annotations

import os
from typing import List

import grpc
import typer
from rich.progress import Progress, SpinnerColumn, TextColumn

from remotivelabs.cli.broker.lib.broker import Broker
from remotivelabs.cli.broker.typer import ApiKeyOption, BrokerUrlOption
from remotivelabs.cli.typer_ext import typer_utils
from remotivelabs.cli.utils.console import print_generic_error, print_grpc_error, print_success

app = typer_utils.create_typer(help=help)


@app.command()
def reload_configuration(
    url: str = BrokerUrlOption,
    api_key: str = ApiKeyOption,
) -> None:
    try:
        broker = Broker(url, api_key)
        broker.reload_config()
        print_success("Configuration reloaded")
    except grpc.RpcError as err:
        print_grpc_error(err)


@app.command()
def delete(
    path: List[str] = typer.Argument(..., help="Paths to files on broker to delete"),
    exit_on_failure: bool = typer.Option(False, help="Exits if there was a problem deleting a file"),
    url: str = BrokerUrlOption,
    api_key: str = ApiKeyOption,
) -> None:
    """
    Deletes the specified files from the broker
    """
    try:
        broker = Broker(url, api_key)

        if len(path) == 0:
            print_generic_error("At least one path must be suppled")
            raise typer.Exit(1)

        broker.delete_files(path, exit_on_failure)
    except grpc.RpcError as err:
        print_grpc_error(err)


@app.command()
def download(
    path: str = typer.Argument(..., help="Path to file on broker to download"),
    output: str = typer.Option("", help="Optional output file name"),
    url: str = BrokerUrlOption,
    api_key: str = ApiKeyOption,
) -> None:
    """
    Downloads a file from a broker
    """
    try:
        with Progress(
            SpinnerColumn(),
            TextColumn("[progress.description]{task.description}"),
            transient=True,
        ) as progress:
            progress.add_task(description=f"Downloading {path}...", total=None)
            broker = Broker(url, api_key)
            output_file = os.path.basename(path)
            if output != "":
                output_file = output
            if os.path.exists(output_file):
                print_generic_error(f"File already exist {output_file}, please use another output file name")
            else:
                broker.download(path, output_file)
                print_success(f"{output_file} saved")
    except grpc.RpcError as err:
        print_grpc_error(err)


@app.command()
def upload(
    path: str = typer.Argument(..., help="Path to local file to upload"),
    output: str = typer.Option("", help="Optional output path on broker"),
    url: str = BrokerUrlOption,
    api_key: str = ApiKeyOption,
) -> None:
    """
    Uploads a file to a broker - physical or in cloud.
    """
    try:
        with Progress(
            SpinnerColumn(),
            TextColumn("[progress.description]{task.description}"),
            transient=True,
        ) as progress:
            progress.add_task(description=f"Uploading {path}...", total=None)

            if path == ".":
                path = "./"  ## Does not work otherwise

            if not os.path.exists(path):
                print_generic_error(f"File {path} does not exist")
                raise typer.Exit(1)

            broker = Broker(url, api_key)

            if os.path.isdir(path):
                broker.upload_folder(path)
                print_success(f"{path} uploaded")
            else:
                output_file = os.path.basename(path)
                if output != "":
                    output_file = output
                broker.upload(path, output_file)
                print_success(f"{path} uploaded")
    except grpc.RpcError as err:
        print_grpc_error(err)
