import os
from pathlib import Path

import pytest
from aioresponses import aioresponses
from pytest_mock import MockerFixture

from checkov.common.bridgecrew.vulnerability_scanning.integrations.package_scanning import package_scanning_integration


def get_report_url() -> str:
    base_url = "https://www.bridgecrew.cloud/api/v1/vulnerabilities"
    return f"{base_url}/results"


@pytest.mark.asyncio
async def test_report_results(mocker: MockerFixture, mock_bc_integration, package_scan_result):
    # given
    bc_api_key = "abcd1234-abcd-1234-abcd-1234abcd1234"
    report_url = get_report_url()

    mocker.patch.dict(os.environ, {"BC_ROOT_DIR": "app"})

    # when
    with aioresponses() as m:
        m.post(report_url, status=200)

        result = await package_scanning_integration.report_results_async(
            twistcli_scan_result=package_scan_result,
            bc_platform_integration=mock_bc_integration,
            bc_api_key=bc_api_key,
            file_path=Path("app/requirements.txt"),
        )

    # then
    assert result == 0
    assert next(iter(m.requests.values()))[0].kwargs["json"] == {
        "packageName": "requirements.txt",
        "packageFilePath": "/requirements.txt",
        "type": "Package",
        "sourceId": "bridgecrewio/checkov",
        "branch": "master",
        "sourceType": "Github",
        "vulnerabilities": [
            {
                "cveId": "CVE-2019-19844",
                "status": "fixed in 3.0.1, 2.2.9, 1.11.27",
                "severity": "critical",
                "packageName": "django",
                "packageVersion": "1.2",
                "link": "https://nvd.nist.gov/vuln/detail/CVE-2019-19844",
                "cvss": 9.8,
                "vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
                "description": "Django before 1.11.27, 2.x before 2.2.9, and 3.x before 3.0.1 allows account takeover.",
                "riskFactors": ["Critical severity", "Has fix", "Attack complexity: low", "Attack vector: network"],
                "publishedDate": "2019-12-18T20:15:00+01:00",
            },
        ],
        "packages": [
            {
                "type": "python",
                "name": "django",
                "version": "1.2",
                "licenses": []
            }
        ]
    }


@pytest.mark.asyncio
async def test_report_results_with_cicd(mocker: MockerFixture, mock_bc_integration, package_scan_result):
    # given
    bc_api_key = "abcd1234-abcd-1234-abcd-1234abcd1234"
    report_url = get_report_url()
    cicd_details = {
        "runId": 123,
        "pr": "patch-1",
        "commit": "qwerty1234",
    }

    mock_bc_integration.cicd_details = cicd_details
    mocker.patch.dict(os.environ, {"BC_ROOT_DIR": "app"})

    # when
    with aioresponses() as m:
        m.post(report_url, status=200)

        result = await package_scanning_integration.report_results_async(
            twistcli_scan_result=package_scan_result,
            bc_platform_integration=mock_bc_integration,
            bc_api_key=bc_api_key,
            file_path=Path("app/requirements.txt"),
        )

    # then
    assert result == 0
    assert next(iter(m.requests.values()))[0].kwargs["json"]["cicdDetails"] == cicd_details


@pytest.mark.asyncio
async def test_report_results_fail(mocker: MockerFixture, mock_bc_integration, package_scan_result):
    # given
    bc_api_key = "abcd1234-abcd-1234-abcd-1234abcd1234"
    report_url = get_report_url()

    mocker.patch.dict(os.environ, {"BC_ROOT_DIR": "app", "REQUEST_MAX_TRIES": "3", "SLEEP_BETWEEN_REQUEST_TRIES": "0.01"})

    # when
    with aioresponses() as m:
        m.post(report_url, status=403, repeat=True)

        result = await package_scanning_integration.report_results_async(
            twistcli_scan_result=package_scan_result,
            bc_platform_integration=mock_bc_integration,
            bc_api_key=bc_api_key,
            file_path=Path("app/requirements.txt"),
        )

    # then
    assert result == 1
