# -*- coding: utf-8 -*-
# Copyright: (c) 2020, Adam Migus <adam@migus.org>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function

__metaclass__ = type

DOCUMENTATION = r"""
name: tss
author: Adam Migus (@amigus) <adam@migus.org>
short_description: Get secrets from Thycotic Secret Server
version_added: 1.0.0
description:
    - Uses the Thycotic Secret Server Python SDK to get Secrets from Secret
      Server using token authentication with I(username) and I(password) on
      the REST API at I(base_url).
requirements:
    - python-tss-sdk - https://pypi.org/project/python-tss-sdk/
options:
    _terms:
        description: The integer ID of the secret.
        required: true
        type: int
    base_url:
        description: The base URL of the server, e.g. C(https://localhost/SecretServer).
        env:
            - name: TSS_BASE_URL
        ini:
            - section: tss_lookup
              key: base_url
        required: true
    username:
        description: The username with which to request the OAuth2 Access Grant.
        env:
            - name: TSS_USERNAME
        ini:
            - section: tss_lookup
              key: username
        required: true
    password:
        description: The password associated with the supplied username.
        env:
            - name: TSS_PASSWORD
        ini:
            - section: tss_lookup
              key: password
        required: true
    api_path_uri:
        default: /api/v1
        description: The path to append to the base URL to form a valid REST
            API request.
        env:
            - name: TSS_API_PATH_URI
        required: false
    token_path_uri:
        default: /oauth2/token
        description: The path to append to the base URL to form a valid OAuth2
            Access Grant request.
        env:
            - name: TSS_TOKEN_PATH_URI
        required: false
"""

RETURN = r"""
_list:
    description:
        - The JSON responses to C(GET /secrets/{id}).
        - See U(https://updates.thycotic.net/secretserver/restapiguide/TokenAuth/#operation--secrets--id--get).
    type: list
    elements: dict
"""

EXAMPLES = r"""
- hosts: localhost
  vars:
      secret: "{{ lookup('community.general.tss', 1) }}"
  tasks:
      - ansible.builtin.debug:
          msg: >
            the password is {{
              (secret['items']
                | items2dict(key_name='slug',
                             value_name='itemValue'))['password']
            }}

- hosts: localhost
  vars:
      secret: >-
        {{
            lookup(
                'community.general.tss',
                102,
                base_url='https://secretserver.domain.com/SecretServer/',
                username='user.name',
                password='password'
            )
        }}
  tasks:
      - ansible.builtin.debug:
          msg: >
            the password is {{
              (secret['items']
                | items2dict(key_name='slug',
                             value_name='itemValue'))['password']
            }}

- hosts: localhost
  vars:
      secret_password: >-
        {{ ((lookup('community.general.tss', 1) | from_json).get('items') | items2dict(key_name='slug', value_name='itemValue'))['password'] }}"
  tasks:
      - ansible.builtin.debug:
          msg: the password is {{ secret_password }}
"""
from distutils.version import LooseVersion
from ansible.errors import AnsibleError, AnsibleOptionsError

sdk_is_missing = False

try:
    from thycotic import __version__ as sdk_version
    from thycotic.secrets.server import (
        SecretServer,
        SecretServerError,
        PasswordGrantAuthorizer,
    )
except ImportError:
    sdk_is_missing = True

from ansible.utils.display import Display
from ansible.plugins.lookup import LookupBase


display = Display()


class LookupModule(LookupBase):
    @staticmethod
    def Client(server_parameters):

        if LooseVersion(sdk_version) < LooseVersion('1.0.0'):
            return SecretServer(**server_parameters)
        else:
            authorizer = PasswordGrantAuthorizer(
                server_parameters["base_url"],
                server_parameters["username"],
                server_parameters["password"],
                server_parameters["token_path_uri"],
            )

            return SecretServer(
                server_parameters["base_url"], authorizer, server_parameters["api_path_uri"]
            )

    def run(self, terms, variables, **kwargs):
        if sdk_is_missing:
            raise AnsibleError("python-tss-sdk must be installed to use this plugin")

        self.set_options(var_options=variables, direct=kwargs)

        secret_server = LookupModule.Client(
            {
                "base_url": self.get_option("base_url"),
                "username": self.get_option("username"),
                "password": self.get_option("password"),
                "api_path_uri": self.get_option("api_path_uri"),
                "token_path_uri": self.get_option("token_path_uri"),
            }
        )
        result = []

        for term in terms:
            display.debug("tss_lookup term: %s" % term)
            try:
                id = int(term)
                display.vvv(u"Secret Server lookup of Secret with ID %d" % id)
                result.append(secret_server.get_secret_json(id))
            except ValueError:
                raise AnsibleOptionsError("Secret ID must be an integer")
            except SecretServerError as error:
                raise AnsibleError("Secret Server lookup failure: %s" % error.message)
        return result