"""The tests for the hassio component."""
import asyncio

from aiohttp import StreamReader
import pytest

from homeassistant.components.hassio.http import _need_auth


async def test_forward_request(hassio_client, aioclient_mock):
    """Test fetching normal path."""
    aioclient_mock.post("http://127.0.0.1/beer", text="response")

    resp = await hassio_client.post("/api/hassio/beer")

    # Check we got right response
    assert resp.status == 200
    body = await resp.text()
    assert body == "response"

    # Check we forwarded command
    assert len(aioclient_mock.mock_calls) == 1


@pytest.mark.parametrize(
    "build_type", ["supervisor/info", "homeassistant/update", "host/info"]
)
async def test_auth_required_forward_request(hassio_noauth_client, build_type):
    """Test auth required for normal request."""
    resp = await hassio_noauth_client.post(f"/api/hassio/{build_type}")

    # Check we got right response
    assert resp.status == 401


@pytest.mark.parametrize(
    "build_type",
    [
        "app/index.html",
        "app/hassio-app.html",
        "app/index.html",
        "app/hassio-app.html",
        "app/some-chunk.js",
        "app/app.js",
    ],
)
async def test_forward_request_no_auth_for_panel(
    hassio_client, build_type, aioclient_mock
):
    """Test no auth needed for ."""
    aioclient_mock.get(f"http://127.0.0.1/{build_type}", text="response")

    resp = await hassio_client.get(f"/api/hassio/{build_type}")

    # Check we got right response
    assert resp.status == 200
    body = await resp.text()
    assert body == "response"

    # Check we forwarded command
    assert len(aioclient_mock.mock_calls) == 1


async def test_forward_request_no_auth_for_logo(hassio_client, aioclient_mock):
    """Test no auth needed for logo."""
    aioclient_mock.get("http://127.0.0.1/addons/bl_b392/logo", text="response")

    resp = await hassio_client.get("/api/hassio/addons/bl_b392/logo")

    # Check we got right response
    assert resp.status == 200
    body = await resp.text()
    assert body == "response"

    # Check we forwarded command
    assert len(aioclient_mock.mock_calls) == 1


async def test_forward_request_no_auth_for_icon(hassio_client, aioclient_mock):
    """Test no auth needed for icon."""
    aioclient_mock.get("http://127.0.0.1/addons/bl_b392/icon", text="response")

    resp = await hassio_client.get("/api/hassio/addons/bl_b392/icon")

    # Check we got right response
    assert resp.status == 200
    body = await resp.text()
    assert body == "response"

    # Check we forwarded command
    assert len(aioclient_mock.mock_calls) == 1


async def test_forward_log_request(hassio_client, aioclient_mock):
    """Test fetching normal log path doesn't remove ANSI color escape codes."""
    aioclient_mock.get("http://127.0.0.1/beer/logs", text="\033[32mresponse\033[0m")

    resp = await hassio_client.get("/api/hassio/beer/logs")

    # Check we got right response
    assert resp.status == 200
    body = await resp.text()
    assert body == "\033[32mresponse\033[0m"

    # Check we forwarded command
    assert len(aioclient_mock.mock_calls) == 1


async def test_bad_gateway_when_cannot_find_supervisor(hassio_client, aioclient_mock):
    """Test we get a bad gateway error if we can't find supervisor."""
    aioclient_mock.get("http://127.0.0.1/addons/test/info", exc=asyncio.TimeoutError)

    resp = await hassio_client.get("/api/hassio/addons/test/info")
    assert resp.status == 502


async def test_forwarding_user_info(hassio_client, hass_admin_user, aioclient_mock):
    """Test that we forward user info correctly."""
    aioclient_mock.get("http://127.0.0.1/hello")

    resp = await hassio_client.get("/api/hassio/hello")

    # Check we got right response
    assert resp.status == 200

    assert len(aioclient_mock.mock_calls) == 1

    req_headers = aioclient_mock.mock_calls[0][-1]
    assert req_headers["X-Hass-User-ID"] == hass_admin_user.id
    assert req_headers["X-Hass-Is-Admin"] == "1"


async def test_backup_upload_headers(hassio_client, aioclient_mock, caplog):
    """Test that we forward the full header for backup upload."""
    content_type = "multipart/form-data; boundary='--webkit'"
    aioclient_mock.get("http://127.0.0.1/backups/new/upload")

    resp = await hassio_client.get(
        "/api/hassio/backups/new/upload", headers={"Content-Type": content_type}
    )

    # Check we got right response
    assert resp.status == 200

    assert len(aioclient_mock.mock_calls) == 1

    req_headers = aioclient_mock.mock_calls[0][-1]
    assert req_headers["Content-Type"] == content_type


async def test_backup_download_headers(hassio_client, aioclient_mock):
    """Test that we forward the full header for backup download."""
    content_disposition = "attachment; filename=test.tar"
    aioclient_mock.get(
        "http://127.0.0.1/backups/slug/download",
        headers={
            "Content-Length": "50000000",
            "Content-Disposition": content_disposition,
        },
    )

    resp = await hassio_client.get("/api/hassio/backups/slug/download")

    # Check we got right response
    assert resp.status == 200

    assert len(aioclient_mock.mock_calls) == 1

    assert resp.headers["Content-Disposition"] == content_disposition


def test_need_auth(hass):
    """Test if the requested path needs authentication."""
    assert not _need_auth(hass, "addons/test/logo")
    assert _need_auth(hass, "backups/new/upload")
    assert _need_auth(hass, "supervisor/logs")

    hass.data["onboarding"] = False
    assert not _need_auth(hass, "backups/new/upload")
    assert not _need_auth(hass, "supervisor/logs")


async def test_stream(hassio_client, aioclient_mock):
    """Verify that the request is a stream."""
    aioclient_mock.get("http://127.0.0.1/test")
    await hassio_client.get("/api/hassio/test", data="test")
    assert isinstance(aioclient_mock.mock_calls[-1][2], StreamReader)


async def test_entrypoint_cache_control(hassio_client, aioclient_mock):
    """Test that we return cache control for requests to the entrypoint only."""
    aioclient_mock.get("http://127.0.0.1/app/entrypoint.js")
    aioclient_mock.get("http://127.0.0.1/app/entrypoint.fdhkusd8y43r.js")

    resp1 = await hassio_client.get("/api/hassio/app/entrypoint.js")
    resp2 = await hassio_client.get("/api/hassio/app/entrypoint.fdhkusd8y43r.js")

    # Check we got right response
    assert resp1.status == 200
    assert resp2.status == 200

    assert len(aioclient_mock.mock_calls) == 2
    assert resp1.headers["Cache-Control"] == "no-store, max-age=0"

    assert "Cache-Control" not in resp2.headers
