"""
This file (test_admin.py) contains the functional tests for
the `admin` blueprint.

These tests use GETs and POSTs to different endpoints to check
for the proper behavior of the `admin` blueprint.
"""
import json
import os

import pytest
from flask import request
from flask import url_for
from modules.box__default.auth.models import Role
from modules.box__default.auth.models import role_user_bridge
from modules.box__default.auth.models import User


dirpath = os.path.dirname(os.path.abspath(__file__))
module_path = os.path.dirname(dirpath)

module_info = None


# class TestAdminInvalidAccess:
#     """
#     Test all admin routes for correct user authentication
#     """

#     routes_get = [
#         "/",
#         "/add",
#         "/delete/<id>",
#         "/edit/<id>",
#         "/roles",
#         "/roles/<role_id>/delete",
#     ]

#     routes_post = ["/update", "/roles/update", "/roles/add", "/add"]

#     @pytest.mark.parametrize("route", routes_get)
#     def test_redirect_if_not_logged_in_get(self, test_client, route, auth):
#         auth.logout()
#         with open(os.path.join(module_path, "info.json")) as f:
#             module_info = json.load(f)
#         response = test_client.get(
#             f"{module_info['url_prefix']}{route}", follow_redirects=True
#         )

#         assert response.status_code == 200
#         assert request.path == url_for("auth.login")

#     @pytest.mark.parametrize("route", routes_post)
#     def test_redirect_if_not_logged_in_post(self, test_client, route, auth):
#         auth.logout()
#         with open(os.path.join(module_path, "info.json")) as f:
#             module_info = json.load(f)
#         response = test_client.post(
#             f"{module_info['url_prefix']}{route}", follow_redirects=True
#         )

#         assert response.status_code == 200
#         assert request.path == url_for("auth.login")

#     @pytest.mark.usefixtures("login_non_admin_user")
#     @pytest.mark.parametrize("route", routes_get)
#     def test_no_admin_access_if_not_admin_get(self, test_client, route):
#         with open(os.path.join(module_path, "info.json")) as f:
#             module_info = json.load(f)
#         response = test_client.get(
#             f"{module_info['url_prefix']}{route}", follow_redirects=True
#         )

#         assert response.status_code == 200
#         assert request.path == url_for("dashboard.index")
#         assert b"You need to be an admin to view this page" in response.data

#     @pytest.mark.usefixtures("login_non_admin_user")
#     @pytest.mark.parametrize("route", routes_post)
#     def test_no_admin_access_if_not_admin_post(self, test_client, route):
#         with open(os.path.join(module_path, "info.json")) as f:
#             module_info = json.load(f)
#         response = test_client.post(
#             f"{module_info['url_prefix']}{route}", follow_redirects=True
#         )

#         assert response.status_code == 200
#         assert request.path == url_for("dashboard.index")
#         assert b"You need to be an admin to view this page" in response.data


@pytest.mark.usefixtures("login_admin_user")
class TestAdminEndpoints:
    """
    Test all admin api post and get requests
    """

    # def test_admin_user_list_get(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     response = test_client.get(f"{module_info['url_prefix']}/")

    #     assert response.status_code == 200
    #     assert b"Admin" in response.data
    #     assert b"id" in response.data
    #     assert b"Email" in response.data
    #     assert b"Password" in response.data
    #     assert b"Roles" in response.data

    # def test_admin_add_get(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     response = test_client.get(f"{module_info['url_prefix']}/add")

    #     assert response.status_code == 200
    #     assert b"Email" in response.data
    #     assert b"Password" in response.data
    #     assert b"First Name" in response.data
    #     assert b"Last Name" in response.data
    #     assert b"Admin User" in response.data

    # def test_admin_add_unique_user_post(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     role1 = Role.create(name="test1-role")
    #     role2 = Role.create(name="test2-role")
    #     data = {
    #         "email": "test@gmail.com",
    #         "password": "pass",
    #         "first_name": "Test",
    #         "last_name": "User",
    #         "is_admin": "",
    #         f"role_{role1.id}": "",
    #         f"role_{role2.id}": "",
    #     }

    #     test_client.post(
    #         f"{module_info['url_prefix']}/add",
    #         data=data,
    #         follow_redirects=True,
    #     )
    #     test_user = User.query.filter(User.email == "test@gmail.com").scalar()

    #     assert test_user is not None
    #     assert test_user.first_name == "Test"
    #     assert test_user.last_name == "User"
    #     assert test_user.is_admin is False
    #     assert test_user.roles is not None
    #     assert len(test_user.roles) == 2
    #     assert role1.users[0].email == "test@gmail.com"
    #     assert role2.users[0].email == "test@gmail.com"

    # def test_admin_add_existing_user_post(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     User.create(email="test@gmail.com", password="pass")
    #     data = {
    #         "email": "test@gmail.com",
    #         "password": "pass",
    #         "first_name": "Test",
    #         "last_name": "User",
    #         "is_admin": "",
    #     }

    #     response = test_client.post(
    #         f"{module_info['url_prefix']}/add",
    #         data=data,
    #         follow_redirects=True,
    #     )
    #     test_users = User.query.filter(User.email == "test@gmail.com").count()

    #     assert response.status_code == 200
    #     assert b"User with same email already exists" in response.data
    #     assert test_users == 1

    # def test_admin_delete_existing_user_get(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     user = User(email="test@gmail.com", password="pass")
    #     role1 = Role(name="test1-role")
    #     role2 = Role(name="test2-role")
    #     user.roles = [role1, role2]
    #     user.save()

    #     response = test_client.get(
    #         f"{module_info['url_prefix']}/delete/{user.id}",
    #         follow_redirects=True,
    #     )
    #     test_user = User.query.filter(User.email == user.email).scalar()
    #     test_roles = Role.query.count()
    #     user_role = (
    #         User.query.join(role_user_bridge)
    #         .join(Role)
    #         .filter(User.id == user.id)
    #         .scalar()
    #     )

    #     assert response.status_code == 200
    #     assert test_user is None
    #     assert user_role is None
    #     assert test_roles == 2

    # def test_admin_delete_nonexisting_user_get(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     response = test_client.get(
    #         f"{module_info['url_prefix']}/delete/some_id",
    #         follow_redirects=True,
    #     )

    #     assert response.status_code == 200
    #     assert b"Unable to delete. Invalid user id" in response.data

    # def test_admin_edit_existing_user_get(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     user = User.create(email="test@gmail.com", password="pass")

    #     response = test_client.get(
    #         f"{module_info['url_prefix']}/edit/{user.id}",
    #     )

    #     assert response.status_code == 200
    #     assert b"test@gmail.com" in response.data
    #     assert b"Edit User" in response.data

    # def test_admin_edit_nonexisting_user_get(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     response = test_client.get(
    #         f"{module_info['url_prefix']}/edit/some-id", follow_redirects=True
    #     )

    #     assert response.status_code == 200
    #     assert b"Invalid user id" in response.data
    #     assert request.path == f"{module_info['url_prefix']}/"

    # def test_admin_update_user_adding_new_roles_to_user(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     user = User.create(email="foo@gmail.com", password="pass")
    #     role1 = Role.create(name="test1-role")
    #     role2 = Role.create(name="test2-role")
    #     data = {
    #         "id": str(user.id),
    #         "email": "bar@gmail.com",
    #         "password": "newpass",
    #         "first_name": "Test",
    #         "last_name": "User",
    #         "is_admin": "",
    #         f"role_{role1.id}": "",
    #         f"role_{role2.id}": "",
    #     }

    #     response = test_client.post(
    #         f"{module_info['url_prefix']}/update",
    #         data=data,
    #         follow_redirects=True,
    #     )

    #     assert response.status_code == 200
    #     assert user.email == "bar@gmail.com"
    #     assert user.check_password("newpass")
    #     assert user.first_name == "Test"
    #     assert user.last_name == "User"
    #     assert len(user.roles) == 2
    #     assert role1.users[0].email == "bar@gmail.com"
    #     assert role2.users[0].email == "bar@gmail.com"

    # def test_admin_update_user_remove_old_roles_from_user(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     user = User(email="foo@gmail.com", password="pass", is_admin=True)
    #     user.is_admin = True
    #     role1 = Role(name="test1-role")
    #     role2 = Role(name="test2-role")
    #     user.roles = [role1, role2]
    #     user.save()
    #     data = {
    #         "id": str(user.id),
    #         "email": "bar@gmail.com",
    #         "first_name": "Test",
    #         "last_name": "User",
    #         "password": "   ",
    #         "is_admin": None,
    #     }

    #     response = test_client.post(
    #         f"{module_info['url_prefix']}/update",
    #         data=data,
    #         follow_redirects=True,
    #     )

    #     assert response.status_code == 200
    #     assert user.email == "bar@gmail.com"
    #     assert user.check_password("pass")
    #     assert len(user.roles) == 0
    #     assert len(role1.users) == 0
    #     assert len(role2.users) == 0

    # def test_admin_roles_get(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     response = test_client.get(f"{module_info['url_prefix']}/roles")

    #     assert response.status_code == 200
    #     assert b"Roles" in response.data

    # def test_admin_roles_add_nonexisting_role_post(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     response = test_client.post(
    #         f"{module_info['url_prefix']}/roles/add",
    #         data=dict(name="new-role"),
    #         follow_redirects=True,
    #     )

    #     role = Role.query.filter(Role.name == "new-role").scalar()
    #     role_count = Role.query.count()

    #     assert response.status_code == 200
    #     assert role is not None
    #     assert role_count == 1

    # def test_admin_roles_add_existing_role_post(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     Role.create(name="new-role")

    #     response = test_client.post(
    #         f"{module_info['url_prefix']}/roles/add",
    #         data=dict(name="new-role"),
    #         follow_redirects=True,
    #     )
    #     role_count = Role.query.count()
    #     role = Role.query.filter(Role.name == "new-role").scalar()

    #     assert response.status_code == 200
    #     assert b"Role already exists" in response.data
    #     assert role is not None
    #     assert role_count == 1

    # def test_admin_roles_delete_nonexisting_role_get(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     response = test_client.get(
    #         f"{module_info['url_prefix']}/roles/some-id/delete",
    #         follow_redirects=True,
    #     )

    #     assert response.status_code == 200
    #     assert request.path == f"{module_info['url_prefix']}/roles"
    #     assert b"Unable to delete. Invalid role id" in response.data

    # def test_admin_roles_delete_existing_role_get(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     role1 = Role.create(name="new-role1")
    #     role2 = Role.create(name="new-role2")

    #     response = test_client.get(
    #         f"{module_info['url_prefix']}/roles/{role1.id}/delete",
    #         follow_redirects=True,
    #     )
    #     roles = Role.query.all()

    #     assert response.status_code == 200
    #     assert request.path == f"{module_info['url_prefix']}/roles"
    #     assert b"Role successfully deleted" in response.data
    #     assert roles is not None
    #     assert roles[0].name == role2.name
    #     assert len(roles) == 1

    # def test_admin_roles_update_nonexisting_role_post(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     response = test_client.post(
    #         f"{module_info['url_prefix']}/roles/update",
    #         data=dict(role_id="some-id"),
    #         follow_redirects=True,
    #     )
    #     roles = Role.query.count()

    #     assert response.status_code == 200
    #     assert request.path == f"{module_info['url_prefix']}/roles"
    #     assert b"Unable to update. Role does not exist" in response.data
    #     assert roles == 0

    # def test_admin_roles_update_existing_role_post(self, test_client):
    #     with open(os.path.join(module_path, "info.json")) as f:
    #         module_info = json.load(f)
    #     new_role = Role.create(name="new-role1")

    #     response = test_client.post(
    #         f"{module_info['url_prefix']}/roles/update",
    #         data=dict(role_id=new_role.id, role_name="update-role"),
    #         follow_redirects=True,
    #     )
    #     role = Role.query.scalar()

    #     assert response.status_code == 200
    #     assert request.path == f"{module_info['url_prefix']}/roles"
    #     assert b"Role successfully updated" in response.data
    #     assert role is not None
    #     assert role.name == "update-role"
