import subprocess
import argparse
from typing import Any
from requests import post

class Constants:
    MULTIPART_HEADER_CONTENT_TYPE = "multipart/form-data"
    REPORT_SCAN_RESULT_FILENAME = "container-sbom"

class SOOSSbomAnalysis:
    def __init__(self, args):
        self.api_key = args.apiKey
        self.client_id = args.clientId
        self.container_image = args.containerImage
        self.base_uri = args.apiURL

    def __generate_upload_results_url__(self, project_id: str, analysis_id: str) -> str:
        return f"{self.base_uri}/api/projects/{project_id}/analysis/{analysis_id}"

    def start_soos_analysis_request(self, extension) -> Any:
    # Open the SBOM file generated by the 'docker sbom' command.
        with open(f"{self.container_image}.{extension}", 'rb') as f:
            files = []
            files.append(("file" + str(1), (f.name, f)))

            # Construct headers
            headers = {
                'x-soos-apikey': self.api_key,
            }

            # Endpoint URL for the scan
            api_url = f"{self.base_uri}clients/{self.client_id}/quickscans/sbom"

            # Make the multipart/form-data POST request
            response = post(api_url, headers=headers, files=files)
            if response.ok:
                return response.json()
            else:
                raise Exception(f"Failed to start analysis: {response.text}")

    def open_results_file(self) -> str:
        with open(Constants.REPORT_SCAN_RESULT_FILENAME, 'r') as file:
            return file.read()

def main():
    parser = argparse.ArgumentParser(description="SOOS Container Analysis")
    parser.add_argument("--clientId", required=True, help="SOOS Client ID - get yours from https://app.soos.io/integrate/sca")
    parser.add_argument("--apiKey", required=True, help="SOOS API Key - get yours from https://app.soos.io/integrate/sca")
    parser.add_argument("--apiURL", default="https://api.soos.io/api/", required=False, help="SOOS API URL - Intended for internal use only, do not modify.")
    parser.add_argument("--format", default="spdx-json", required=False, help="SBOM format, cyclonedx-json or spdx-json")
    parser.add_argument("containerImage", help="Container Image to scan")

    args = parser.parse_args()

    analysis = SOOSSbomAnalysis(args)
    extension = "spdx.json"
    if args.format == "cyclonedx-json":
        extension = "cdx.json"

    try:
        print("Generating SBOM...")
        docker_command = f"docker sbom --format {args.format} --output {args.containerImage}.{extension} {analysis.container_image}"
        subprocess.run(docker_command, shell=True, check=True, capture_output=True)
    except Exception as exception:
        print(f"Failed to generate SBOM: {exception}")
        exit(1)
    print("SBOM Generated successfully")


    # Start Analysis
    print("Uploading SBOM to SOOS...")
    analysis_response = analysis.start_soos_analysis_request(extension=extension)
    scan_url = analysis_response.get('scanUrl', "Unknown URL")  # Extracting scanUrl

    print(f"Sbom has been uploaded, see results at {scan_url}")  # Displaying scanUrl
    
if __name__ == "__main__":
    main()