import click
import logging
import json
from pathlib import Path
from base64 import b64encode
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from rich.console import Console
from rich.table import Table
from rich.pretty import pprint
from .main import cli


log = logging.getLogger("pymokusdk")


KEY_DIR = Path.home() / '.config/pymoku/keys'


def generate_private_key(name, overwrite=False):
    private_key = Ed25519PrivateKey.generate()
    KEY_DIR.mkdir(parents=True, exist_ok=True)
    keyfile = KEY_DIR / f'{name}.key'

    if keyfile.exists() and not overwrite:
        raise Exception(f"private key '{name}' already exists")

    keyfile.write_bytes(private_key.private_bytes_raw())
    log.info(f'wrote private key to {keyfile}')

    public_key = private_key.public_key()
    public_key_64 = b64encode(public_key.public_bytes_raw()).decode()
    return public_key_64


def load_private_key(keyname):
    key_bytes = (KEY_DIR / keyname).with_suffix('.key').read_bytes()
    return Ed25519PrivateKey.from_private_bytes(key_bytes)


def list_private_keys():
    for keyfile in KEY_DIR.glob('*.key'):
        private_key = load_private_key(keyfile.stem)
        yield (keyfile.stem, private_key)


def list_public_keys():
    for keyfile in KEY_DIR.glob('*.key'):
        private_key = load_private_key(keyfile.stem)
        public_key = private_key.public_key()
        public_key_64 = b64encode(public_key.public_bytes_raw()).decode()
        yield (keyfile.stem, public_key_64)


@cli.group()
def keys():
    pass


@keys.command('create')
@click.argument('name')
@click.option('-f', '--force', is_flag=True)
def create_key(name, force):
    public_key = generate_private_key(name, overwrite=force)
    pprint(f'Public Key: {name} {public_key}')


@keys.command('delete')
@click.argument('name')
def delete_key(name):
    keyfile = KEY_DIR / f'{name}.key'
    keyfile.unlink(missing_ok=True)


@keys.command('list')
@click.option('--json', '_json', is_flag=True, help='output keys as JSON')
def list_keys(_json=False):
    if _json:
        print(json.dumps(dict(list_public_keys())))
    else:
        table = Table()

        table.add_column("Key Name", justify="right", no_wrap=True)
        table.add_column("Public Key (base64)", no_wrap=True)

        for name, pubkey in list_public_keys():
            table.add_row(name, pubkey)

        console = Console()
        console.print(table)
