import requests

# This modules contains helper functions for the tests
from helpers import *

print("Running Tests...")

# Defined once per test run
username = "user_" + randomString()
projectName = "project_" + randomString()


# ta bort auth i handlern för att få testet att gå igenom
def test_ProjectRoleChange():
    dprint("Testing ProjectRoleChange")
    localUsername = randomString()
    localProjectName = randomString()
    register(localUsername, "username_password")

    token = login(localUsername, "username_password").json()["token"]

    # Just checking since this test is built somewhat differently than the others
    assert token != None, "Login failed"

    response = requests.post(
        addProjectPath,
        json={"name": localProjectName, "description": "This is a project"},
        headers={"Authorization": "Bearer " + token},
    )

    if response.status_code != 200:
        print("Add project failed")

    response = requests.post(
        ProjectRoleChangePath,
        headers={"Authorization": "Bearer " + token},
        json={
            "projectName": localProjectName,
            "role": "project_manager",
        },
    )

    assert response.status_code == 200, "ProjectRoleChange failed"
    gprint("test_ProjectRoleChange successful")


def test_get_user_projects():
    username = "user2"
    password = "123"

    dprint("Testing get user projects")
    loginResponse = login(username, password)
    # Check if the user is added to the project
    response = requests.get(
        getUserProjectsPath + "/" + username,
        headers={"Authorization": "Bearer " + loginResponse.json()["token"]},
    )
    dprint(response.text)
    dprint(response.json())
    assert response.status_code == 200, "Get user projects failed"
    gprint("test_get_user_projects successful")


# Test function to login
def test_login():
    response = login(username, "always_same")
    assert response.status_code == 200, "Login failed"
    dprint("Login successful")
    gprint("test_login successful")
    return response.json()["token"]


# Test function to create a new user
def test_create_user():
    response = register(username, "always_same")
    assert response.status_code == 200, "Registration failed"
    gprint("test_create_user successful")


# Test function to add a project
def test_add_project():
    loginResponse = login(username, "always_same")
    token = loginResponse.json()["token"]
    response = requests.post(
        addProjectPath,
        json={"name": projectName, "description": "This is a project"},
        headers={"Authorization": "Bearer " + token},
    )
    dprint(response.text)
    assert response.status_code == 200, "Add project failed"
    gprint("test_add_project successful")


# Test function to submit a report
def test_submit_report():
    token = login(username, "always_same").json()["token"]
    response = requests.post(
        submitReportPath,
        json={
            "projectName": projectName,
            "week": 1,
            "developmentTime": 10,
            "meetingTime": 5,
            "adminTime": 5,
            "ownWorkTime": 10,
            "studyTime": 10,
            "testingTime": 10,
        },
        headers={"Authorization": "Bearer " + token},
    )
    dprint(response.text)
    assert response.status_code == 200, "Submit report failed"
    gprint("test_submit_report successful")


# Test function to get a weekly report
def test_get_weekly_report():
    token = login(username, "always_same").json()["token"]
    response = requests.get(
        getWeeklyReportPath,
        headers={"Authorization": "Bearer " + token},
        params={"username": username, "projectName": projectName, "week": 1},
    )
    dprint(response.text)
    assert response.status_code == 200, "Get weekly report failed"
    gprint("test_get_weekly_report successful")


# Tests getting a project by id
def test_get_project():
    token = login(username, "always_same").json()["token"]
    response = requests.get(
        getProjectPath + "/1",  # Assumes that the project with id 1 exists
        headers={"Authorization": "Bearer " + token},
    )
    dprint(response.text)
    assert response.status_code == 200, "Get project failed"
    gprint("test_get_project successful")


# Test function to add a user to a project
def test_add_user_to_project():
    # User to create
    pm_user = "user" + randomString()
    pm_passwd = "password"

    # User to add
    member_user = "member" + randomString()
    member_passwd = "password"

    # Name of the project to be created
    project_name = "project" + randomString()

    pm_token = register_and_login(pm_user, pm_passwd)
    register(member_user, member_passwd)

    response = create_project(pm_token, project_name)
    assert response.status_code == 200, "Create project failed"

    # Promote the user to project manager
    response = addToProject(pm_token, member_user, project_name)
    assert response.status_code == 200, "Add user to project failed"


# Test function to sign a report
def test_sign_report():
    # Pm user
    pm_username = "pm" + randomString()
    pm_password = "admin_password2"

    # User to add
    member_user = "member" + randomString()
    member_passwd = "password"

    # Name of the project to be created
    project_name = "project" + randomString()

    # Register and get the tokens for both users
    pm_token = register_and_login(pm_username, pm_password)
    member_token = register_and_login(member_user, member_passwd)

    # Create the project
    response = create_project(pm_token, project_name)
    assert response.status_code == 200, "Create project failed"

    # Add the user to the project
    response = addToProject(pm_token, member_user, project_name)

    # Submit a report for the project
    response = submitReport(
        member_token,
        {
            "projectName": project_name,
            "week": 1,
            "developmentTime": 10,
            "meetingTime": 5,
            "adminTime": 5,
            "ownWorkTime": 10,
            "studyTime": 10,
            "testingTime": 10,
        },
    )
    assert response.status_code == 200, "Submit report failed"

    # Retrieve the report ID
    report_id = getReport(member_token, member_user, project_name)["reportId"]

    # Sign the report as the project manager
    response = signReport(pm_token, report_id)
    assert response.status_code == 200, "Sign report failed"
    dprint("Sign  report successful")

    # Retrieve the report ID again for confirmation
    report_id = getReport(member_token, member_user, project_name)["reportId"]
    assert report_id != None, "Get report failed"
    gprint("test_sign_report successful")


# Test function to get weekly reports for a user in a project
def test_get_all_weekly_reports():
    # Log in as the user
    token = login(username, "always_same").json()["token"]

    # Get weekly reports for the user in the project
    response = requests.get(
        getAllWeeklyReportsPath + "/" + projectName,
        headers={"Authorization": "Bearer " + token},
        params={"targetUser": username},
    )

    dprint(response.text)
    assert response.status_code == 200, "Get weekly reports for user failed"
    gprint("test_get_weekly_reports_user successful")


# Test function to check if a user is a project manager
def test_check_if_project_manager():
    # Log in as the user
    token = login(username, "always_same").json()["token"]

    # Check if the user is a project manager for the project
    response = requests.get(
        checkIfProjectManagerPath + "/" + projectName,
        headers={"Authorization": "Bearer " + token},
    )

    dprint(response.text)
    assert response.status_code == 200, "Check if project manager failed"
    gprint("test_check_if_project_manager successful")


def test_ensure_manager_of_created_project():
    # Create a new user to add to the project
    newUser = "karen_" + randomString()
    newProject = "HR_" + randomString()
    register(newUser, "new_user_password")
    token = login(newUser, "new_user_password").json()["token"]

    # Create a new project
    response = requests.post(
        addProjectPath,
        json={"name": newProject, "description": "This is a project"},
        headers={"Authorization": "Bearer " + token},
    )
    assert response.status_code == 200, "Add project failed"

    response = requests.get(
        checkIfProjectManagerPath + "/" + newProject,
        headers={"Authorization": "Bearer " + token},
    )
    assert response.status_code == 200, "Check if project manager failed"
    assert response.json()["isProjectManager"] == True, "User is not project manager"
    gprint("test_ensure_admin_of_created_project successful")


def test_change_user_name():
    # Register a new user
    new_user = randomString()
    register(new_user, "password")

    # Log in as the new user
    token = login(new_user, "password").json()["token"]

    # Register a new admin
    admin_username = randomString()
    admin_password = "admin_password"
    dprint(
        "Registering with username: ", admin_username, " and password: ", admin_password
    )
    response = requests.post(
        registerPath, json={"username": admin_username, "password": admin_password}
    )
    admin_token = login(admin_username, admin_password).json()["token"]

    # Promote to admin
    response = requests.post(
        promoteToAdminPath,
        json={"username": admin_username},
        headers={"Authorization": "Bearer " + admin_token},
    )

    # Change the user's name
    response = requests.put(
        getChangeUserNamePath,
        json={"prevName": new_user, "newName": randomString()},
        headers={"Authorization": "Bearer " + admin_token},
    )

    # Check if the change was successful
    assert response.status_code == 200, "Change user name failed"
    gprint("test_change_user_name successful")


def test_list_all_users_project():
    # Log in as a user who is a member of the project
    admin_username = randomString()
    admin_password = "admin_password2"
    dprint(
        "Registering with username: ", admin_username, " and password: ", admin_password
    )
    response = requests.post(
        registerPath, json={"username": admin_username, "password": admin_password}
    )
    dprint(response.text)

    # Log in as the admin
    admin_token = login(admin_username, admin_password).json()["token"]
    response = requests.post(
        promoteToAdminPath,
        json={"username": admin_username},
        headers={"Authorization": "Bearer " + admin_token},
    )

    # Make a request to list all users associated with the project
    response = requests.get(
        getUsersProjectPath + "/" + projectName,
        headers={"Authorization": "Bearer " + admin_token},
    )
    assert response.status_code == 200, "List all users project failed"
    gprint("test_list_all_users_project sucessful")


def test_update_weekly_report():
    # Log in as the user
    token = login(username, "always_same").json()["token"]

    # Prepare the JSON data for updating the weekly report
    update_data = {
        "projectName": projectName,
        "userName": username,
        "week": 1,
        "developmentTime": 8,
        "meetingTime": 6,
        "adminTime": 4,
        "ownWorkTime": 11,
        "studyTime": 8,
        "testingTime": 18,
    }

    # Send a request to update the weekly report
    response = requests.put(
        getUpdateWeeklyReportPath,
        json=update_data,
        headers={"Authorization": "Bearer " + token},
    )

    # Check if the update was successful
    assert response.status_code == 200, "Update weekly report failed"
    gprint("test_update_weekly_report successful")


def test_remove_project():
    admin_username = randomString()
    admin_password = "admin_password2"
    dprint(
        "Registering with username: ", admin_username, " and password: ", admin_password
    )
    response = requests.post(
        registerPath, json={"username": admin_username, "password": admin_password}
    )
    dprint(response.text)

    # Log in as the admin
    admin_token = login(admin_username, admin_password).json()["token"]
    response = requests.post(
        promoteToAdminPath,
        json={"username": admin_username},
        headers={"Authorization": "Bearer " + admin_token},
    )

    # Create a new project
    new_project = randomString()
    response = requests.post(
        addProjectPath,
        json={"name": new_project, "description": "This is a project"},
        headers={"Authorization": "Bearer " + admin_token},
    )
    assert response.status_code == 200, "Add project failed"

    # Remove the project
    response = requests.delete(
        removeProjectPath + "/" + new_project,
        headers={"Authorization": "Bearer " + admin_token},
    )
    assert response.status_code == 200, "Remove project failed"
    gprint("test_remove_project successful")


def test_get_unsigned_reports():
    # Log in as the user
    token = login("user2", "123").json()["token"]

    # Make a request to get all unsigned reports
    response = requests.get(
        getUnsignedReportsPath + "/" + projectName,
        headers={"Authorization": "Bearer " + token},
    )
    assert response.status_code == 200, "Get unsigned reports failed"
    gprint("test_get_unsigned_reports successful")


def test_get_other_users_report_as_pm():
    # Create user
    user = randomString()
    register(user, "password")

    # Create project
    project = randomString()
    pm_token = login(user, "password").json()["token"]
    response = requests.post(
        addProjectPath,
        json={"name": project, "description": "This is a project"},
        headers={"Authorization": "Bearer " + pm_token},
    )
    assert response.status_code == 200, "Add project failed"

    # Create other user
    other_user = randomString()
    register(other_user, "password")
    user_token = login(other_user, "password").json()["token"]

    # Add other user to project
    response = requests.put(
        addUserToProjectPath + "/" + project,
        headers={"Authorization": "Bearer " + pm_token},  # note pm_token
        params={"userName": other_user},
    )
    assert response.status_code == 200, "Add user to project failed"

    # Submit report as other user
    response = requests.post(
        submitReportPath,
        json={
            "projectName": project,
            "week": 1,
            "developmentTime": 10,
            "meetingTime": 5,
            "adminTime": 5,
            "ownWorkTime": 10,
            "studyTime": 10,
            "testingTime": 10,
        },
        headers={"Authorization": "Bearer " + user_token},
    )
    assert response.status_code == 200, "Submit report failed"

    # Get report as project manager
    response = requests.get(
        getWeeklyReportPath,
        headers={"Authorization": "Bearer " + pm_token},
        params={"targetUser": other_user, "projectName": project, "week": 1},
    )
    assert response.status_code == 200, "Get weekly report failed"


def test_promote_to_manager():
    # User to create
    pm_user = "user" + randomString()
    pm_passwd = "password"

    # User to promote
    member_user = "member" + randomString()
    member_passwd = "password"

    # Name of the project to be created
    project_name = "project" + randomString()

    pm_token = register_and_login(pm_user, pm_passwd)
    member_token = register_and_login(member_user, member_passwd)

    response = create_project(pm_token, project_name)
    assert response.status_code == 200, "Create project failed"

    # Promote the user to project manager
    response = promoteToManager(pm_token, member_user, project_name)
    assert response.status_code == 200, "Promote to manager failed"


if __name__ == "__main__":
    test_promote_to_manager()
    test_remove_project()
    test_get_user_projects()
    test_create_user()
    test_login()
    test_add_project()
    test_submit_report()
    test_get_weekly_report()
    test_get_project()
    test_sign_report()
    test_add_user_to_project()
    test_get_all_weekly_reports()
    test_check_if_project_manager()
    test_ProjectRoleChange()
    test_ensure_manager_of_created_project()
    test_get_unsigned_reports()
    test_list_all_users_project()
    test_change_user_name()
    test_update_weekly_report()
    test_get_other_users_report_as_pm()