#!/usr/bin/env python3

import json
import sys

import requests
import yaml


class GPLIClient:
    api_url = "https://glpi.{{domain}}/api.php/v1"
    ca_cert = "/etc/ssl/certs/{{domain}}-cacert.pem"

    def __init__(self):
        self.read_credentials()

    def read_credentials(self):
        with open("/var/www/fuss-data-conf/glpi.yaml") as fp:
            glpi_conf = yaml.safe_load(fp)
        try:
            self.app_token = glpi_conf["app_token"]
            self.user_token = glpi_conf["user_token"]
        except KeyError:
            print(
                "GLPI credentials not found "
                "in /var/www/fuss-data-conf/glpi.yaml",
                file=sys.stderr,
            )

            sys.exit(1)

    def get_token(self):
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"user_token {self.user_token}",
            "App-Token": self.app_token,
        }

        r = requests.get(
            f"{self.api_url}/initSession",
            verify=self.ca_cert,
            headers=headers,
        )

        if r.status_code == 200:
            self.token = json.loads(r.content)["session_token"]
            self.headers = {
                "Content-Type": "application/json",
                "Session-Token": self.token,
                "App-Token": self.app_token,
            }
        else:
            print(r.status_code, r.reason, file=sys.stderr)
            sys.exit(1)

    def discover_search_codes(self):
        url = f"{self.api_url}/listSearchOptions/Computer"
        r = requests.get(
            url,
            verify=self.ca_cert,
            headers=self.headers,
        )
        options = json.loads(r.content)

        self.search_fields = {}
        for k, v in options.items():
            try:
                uid = v.get("uid")
                name = v.get("name")
            except AttributeError:
                continue
            if uid == "Computer.name":
                self.search_fields["name"] = k
            elif uid == "Computer.id":
                self.search_fields["id"] = k
            elif uid == "Computer.NetworkPort.mac":
                self.search_fields["mac"] = k
            elif uid == "Computer.Group_Item.Group.completename" \
                    and name == "Group":
                self.search_fields["group"] = k
            elif uid == "Computer.Location.completename" \
                    and name == "Location":
                self.search_fields["location"] = k

    def search_and_print(self, criterion, names, prefix):
        for name in names:
            print(f"[{prefix}{name}]")
            url = (
                f"{self.api_url}/search/Computer?"
                "withindexes=true&"
                f"criteria[0][field]={self.search_fields[criterion]}&"
                "criteria[0][searchtype]=contains&"
                f"criteria[0][value]={name}"
            )
            r = requests.get(
                url,
                verify=self.ca_cert,
                headers=self.headers,
            )
            try:
                computers = json.loads(r.content)["data"]
            except KeyError:
                continue

            for i, c in computers.items():
                computer_name = c['1']
                print(f"    {computer_name}")

    def print_inventory(self):
        self.get_token()
        self.discover_search_codes()

        url = f"{self.api_url}/Location"
        r = requests.get(
            url,
            verify=self.ca_cert,
            headers=self.headers,
        )
        locations = json.loads(r.content)
        loc_names = [loc["name"] for loc in locations]

        self.search_and_print("location", loc_names, "")

        url = f"{self.api_url}/Group"
        r = requests.get(
            url,
            verify=self.ca_cert,
            headers=self.headers,
        )
        groups = json.loads(r.content)
        group_names = [g["name"] for g in groups]

        self.search_and_print("group", group_names, "group_")


if __name__ == "__main__":
    GPLIClient().print_inventory()
