#!/var/www/html/api/v1/lib/venv/bin/python
import json
import os
import glob
import argparse

CONFIG = {}


def get_snapshots_by_export_timestamp(timestamp, field):
    """
    Get snapshots by export timestamp.

    Args:
        timestamp (str): The export file name is a timestamp.
        field (optional) - Specify field=coordinates to get the list of unique latitude and longitude pairs or field=user_agents to get the list of unique user agents instead of the full information listed below.

    Returns:
        tuple: A tuple containing the JSON response and the status code.
    """

    # Define the file directory and path
    f_dir = CONFIG["CRAWLER_EXPORT_DIR"]
    fpath = os.path.join(f_dir, str(timestamp) + ".json")
    
    if timestamp == 'latest':
        # Get a list of JSON files in the directory
        fpath = max(glob.iglob(f'{f_dir}*.json'))
        timestamp = os.path.basename(fpath).removesuffix(".json")


    result = {}
    try:
        with open(fpath, 'r') as file:
            # Load the contents of the file
            data = json.load(file)

            # Extract relevant information from the data based on the field parameter
            field = None if field not in ['coordinates', 'user_agents'] else field# Set field to None if invalid 
            # print(field)

            # Extract relevant information from the data
            result["timestamp"] = timestamp

            if len(data) == 0:
                return json.dumps(result), 200  # Return empty JSON response

            result["total_nodes"] = len(data)
            result["latest_height"] = data[-1][6]  # Height

            if field == 'coordinates':
                # Get the list of unique latitude and longitude pairs
                coordinates = set((item[10], item[11]) for item in data)
                result["coordinates"] = list(coordinates)
            elif field == 'user_agents':
                # Get the list of unique user agents
                user_agents = set(item[3] for item in data)
                result["user_agents"] = list(user_agents)
            else:
                # Get the full information for all nodes
                result["nodes"] = {}

                for item in data:
                    # Check if item has the correct length
                    if len(item) != 15:
                        result["error"] = "Incorrect item length"
                        return json.dumps(result), 400
                    
                    # Individual fields from the item array
                    # Ip_Address, Port, Protocol_version, User_agent, Connected_since, Services, Height, Hostname, City, Country_code, Latitude, Longitude, Timezone, ASN, Organization_name = item

                    # Store relevant information in the result dictionary
                    result["nodes"][item[0] + ":" + str(item[1])] = item[2:]

    except FileNotFoundError:
        result["error"] = "File not found"
        return json.dumps(result), 404

    return json.dumps(result), 200


def get_snapshots(limit=10, page=1):
    """
    Get a list of snapshots.

    Args:
        limit (int): The number of snapshots per page. Default is 10.
        page (int): The page number. Default is 1.

    Returns:
        tuple: A tuple containing the JSON response and the status code.
    """

    try:
        # Define the file directory and path
        f_dir = CONFIG["CRAWLER_EXPORT_DIR"]

        # Get a list of JSON files in the directory
        f_list = glob.glob(f'{f_dir}*.json')
        f_list.sort(reverse=True)

        # Validate the limit parameter type
        if not isinstance(limit, int):
            raise TypeError("Limit must be an integer")

        # Validate the page parameter type
        if not isinstance(page, int):
            raise TypeError("Page must be an integer")

        # Calculate the total number of pages
        total_snapshots = len(f_list)
        total_pages = (total_snapshots + limit - 1) // limit

        # Validate the page parameter
        if page < 1 or page > total_pages:
            raise ValueError("Invalid page number")

        # Calculate the start and end indices for the current page
        start_index = (page - 1) * limit
        end_index = start_index + limit

        # Create a list of snapshot results for the current page
        results = []
        for fpath in f_list[start_index:end_index]:
            entry = {}
            entry["timestamp"] = os.path.basename(fpath).removesuffix(".json")
            entry["url"] = CONFIG["API_BASE_URL"] + f"snapshots.php?timestamp={entry['timestamp']}"

            with open(fpath, 'r') as file:
                data = json.load(file)
                entry["total_nodes"] = len(data)
                entry["latest_height"] = data[-1][6]

            results.append(entry)

        # Create the API response dictionary
        response = {
            "count": total_snapshots,
            "results": results
        }

        # Add the "next" field to the response if there is a next page
        if page < total_pages:
            next_page = page + 1
            next_limit = "" if limit <= 10 else f"&limit={limit}"
            response["next"] = CONFIG["API_BASE_URL"] + f"/snapshots/?page={next_page}{next_limit}"
            # print(limit)
        else:
            response["next"] = None

        # Add the "previous" field to the response if there is a previous page
        if page > 1:
            previous_page = page - 1
            previous_limit = "" if limit <= 10 else f"&limit={limit}"
            response["previous"] = CONFIG["API_BASE_URL"] + f"/snapshots/?page={previous_page}{previous_limit}"
        else:
            response["previous"] = None

        return json.dumps(response), 200

    except TypeError as e:
        error_response = {"error": str(e)}
        return json.dumps(error_response), 400

    except ValueError as e:
        error_response = {"error": str(e)}
        return json.dumps(error_response), 400

    except Exception as e:
        error_response = {"error": "An error occurred while processing the request"}
        return json.dumps(error_response), 500


if __name__ == "__main__":
    with open("/var/www/html/api/v1/lib/config.json") as f:
        CONFIG = json.load(f)

    # Create an argument parser
    parser = argparse.ArgumentParser(description="API Manager")

    # Add the arguments
    parser.add_argument("--page", type=int, default=1, help="Page number")
    parser.add_argument("--limit", type=int, default=10, help="Number of snapshots per page")
    parser.add_argument("--timestamp", type=str, default='', help="List reachable nodes snapshot at timestamp")
    parser.add_argument("--field", type=str, default='', help="Specify field=coordinates to get the list of unique latitude and longitude pairs or field=user_agents to get the list of unique user agents instead of the full information listed below.")

    # Parse the arguments
    args = parser.parse_args()

    # Call the get_snapshots function with the specified page and limit
    # print(f"   args.page", args.page)
    # print(f"   args.limit", args.limit)
    # print(f"   args.timestamp", args.timestamp)
    if (args.timestamp):
        # print("--get_snapshots_by_export_timestamp--")
        response, status_code = get_snapshots_by_export_timestamp(timestamp=args.timestamp, field=args.field)
        print(response)
    else:
        # print("--get_snapshots-")
        response, status_code = get_snapshots(limit=args.limit, page=args.page)
        print(response)
