import requests
import string
import random

debug_output = False

def gprint(*args, **kwargs):
    print("\033[92m", *args, "\033[00m", **kwargs)

print("Running Tests...")

def dprint(*args, **kwargs):
    if debug_output:
        print(*args, **kwargs)

def randomString(len=10):
    """Generate a random string of fixed length"""
    letters = string.ascii_lowercase
    return "".join(random.choice(letters) for i in range(len))


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

# The base URL of the API
base_url = "http://localhost:8080"

# Endpoint to test
registerPath = base_url + "/api/register"
loginPath = base_url + "/api/login"
addProjectPath = base_url + "/api/project"
submitReportPath = base_url + "/api/submitWeeklyReport"
getWeeklyReportPath = base_url + "/api/getWeeklyReport"
getProjectPath = base_url + "/api/project"
signReportPath = base_url + "/api/signReport"
addUserToProjectPath = base_url + "/api/addUserToProject"
promoteToAdminPath = base_url + "/api/promoteToAdmin"
getUserProjectsPath = base_url + "/api/getUserProjects"
getWeeklyReportsUserPath = base_url + "/api/getWeeklyReportsUser"
checkIfProjectManagerPath = base_url + "/api/checkIfProjectManager"
ProjectRoleChangePath = base_url + "/api/ProjectRoleChange"
getUsersProjectPath = base_url + "/api/getUsersProject"

#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():

    dprint("Testing get user projects")
    loginResponse = login("user2", "123")
    # Check if the user is added to the project
    response = requests.get(
        getUserProjectsPath,
        json={"username": "user2"},
        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")


# Posts the username and password to the register endpoint
def register(username: string, password: string):
    dprint("Registering with username: ", username, " and password: ", password)
    response = requests.post(
        registerPath, json={"username": username, "password": password}
    )
    dprint(response.text)
    return response


# Posts the username and password to the login endpoint
def login(username: string, password: string):
    dprint("Logging in with username: ", username, " and password: ", password)
    response = requests.post(
        loginPath, json={"username": username, "password": password}
    )
    dprint(response.text)
    return response


# 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():
    # Log in as a site 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}
    )
    dprint(response.text)

    admin_token = login(admin_username, admin_password).json()["token"]
    response = requests.post(
        promoteToAdminPath,
        json={"username": admin_username},
        headers={"Authorization": "Bearer " + admin_token},
    )
    dprint(response.text)
    assert response.status_code == 200, "Promote to site admin failed"
    dprint("Admin promoted to site admin successfully")

    # Create a new user to add to the project
    new_user = randomString()
    register(new_user, "new_user_password")

    # Add the new user to the project as a member
    response = requests.put(
        addUserToProjectPath,
        json={"projectName": projectName, "username": new_user, "role": "member"},
        headers={"Authorization": "Bearer " + admin_token},
    )

    dprint(response.text)
    assert response.status_code == 200, "Add user to project failed"
    gprint("test_add_user_to_project successful")

# Test function to sign a report
def test_sign_report():
    # Create a project manager user
    project_manager = randomString()
    register(project_manager, "project_manager_password")

    # Register an admin
    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},
    )

    response = requests.put(
        addUserToProjectPath,
        json={
            "projectName": projectName,
            "username": project_manager,
            "role": "project_manager",
        },
        headers={"Authorization": "Bearer " + admin_token},
    )
    assert response.status_code == 200, "Add project manager to project failed"
    dprint("Project manager added to project successfully")

    # Log in as the project manager
    project_manager_token = login(project_manager, "project_manager_password").json()[
        "token"
    ]

    # Submit a report for the project
    token = login(username, "always_same").json()["token"]
    response = requests.post(
        submitReportPath,
        json={
            "projectName": projectName,
            "week": 2,
            "developmentTime": 10,
            "meetingTime": 5,
            "adminTime": 5,
            "ownWorkTime": 10,
            "studyTime": 10,
            "testingTime": 10,
        },
        headers={"Authorization": "Bearer " + token},
    )
    assert response.status_code == 200, "Submit report failed"
    dprint("Submit report successful")

    # Retrieve the report ID
    response = requests.get(
        getWeeklyReportPath,
        headers={"Authorization": "Bearer " + token},
        params={"username": username, "projectName": projectName, "week": 1},
    )
    dprint(response.text)
    report_id = response.json()["reportId"]

    # Sign the report as the project manager
    response = requests.post(
        signReportPath,
        json={"reportId": report_id},
        headers={"Authorization": "Bearer " + project_manager_token},
    )
    assert response.status_code == 200, "Sign report failed"
    dprint("Sign  report successful")

    # Retrieve the report ID again for confirmation
    response = requests.get(
        getWeeklyReportPath,
        headers={"Authorization": "Bearer " + token},
        params={"username": username, "projectName": projectName, "week": 1},
    )
    dprint(response.text)
    gprint("test_sign_report successful")

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

    # Get weekly reports for the user in the project
    response = requests.get(
        getWeeklyReportsUserPath + "/" + projectName,
        headers={"Authorization": "Bearer " + token},
    )
    
    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")


if __name__ == "__main__":
    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_weekly_reports_user()
    test_check_if_project_manager()
    test_ProjectRoleChange()
    #test_list_all_users_project()
    test_ensure_manager_of_created_project()