#!/usr/bin/env python3
# -*- coding: latin-1 -*-

"""Get Terraform RUM statistics."""
import time
import csv
import requests


__version__ = "1.0.0"
__author__ = "Ahmad Ferdaus Abd Razak"


def get_subscription_rums(
    organization_name: str,
    token: str,
    api_url: str
) -> int:
    """Get subscription RUMs for an Organization."""
    endpoint = f"/organizations/{organization_name}/subscription"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/vnd.api+json",
    }
    response = requests.get(f"{api_url}/{endpoint}", headers=headers).json()

    rums = (
        response["data"]["attributes"]["contract-managed-resources-limit"]
        if response["data"]["attributes"]["contract-managed-resources-limit"] is not None else 500
    )

    return rums


def get_billable_rum(
    workspace_id: str,
    workspace_name: str,
    token: str,
    api_url: str
) -> int:
    """Get billable RUM for a Workspace."""
    print(f"Reading Workspace: {workspace_name}...")
    endpoint = f"/workspaces/{workspace_id}/current-state-version"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/vnd.api+json",
    }
    response = requests.get(f"{api_url}/{endpoint}", headers=headers).json()

    try:
        rum = response["data"]["attributes"]["billable-rum-count"]
    except KeyError:
        # This is to account for Workspaces with no data.
        rum = 0

    return rum


def get_workspace_data(
    organization_name: str,
    token: str,
    api_url: str,
    page_size: int,
    delay: float,
    quota: int
) -> dict:
    """Get Workspace data for an Organization."""
    full_list = []
    page = 1

    # Loop through the list pagination.
    while page is not None:

        endpoint = f"/organizations/{organization_name}/explorer"
        query = (
            f"page%5Bnumber%5D={page}"
            f"&page%5Bsize%5D={page_size}"
            f"&type=workspaces"
        )
        headers = {
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/vnd.api+json",
        }
        response = requests.get(f"{api_url}/{endpoint}?{query}", headers=headers).json()

        # Add data from current page to the full list.
        full_list.extend(
            [
                {
                    "id": workspace["id"],
                    "name": workspace["attributes"]["workspace-name"],
                    "rum": (
                        workspace["attributes"]["current-rum-count"]
                        if workspace["attributes"]["current-rum-count"] is not None else 0
                    ),
                    "billable_rum": get_billable_rum(
                        workspace["id"],
                        workspace["attributes"]["workspace-name"],
                        token,
                        api_url
                    )
                } for workspace in response["data"]
            ]
        )

        # Check next page for loop and stop if there's no more.
        page = response["meta"]["pagination"]["next-page"]

        # Terraform Cloud has an API call rate limit of 30 per second.
        time.sleep(delay)

    return {
        "data": full_list,
        "rum_sum": sum([workspace["rum"] for workspace in full_list]),
        "billable_rum_sum": sum([workspace["billable_rum"] for workspace in full_list]),
        "delta": quota - sum([workspace["billable_rum"] for workspace in full_list]),
        "usage_percentage": (
            sum([workspace["billable_rum"] for workspace in full_list]) / quota * 100
        )
    }


def create_csv(
    data: list,
    filename: str
) -> None:
    """Create CSV file from data."""
    with open(filename, "w", newline="") as file:
        writer = csv.writer(file)
        field = [
            "workspace_id",
            "workspace_name",
            "rum_count",
            "billable_rum_count"
        ]
        writer.writerow(field)
        for datapoint in data:
            writer.writerow(datapoint)


def main():
    """Execute main module."""
    import argparse

    # Get and parse command line arguments.
    myparser = argparse.ArgumentParser(
        add_help=True,
        allow_abbrev=False,
        description="Get Terraform RUM statistics.",
        usage="%(prog)s [options]"
    )
    myparser.add_argument(
        "-V",
        "--version",
        action="version",
        version=f"{__file__} {__version__}"
    )
    myparser.add_argument(
        "-o",
        "--organization",
        action="store",
        help="[REQUIRED] Terraform Cloud organization name",
        required=True,
        type=str
    )
    myparser.add_argument(
        "-t",
        "--token",
        action="store",
        help="[REQUIRED] Terraform Cloud API token",
        required=True,
        type=str
    )
    myparser.add_argument(
        "-f",
        "--filename",
        action="store",
        help="[OPTIONAL: default = report.csv] CSV report filename",
        required=False,
        default="report.csv",
        type=str
    )
    myparser.add_argument(
        "-u",
        "--url",
        action="store",
        help="[OPTIONAL: default = https://app.terraform.io/api/v2] Terraform Cloud API URL",
        required=False,
        default="https://app.terraform.io/api/v2",
        type=str
    )
    myparser.add_argument(
        "-p",
        "--page-size",
        action="store",
        help="[OPTIONAL: default = 50] number of items per page",
        required=False,
        default=50,
        type=int
    )
    myparser.add_argument(
        "-d",
        "--delay",
        action="store",
        help="[OPTIONAL: default = 0.0] delay (in seconds) between Workspaces",
        required=False,
        default=0.0,
        type=float
    )
    args = myparser.parse_args()
    organization = args.organization
    token = args.token
    filename = args.filename
    api_url = args.url
    page_size = args.page_size
    delay = args.delay

    # Print execution parameters.
    print("\nTerraform RUM Statistics")
    print("-------")
    print("Run parameters:")
    print(f"Organization: {organization}")
    print(f"Filename: {filename}")
    print(f"API URL: {api_url}")
    print(f"Page size: {page_size}")
    print(f"Delay: {delay}")
    print("-------")

    # Get subscription details for the Organization.
    quota = get_subscription_rums(organization, token, api_url)

    # Get RUMs.
    rums = get_workspace_data(
        organization,
        token,
        api_url,
        page_size,
        delay,
        quota
    )

    # Print results.
    print("-------")
    print(f"Workspaces: {len(rums['data'])}")
    print(f"Quota: {quota}")
    print(f"RUMs: {rums['rum_sum']}")
    print(f"Billable RUMs: {rums['billable_rum_sum']}")
    print(f"Delta: {rums['delta']}")
    print(f"Usage percentage: {rums['usage_percentage']:.2f}%")
    print("-------")
    print(f"Writing data to {filename}...\n")

    # Create CSV file from data.
    create_csv(
        [list(workspace.values()) for workspace in rums['data']],
        filename
    )
