from webtest import TestApp

import pytest
from mekansm import handlers, adapters


def get_app(request, ctx):
    app = handlers.wsgi_app(ctx)
    return TestApp(app)


def sample_deployment_payload():
    return {
        "data": {
            "type": "deployments",
            "attributes": {
                "nodes": [
                    {"dc": "SFO", "nodes": ["server-1", "server-2"]},
                    {"dc": "LIM", "nodes": ["slow-server"]},
                    {"dc": "SEA", "nodes": [""]}
                ],
                "repository": "mekansm",
                "owner": "dta",
                "triggered_by": "Kappa",
                "environment": "staging",
                "sha": "KappaKappaKappa",
                "account": "aws-account-id",
                "application": "dta-mekansm",
                "group": "dta-mekansm-staging",
                "s3location": "myartifacts/dta/Mekansm",
                "bundletype": "tgz",
                "config": "CodeDeployDefault.AllAtOnce"
            }
        }
    }


def dummy_context(mekansm_dbconf):
    return adapters.Context({"database": mekansm_dbconf})


def test_handlers_have_root(request, mekansm_dbconf):
    app = get_app(request, dummy_context(mekansm_dbconf))
    resp = app.get("/", headers={"Accept": "application/vnd.api+json"})
    assert resp.status_int == 200
    assert resp.content_type == "application/json"


def test_post_new_deployment_without_account(request, mekansm_dbconf):
    app = get_app(request, dummy_context(mekansm_dbconf))
    payload = sample_deployment_payload()
    resp = app.post_json("/deployments/", payload, expect_errors=True)
    assert resp.status_int == 404


def test_post_new_deployment(request, mekansm_dbconf):
    ctx = adapters.Context({"database": mekansm_dbconf})
    deployment_id = "d-Kappa"

    class StubCodeDeploy:

        profile_name = "aws-account-id"
        expected_status = "Created"

        def create_deployment(self, deployment_data):
            return deployment_id

        def get_deployment(self, deployment_id):
            return {
                "deploymentInfo": {
                    "status": self.expected_status
                }
            }

    cd_stub = StubCodeDeploy()
    ctx.aws.accounts = [cd_stub]
    app = get_app(request, ctx)
    payload = sample_deployment_payload()
    resp = app.post_json("/deployments/", payload)
    assert resp.status_int == 201
    assert "Location" in resp.headers
    deployment_location = resp.headers["Location"]
    assert resp.json["data"]["id"] == deployment_id

    resp = app.get("/deployments/")
    assert resp.status_int == 200
    deployments = resp.json["data"]
    assert len(deployments) == 1
    assert deployments[0]["id"] == deployment_id

    cd_stub.expected_status = "InProgress"
    resp = app.get(deployment_location)
    assert resp.status_int == 200
    assert resp.json["data"]["id"] == deployment_id
    assert resp.json["data"]["attributes"]["status"] == "InProgress"

    new_status = "Failed"
    cd_stub.expected_status = new_status
    patch_payload = {
        "data": {
            "type": "deployments",
            "id": deployment_id,
            "attributes": {"status": new_status}
        }
    }
    resp = app.patch_json(deployment_location, patch_payload)
    assert resp.status_int == 200
    assert resp.json["data"]["id"] == deployment_id
    assert resp.json["data"]["attributes"]["status"] == new_status

    resp = app.get(deployment_location)
    assert resp.status_int == 200
    assert resp.json["data"]["id"] == deployment_id
    assert resp.json["data"]["attributes"]["status"] == new_status
