import json
import logging
import shutil
import tempfile
import click
import yaml
import os
import base64
import glob

from .handlers.expression_handlers import handlers as exh
from .utils import process_refs
from .wflow import YadageWorkflow


def printRef(ref, dag, indent=""):
    click.secho(
        "{}name: {} position: {}, value: {}, id: {}".format(
            indent,
            dag.getNode(ref.stepid).name,
            ref.pointer.path,
            ref.pointer.resolve(dag.getNode(ref.stepid).result),
            ref.stepid,
        ),
        fg="cyan",
    )


def wflow_with_trivial_backend(instance):

    stateopts = {}
    wflow = YadageWorkflow.fromJSON(json.load(open(instance)), stateopts)
    return wflow


@click.group()
def utilcli():
    pass


@utilcli.command()
@click.argument("instance")
@click.argument("selection")
@click.option("--viewscope", default="")
@click.option("-v", "--verbosity", default="INFO")
def testsel(instance, selection, verbosity, viewscope):

    logging.basicConfig(
        level=getattr(logging, verbosity),
        format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    )

    wflow = wflow_with_trivial_backend(instance)

    selresult = exh["stage-output-selector"](
        wflow.view(viewscope), yaml.safe_load(selection)
    )

    if not selresult:
        click.secho("Bad selection {}".format(selresult), fg="red")
        return

    click.secho(
        json.dumps(
            process_refs(selresult, wflow.dag),
            sort_keys=True,
            indent=4,
            separators=(",", ": "),
        ),
        fg="green",
    )


@utilcli.command()
@click.argument("instance")
@click.argument("vizpdf")
@click.option("--viewscope", default="")
@click.option("-v", "--verbosity", default="INFO")
def viz(instance, vizpdf, viewscope, verbosity):
    logging.basicConfig(
        level=getattr(logging, verbosity),
        format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    )
    import yadage.visualize as visualize

    wflow = wflow_with_trivial_backend(instance)

    dirpath = tempfile.mkdtemp()
    visualize.write_prov_graph(dirpath, wflow, scope=viewscope)
    shutil.copy("{}/yadage_workflow_instance.pdf".format(dirpath), vizpdf)
    shutil.rmtree(dirpath)


@utilcli.group()
def k8s():
    pass


@k8s.command()
@click.option("--hostname", default="docker-for-desktop")
@click.option("--path", default=None)
def create_state(hostname, path):
    pvc_name = "yadagedata"
    sc_name = "local-storage"
    path_base = path or os.getcwd()
    size = "1G"
    kubeyaml = """\
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: {pvc_name}
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: {size}
  storageClassName: {sc_name}
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: {sc_name}
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: yadage-pv
spec:
  capacity:
    storage: {size}
  volumeMode: Filesystem
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  storageClassName: {sc_name}
  local:
    path: {path_base}
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - {hostname}
""".format(
        pvc_name=pvc_name,
        sc_name=sc_name,
        base_path=path_base,
        size=size,
        path_base=path_base,
        hostname=hostname,
    )
    click.echo(kubeyaml)


@k8s.command()
@click.option("--path")
def create_secrets(path):
    files = glob.glob("{}/*".format(path or os.environ["PACKTIVITY_AUTH_LOCATION"]))
    data = {
        os.path.basename(f): base64.b64encode(open(f, "rb").read()).decode("ascii")
        for f in files
    }
    secrets = """\
apiVersion: v1
data: {}
kind: Secret
metadata:
  name: hepauth
  namespace: default
type: Opaque
""".format(
        json.dumps(data)
    )
    click.echo(secrets)


if __name__ == "__main__":
    utilcli()
