from django.shortcuts import reverse

import pytest
from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST, HTTP_404_NOT_FOUND

from baserow.core.handler import CoreHandler
from baserow.core.models import Workspace, WorkspaceUser
from baserow.test_utils.helpers import is_dict_subset


@pytest.mark.django_db
@pytest.mark.disabled_in_ci
def test_list_groups(api_client, data_fixture, group_compat_timebomb):
    user, token = data_fixture.create_user_and_token(
        email="test@test.nl", password="password", first_name="Test1"
    )
    user_workspace_2 = data_fixture.create_user_workspace(
        user=user, order=2, permissions="ADMIN"
    )
    user_workspace_1 = data_fixture.create_user_workspace(
        user=user, order=1, permissions="MEMBER"
    )
    data_fixture.create_workspace()

    response = api_client.get(
        reverse("api:groups:list"), **{"HTTP_AUTHORIZATION": f"JWT {token}"}
    )
    assert response.status_code == HTTP_200_OK
    response_json = response.json()
    assert len(response_json) == 2
    assert response_json[0]["id"] == user_workspace_1.workspace.id
    assert response_json[0]["order"] == 1
    assert response_json[0]["name"] == user_workspace_1.workspace.name
    assert response_json[0]["permissions"] == "MEMBER"
    assert response_json[1]["id"] == user_workspace_2.workspace.id
    assert response_json[1]["order"] == 2
    assert response_json[1]["name"] == user_workspace_2.workspace.name
    assert response_json[1]["permissions"] == "ADMIN"


@pytest.mark.django_db
@pytest.mark.disabled_in_ci
def test_list_groups_with_users(api_client, data_fixture, group_compat_timebomb):
    user, token = data_fixture.create_user_and_token(
        email="test@test.nl", password="password", first_name="Test1"
    )
    user_workspace_1 = data_fixture.create_user_workspace(
        user=user, order=1, permissions="MEMBER"
    )
    user_workspace_1_2 = data_fixture.create_user_workspace(
        order=1, permissions="ADMIN", workspace=user_workspace_1.workspace
    )
    user_workspace_1_3 = data_fixture.create_user_workspace(
        order=1, permissions="MEMBER", workspace=user_workspace_1.workspace
    )

    user_workspace_2 = data_fixture.create_user_workspace(
        user=user, order=2, permissions="ADMIN"
    )
    user_workspace_2_2 = data_fixture.create_user_workspace(
        order=2, permissions="MEMBER", workspace=user_workspace_2.workspace
    )

    response = api_client.get(
        reverse("api:groups:list"), **{"HTTP_AUTHORIZATION": f"JWT {token}"}
    )
    assert response.status_code == HTTP_200_OK
    response_json = response.json()

    expected_result = [
        {
            "id": user_workspace_1.workspace.id,
            "name": user_workspace_1.workspace.name,
            "order": 1,
            "permissions": "MEMBER",
            "users": [
                {
                    "email": user_workspace_1.user.email,
                    "group": user_workspace_1.workspace.id,
                    "id": user_workspace_1.id,
                    "name": user_workspace_1.user.first_name,
                    "permissions": "MEMBER",
                    "to_be_deleted": False,
                    "user_id": user_workspace_1.user.id,
                },
                {
                    "email": user_workspace_1_2.user.email,
                    "group": user_workspace_1_2.workspace.id,
                    "id": user_workspace_1_2.id,
                    "name": user_workspace_1_2.user.first_name,
                    "permissions": "ADMIN",
                    "to_be_deleted": False,
                    "user_id": user_workspace_1_2.user.id,
                },
                {
                    "email": user_workspace_1_3.user.email,
                    "group": user_workspace_1_3.workspace.id,
                    "id": user_workspace_1_3.id,
                    "name": user_workspace_1_3.user.first_name,
                    "permissions": "MEMBER",
                    "to_be_deleted": False,
                    "user_id": user_workspace_1_3.user.id,
                },
            ],
        },
        {
            "id": user_workspace_2.workspace.id,
            "name": user_workspace_2.workspace.name,
            "order": 2,
            "permissions": "ADMIN",
            "users": [
                {
                    "email": user_workspace_2.user.email,
                    "group": user_workspace_2.workspace.id,
                    "id": user_workspace_2.id,
                    "name": user_workspace_2.user.first_name,
                    "permissions": "ADMIN",
                    "to_be_deleted": False,
                    "user_id": user_workspace_2.user.id,
                },
                {
                    "email": user_workspace_2_2.user.email,
                    "group": user_workspace_2_2.workspace.id,
                    "id": user_workspace_2_2.id,
                    "name": user_workspace_2_2.user.first_name,
                    "permissions": "MEMBER",
                    "to_be_deleted": False,
                    "user_id": user_workspace_2_2.user.id,
                },
            ],
        },
    ]

    assert is_dict_subset(expected_result, response_json)


@pytest.mark.django_db
@pytest.mark.disabled_in_ci
def test_create_group(api_client, data_fixture, group_compat_timebomb):
    user, token = data_fixture.create_user_and_token()

    response = api_client.post(
        reverse("api:groups:list"),
        {"name": "Test 1"},
        format="json",
        HTTP_AUTHORIZATION=f"JWT {token}",
    )
    assert response.status_code == HTTP_200_OK
    json_response = response.json()
    workspace_user = WorkspaceUser.objects.filter(user=user.id).first()
    assert workspace_user.order == 1
    assert workspace_user.order == json_response["order"]
    assert workspace_user.workspace.id == json_response["id"]
    assert workspace_user.workspace.name == "Test 1"
    assert workspace_user.user == user

    response = api_client.post(
        reverse("api:groups:list"),
        {"not_a_name": "Test 1"},
        format="json",
        HTTP_AUTHORIZATION=f"JWT {token}",
    )
    assert response.status_code == HTTP_400_BAD_REQUEST


@pytest.mark.django_db
@pytest.mark.disabled_in_ci
def test_update_group(api_client, data_fixture, group_compat_timebomb):
    user, token = data_fixture.create_user_and_token()
    user_2, token_2 = data_fixture.create_user_and_token()
    workspace = data_fixture.create_workspace(user=user, name="Old name")
    data_fixture.create_user_workspace(
        user=user_2, workspace=workspace, permissions="MEMBER"
    )
    workspace_2 = data_fixture.create_workspace()

    url = reverse("api:groups:item", kwargs={"group_id": 99999})
    response = api_client.patch(
        url, {"name": "New name"}, format="json", HTTP_AUTHORIZATION=f"JWT {token}"
    )
    assert response.status_code == HTTP_404_NOT_FOUND
    assert response.json()["error"] == "ERROR_GROUP_DOES_NOT_EXIST"

    url = reverse("api:groups:item", kwargs={"group_id": workspace_2.id})
    response = api_client.patch(
        url, {"name": "New name"}, format="json", HTTP_AUTHORIZATION=f"JWT {token}"
    )
    assert response.status_code == HTTP_400_BAD_REQUEST
    assert response.json()["error"] == "ERROR_USER_NOT_IN_GROUP"

    url = reverse("api:groups:item", kwargs={"group_id": workspace.id})
    response = api_client.patch(
        url, {"name": "New name"}, format="json", HTTP_AUTHORIZATION=f"JWT {token_2}"
    )
    assert response.status_code == HTTP_400_BAD_REQUEST
    assert response.json()["error"] == "ERROR_USER_INVALID_GROUP_PERMISSIONS"

    url = reverse("api:groups:item", kwargs={"group_id": workspace.id})
    response = api_client.patch(
        url, {"name": "New name"}, format="json", HTTP_AUTHORIZATION=f"JWT {token}"
    )
    assert response.status_code == HTTP_200_OK
    json_response = response.json()

    workspace.refresh_from_db()

    assert workspace.name == "New name"
    assert json_response["id"] == workspace.id
    assert json_response["name"] == "New name"


@pytest.mark.django_db
@pytest.mark.disabled_in_ci
def test_leave_group(api_client, data_fixture, group_compat_timebomb):
    user, token = data_fixture.create_user_and_token()
    user_2, token_2 = data_fixture.create_user_and_token()
    workspace = data_fixture.create_workspace(name="Old name")
    data_fixture.create_user_workspace(
        user=user, workspace=workspace, permissions="MEMBER"
    )
    data_fixture.create_user_workspace(
        user=user_2, workspace=workspace, permissions="ADMIN"
    )
    workspace_2 = data_fixture.create_workspace()

    url = reverse("api:groups:leave", kwargs={"group_id": 99999})
    response = api_client.post(url, HTTP_AUTHORIZATION=f"JWT {token}")
    assert response.status_code == HTTP_404_NOT_FOUND
    assert response.json()["error"] == "ERROR_GROUP_DOES_NOT_EXIST"

    url = reverse("api:groups:leave", kwargs={"group_id": workspace_2.id})
    response = api_client.post(url, HTTP_AUTHORIZATION=f"JWT {token}")
    assert response.status_code == HTTP_400_BAD_REQUEST
    assert response.json()["error"] == "ERROR_USER_NOT_IN_GROUP"

    url = reverse("api:groups:leave", kwargs={"group_id": workspace.id})
    response = api_client.post(url, HTTP_AUTHORIZATION=f"JWT {token_2}")
    assert response.status_code == HTTP_400_BAD_REQUEST
    assert response.json()["error"] == "ERROR_GROUP_USER_IS_LAST_ADMIN"

    url = reverse("api:groups:leave", kwargs={"group_id": workspace.id})
    response = api_client.post(url, HTTP_AUTHORIZATION=f"JWT {token}")
    assert response.status_code == 204
    assert WorkspaceUser.objects.all().count() == 1
    assert not WorkspaceUser.objects.filter(user=user, workspace=workspace).exists()
    assert WorkspaceUser.objects.filter(user=user_2, workspace=workspace).exists()


@pytest.mark.django_db
@pytest.mark.disabled_in_ci
def test_delete_group(api_client, data_fixture, group_compat_timebomb):
    user, token = data_fixture.create_user_and_token()
    user_2, token_2 = data_fixture.create_user_and_token()
    workspace = data_fixture.create_workspace(user=user, name="Old name")
    data_fixture.create_user_workspace(
        user=user_2, workspace=workspace, permissions="MEMBER"
    )
    workspace_2 = data_fixture.create_workspace()

    url = reverse("api:groups:item", kwargs={"group_id": 99999})
    response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
    assert response.status_code == HTTP_404_NOT_FOUND
    assert response.json()["error"] == "ERROR_GROUP_DOES_NOT_EXIST"

    url = reverse("api:groups:item", kwargs={"group_id": workspace_2.id})
    response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
    assert response.status_code == HTTP_400_BAD_REQUEST
    assert response.json()["error"] == "ERROR_USER_NOT_IN_GROUP"

    url = reverse("api:groups:item", kwargs={"group_id": workspace.id})
    response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token_2}")
    assert response.status_code == HTTP_400_BAD_REQUEST
    assert response.json()["error"] == "ERROR_USER_INVALID_GROUP_PERMISSIONS"

    url = reverse("api:groups:item", kwargs={"group_id": workspace.id})
    response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
    assert response.status_code == 204
    assert Workspace.objects.all().count() == 1


@pytest.mark.django_db
@pytest.mark.disabled_in_ci
def test_reorder_groups(api_client, data_fixture, group_compat_timebomb):
    user, token = data_fixture.create_user_and_token()
    workspace_user_1 = data_fixture.create_user_workspace(user=user)
    workspace_user_2 = data_fixture.create_user_workspace(user=user)
    workspace_user_3 = data_fixture.create_user_workspace(user=user)

    url = reverse("api:groups:order")
    response = api_client.post(
        url,
        {
            "workspaces": [
                workspace_user_2.workspace.id,
                workspace_user_1.workspace.id,
                workspace_user_3.workspace.id,
            ]
        },
        format="json",
        HTTP_AUTHORIZATION=f"JWT {token}",
    )
    assert response.status_code == 204

    workspace_user_1.refresh_from_db()
    workspace_user_2.refresh_from_db()
    workspace_user_3.refresh_from_db()

    assert [1, 2, 3] == [
        workspace_user_2.order,
        workspace_user_1.order,
        workspace_user_3.order,
    ]


@pytest.mark.django_db
@pytest.mark.disabled_in_ci
def test_trashed_group_not_returned_by_views(
    api_client, data_fixture, group_compat_timebomb
):
    user, token = data_fixture.create_user_and_token(
        email="test@test.nl", password="password", first_name="Test1"
    )
    trashed_workspace = data_fixture.create_workspace(user=user)
    visible_workspace = data_fixture.create_workspace(user=user)

    CoreHandler().delete_workspace_by_id(user, trashed_workspace.id)

    response = api_client.get(
        reverse("api:groups:list"), **{"HTTP_AUTHORIZATION": f"JWT {token}"}
    )
    assert response.status_code == HTTP_200_OK
    response_json = response.json()
    assert len(response_json) == 1
    assert response_json[0]["id"] == visible_workspace.id
