"""
3rd Party Libraries
Not much interesting here. We have some default imports for FastAPI endpoints and common SQL Alchemy use cases
"""
from fastapi import APIRouter, Body

from ehelply_microservice_library.integrations.fact import get_fact_endpoint
from ehelply_microservice_library.integrations.sdk import SDK

"""
eHelply Bootstrapper
Now we are getting interesting.
- State provides you with access to the app state
- get_db is used with Dependency injection to obtain a fresh DB connection session
    `db: Session = Depends(get_db)`
- Responses imports a bunch of default HTTP responses that eHelply has standardized on. Use these where possible as your
    return from each endpoint
"""
from ehelply_bootstrapper.utils.state import State

from ehelply_bootstrapper.drivers.fast_api_utils.responses import *

from ehelply_batcher.abstract_timer_service import AbstractTimerService
from ehelply_logger.Logger import Logger
import threading
import asyncio
import requests

"""
Router
This is a self-contained router instance. By itself it does nothing, but by attaching endpoints to it using decorator
  notation, you can make an epic router!
"""
router = APIRouter()


@router.post(
    '/keys/categories/{category_name}',
    tags=["keys"],
)
async def add_key(category_name: str, data: dict = Body({})):
    """
    Add a new key
    :return:
    """
    State.secrets.add(data['key'], category=category_name)

    return http_200_ok({"message": "Added key"})


@router.delete(
    '/keys/categories/{category_name}',
    tags=["keys"],
)
async def remove_key(category_name: str, data: dict = Body({})):
    """
    Add a new key
    :return:
    """
    State.secrets.remove(data['key'], category=category_name)

    return http_200_ok({"message": "Removed key"})


def get_encryption_keys(category: str, secret_key: str):
    return requests.get(
        get_fact_endpoint("ehelply-security") + f"/encryption/categories/{category}/keys",
        headers={'EHELPLY-SECURITY-SECRET-KEY': secret_key}
    ).json()


def create_encryption_key(category: str, secret_key: str):
    return requests.post(
        get_fact_endpoint("ehelply-security") + f"/encryption/categories/{category}/keys",
        headers={'EHELPLY-SECURITY-SECRET-KEY': secret_key}
    ).json()


async def refresh_encryption_keys(category: str):
    from ehelply_bootstrapper.utils.db_encryption import DBEncryption
    from ehelply_microservice_library.utils.secret_names import secret_name_security_vault

    secret_key: str = State.secrets.get(secret_name_security_vault())[0].secret_key

    keys: list = get_encryption_keys(category=category, secret_key=secret_key)

    if not keys:
        create_encryption_key(category=category, secret_key=secret_key)
        keys = get_encryption_keys(category=category, secret_key=secret_key)

    for key in keys:
        if not State.secrets.exists(secret=key['key'], category='database'):
            State.secrets.add(key['key'], category='database', prepend=True)
            DBEncryption.update_keys()


class SecurityKeys(AbstractTimerService):
    """
    Periodically checks for new or removed keys
    """

    def __init__(self, logger: Logger, delay_seconds: int, category: str):
        self.category: str = category

        super().__init__(
            name="SecurityKeys",
            delay_seconds=delay_seconds,
            logger=logger,
        )

    async def proc(self):
        await refresh_encryption_keys(category=self.category)


class SecurityKeysThread(threading.Thread):
    def __init__(self, logger: Logger, delay: int, category: str):
        super().__init__()
        self.timer: SecurityKeys = None
        self.logger = logger
        self.delay: int = delay
        self.category: str = category
        self.daemon = True

    def run(self) -> None:
        self.timer = SecurityKeys(
            logger=self.logger,
            delay_seconds=self.delay,
            category=self.category
        )
        asyncio.run(self.timer.run())
