import logging
import json
import requests

from zammad_pgp_import.utils import get_version
from zammad_pgp_import.pgp import PGPKey
from zammad_pgp_import.exceptions import ZammadError, ZammadPGPKeyAlreadyImportedError

logger = logging.getLogger(__name__)


class Zammad(object):
    session: requests.Session
    bsae_url: str

    def __init__(self, zammad_base_url: str, auth_token: str):
        self.base_url = zammad_base_url
        self.session = requests.Session()
        self.session.headers.update({"Authorization": f"Token token={auth_token}",
                                     "User-Agent": f"PGP auto-import webhook {get_version()}"})

    def get_all_imported_pgp_keys(self) -> list:
        """
        This is not used any more.  We just import and do net check if the key already exists before
        """
        logger.debug("Getting all imported PGP keys using Zammad API")
        try:
            resp = self.session.get(self.base_url + "/api/v1/integration/pgp/key")
            resp.raise_for_status()
            return resp.json()
        except requests.exceptions.RequestException as e:
            raise ZammadError(f"Could not get all imported PGP keys from Zammad: {e}")

    def get_tickets(self) -> list:
        logger.debug("Getting all tickets using Zammad API")
        tickets = []
        page_index = 1
        while True:
            try:
                params = {
                    "per_page": 100,
                    "page": page_index,
                }
                resp = self.session.get(self.base_url + "/api/v1/tickets/", params=params)
                resp.raise_for_status()
                len_results = len(resp.json())
                logger.debug(f"Got {len_results} tickets for page {page_index}")
                tickets.extend(resp.json())
                if len_results == 0:
                    logger.debug(f"Successfully got {len(tickets)} tickets via Zammad API")
                    return tickets
                page_index += 1
            except requests.exceptions.RequestException as e:
                if isinstance(e, requests.exceptions.HTTPError):
                    logger.error(f"Zammad API error: {e}")
                    raise ZammadError(f"Could not get tickets from Zammad: {e.response.json()['error_human']}")
                raise ZammadError(f"Could not get tickets from Zammad: {e}")

    def get_ticket(self, ticket_id: int) -> dict:
        logger.debug(f"Getting ticket {ticket_id} using Zammad API")
        try:
            resp = self.session.get(self.base_url + f"/api/v1/tickets/{ticket_id}")
            resp.raise_for_status()
            logger.debug("Successfully got ticket via Zammad API")
            return resp.json()
        except requests.exceptions.RequestException as e:
            if isinstance(e, requests.exceptions.HTTPError):
                logger.error(f"Zammad API error: {e}")
                raise ZammadError(f"Could not get ticket from Zammad: {e.response.json()['error_human']}")
            raise ZammadError(f"Could not get ticket from Zammad: {e}")

    def get_ticket_articles(self, ticket_id: int) -> list:
        logger.debug(f"Getting ticket articles of ticket {ticket_id} using Zammad API")
        try:
            resp = self.session.get(self.base_url + f"/api/v1/ticket_articles/by_ticket/{ticket_id}")
            resp.raise_for_status()
            logger.debug("Successfully got ticket articles via Zammad API")
            return resp.json()
        except requests.exceptions.RequestException as e:
            if isinstance(e, requests.exceptions.HTTPError):
                logger.error(f"Zammad API error: {e}")
                raise ZammadError(f"Could not get ticket articles from Zammad: {e.response.json()['error_human']}")
            raise ZammadError(f"Could not get ticket articles from Zammad: {e}")

    def get_user(self, user_id: int) -> dict:
        logger.debug(f"Getting user {user_id} using Zammad API")
        try:
            resp = self.session.get(self.base_url + f"/api/v1/users/{user_id}")
            resp.raise_for_status()
            logger.debug("Successfully got user via Zammad API")
            return resp.json()
        except requests.exceptions.RequestException as e:
            if isinstance(e, requests.exceptions.HTTPError):
                logger.error(f"Zammad API error: {e}")
                raise ZammadError(f"Could not get user from Zammad: {e.response.json()['error_human']}")
            raise ZammadError(f"Could not get user from Zammad: {e}")

    def download_attachment(self, ticket_id: int, article_id: int, attachment_id: int) -> str:
        logger.debug("Downloading ticket attachment using Zammad API")
        try:
            resp = self.session.get(self.base_url + f"/api/v1/ticket_attachment/{ticket_id}/{article_id}/{attachment_id}")
            resp.raise_for_status()
            logger.debug("Successfully downloaded email attachment")
            return resp.text
        except requests.exceptions.RequestException as e:
            if isinstance(e, requests.exceptions.HTTPError):
                logger.error(f"Zammad API error: {e}")
                raise ZammadError(f"Could not download attachment from Zammad: {e.response.json()['error_human']}")
            raise ZammadError(f"Could not download attachment from Zammad: {e}")

    def import_pgp_key(self, pgp_key: PGPKey) -> None:
        logger.debug("Importing PGP key using Zammad API")
        data = {'file': pgp_key.raw,
                'key': "",
                'passphrase': ""}
        try:
            resp = self.session.post(self.base_url + "/api/v1/integration/pgp/key", files=data)
            resp.raise_for_status()
        except requests.exceptions.RequestException as e:
            if isinstance(e, requests.exceptions.HTTPError) and e.response.status_code == 422:
                raise ZammadPGPKeyAlreadyImportedError(f"Key was already imported. API response: '{e.response.json()['error_human']}'")
            elif isinstance(e, requests.exceptions.HTTPError):
                logger.error(f"Zammad API error: {e}")
                logger.error(f"Request json:\n{json.dumps(data, indent=4)}")
                raise ZammadError(f"Could not import PGP key: '{e.response.json()['error_human']}'")
            raise ZammadError(f"Could not import PGP key: {e}")

    def delete_pgp_key(self, key_id: int) -> None:
        logger.debug(f"Deleting PGP key with key id {key_id} using Zammad API")
        try:
            resp = self.session.delete(self.base_url + f"/api/v1/integration/pgp/key/{key_id}")
            resp.raise_for_status()
            logger.info("Successfully deleted PGP in Zammad")
        except requests.exceptions.RequestException as e:
            logger.error(f"Could not delete PGP key in Zammad: {e}")
