from fastapi.exceptions import HTTPException
import pytest
from sqlmodel import select, Session
from sqlmodel.main import SQLModel
from sfm.routes.projects import crud
from tests.conftest import hashed_token1, hashed_token2

from sfm.models import Project, ProjectCreate, ProjectUpdate


# get_all
def test_get_all(db, session: Session):
    """test that the crud function works as expected"""
    response = crud.get_all(db)
    assert response is not None
    assert response[0].name == "Test Project 1"
    assert response[0].lead_name == "<NAME>"
    assert response[0].lead_email == "<EMAIL>"
    assert response[0].description == "A test project for testing"
    assert response[0].location == "Strangeville"
    assert response[0].repo_url == "github.com/starkEnterprises"
    assert response[0].on_prem is False
    assert response[0].project_auth_token_hashed == hashed_token1

    assert response[1].name == "Test Project 2"
    assert response[1].lead_name == "<NAME>"
    assert response[1].lead_email == "<EMAIL>"
    assert response[1].description == "A second test project for testing"
    assert response[1].location == "Kohler"
    assert response[1].repo_url == "github.com/pgaGolf"
    assert response[1].on_prem is False
    assert response[1].project_auth_token_hashed == hashed_token2

    """
    Test that the function raises an error when there are
    no projects in the table
    """
    session.delete(session.get(Project, 1))
    session.delete(session.get(Project, 2))
    session.commit()
    # SQLModel.metadata.drop_all(engine)
    with pytest.raises(Exception) as ex:
        crud.get_all(db)
        assert ex.value.message == "Projects not found"


# get_by_id
def test_get_by_id(db):
    """test that the crud function works as expected"""
    response = crud.get_by_id(db, project_id=1)
    assert response is not None
    assert response.name == "Test Project 1"
    assert response.lead_name == "<NAME>"
    assert response.lead_email == "<EMAIL>"
    assert response.description == "A test project for testing"
    assert response.location == "Strangeville"
    assert response.repo_url == "github.com/starkEnterprises"
    assert response.on_prem is False
    assert response.project_auth_token_hashed == hashed_token1

    """
    Testing that the crud function raises exception when the project
    does with matching id does not exist in DB
    """
    with pytest.raises(Exception) as ex:
        crud.get_by_id(db, project_id=15)
        assert ex.value.message == "Project not found"


# create_project
def test_create(db):
    """Testing that the project works as expected"""
    project_data = ProjectCreate(
        **{
            "name": "Test Project 3",
            "lead_name": "<NAME>",
            "lead_email": "<EMAIL>",
            "description": "A test project for testing creation",
            "location": "Bikini Gotham",
            "repo_url": "github.com/crustyEnterprises",
            "on_prem": True,
        }
    )

    response = crud.create_project(db, project_data, admin_key="admin_key")

    assert len(response) == 2
    assert response[0].name == "Test Project 3"
    assert response[0].lead_name == "<NAME>"
    assert response[0].lead_email == "<EMAIL>"
    assert response[0].description == "A test project for testing creation"
    assert response[0].location == "Bikini Gotham"
    assert response[0].repo_url == "github.com/crustyEnterprises"
    assert response[0].on_prem is True
    assert response[0].project_auth_token_hashed is not None

    """
    Testing that the function raises an error if the project name already
    exists in the database
    """
    with pytest.raises(Exception) as ex:
        response = crud.create_project(db, project_data, admin_key="admin_key")
        assert ex.value.message == "Database entry already exists"

    """
    Testing that the project raises an exception when the admin_key
    is incorrect
    """
    with pytest.raises(Exception) as ex:
        crud.create_project(db, project_data, admin_key="Shmadmin_key")
        assert ex.value.message == "Credentials are incorrect"


# delete_project
def test_delete_project(db):
    """Testing that the crud function works as expected"""
    response = crud.delete_project(db, project_id=1, admin_key="admin_key")
    assert response is True
    projects = db.exec(select(Project)).all()
    for project in projects:
        assert project.id != 1

    """
    Testing that the crud function raises an exception when the project
    with matching id does not exist in the database
    """
    with pytest.raises(Exception) as ex:
        crud.delete_project(db, project_id=15, admin_key="admin_key")
        assert ex.value.message == "Project not found"

    """
    Testing that the project raises an exception when the admin_key
    is incorrect
    """
    with pytest.raises(Exception) as ex:
        crud.delete_project(db, project_id=1, admin_key="Shmadmin_key")
        assert ex.value.message == "Credentials are incorrect"


# refresh_project_key
def test_refresh_project_key(db):
    """Testing that the crud function works as expected"""
    response = crud.refresh_project_key(db, project_id=1, admin_key="admin_key")
    assert response is not False
    assert response != "Catalyst"

    # testing that refreshing key did not change project details
    project_test = db.get(Project, 1)
    assert project_test.name == "Test Project 1"
    assert project_test.lead_name == "<NAME>"
    assert project_test.lead_email == "<EMAIL>"
    assert project_test.description == "A test project for testing"
    assert project_test.location == "Strangeville"
    assert project_test.repo_url == "github.com/starkEnterprises"
    assert project_test.on_prem is False

    """
    Testing that the crud function raises an exception when the project
    with matching id does not exist in the database
    """
    with pytest.raises(Exception) as ex:
        crud.refresh_project_key(db, project_id=15, admin_key="admin_key")
        assert ex.value.message == "Project not found"

    """
    Testing that the project raises an exception when the admin_key
    is incorrect
    """
    with pytest.raises(Exception) as ex:
        crud.refresh_project_key(db, project_id=1, admin_key="Shmadmin_key")
        assert ex.value.message == "Credentials are incorrect"


# update_project
def test_update_project(db):
    """Testing that the project works as expected"""
    update_dict = {
        "name": "New Test Project 1",
        "lead_name": "Strong Squid",
        "repo_url": "github.com/SquidEnterprises",
    }
    # vvv causes unset params to become default (exclude_unset didnt help)
    updated_project = ProjectUpdate(**update_dict)
    response = crud.update_project(
        db, project_id=1, project_data=updated_project, admin_key="admin_key"
    )

    assert response is not None
    assert response.name == "New Test Project 1"
    assert response.lead_name == "Strong Squid"
    assert response.lead_email == "<EMAIL>"
    assert response.description == "A test project for testing"
    assert response.location == "Strangeville"
    assert response.repo_url == "github.com/SquidEnterprises"
    assert response.on_prem is False
    assert response.project_auth_token_hashed == hashed_token1

    """
    Testing that the crud function raises an exception when the
    project with matching id does not exist in the database
    """
    with pytest.raises(Exception) as ex:
        crud.update_project(
            db,
            project_id=15,
            project_data="placeholder",
            admin_key="admin_key",
        )
        assert ex.value.message == "Project not found"

    """
    Testing that the project raises an exception when the admin_key
    is incorrect
    """
    with pytest.raises(Exception) as ex:
        crud.update_project(
            db,
            project_id=1,
            project_data="placeholder",
            admin_key="Shmadmin_key",
        )
        assert ex.value.message == "Credentials are incorrect"

sfm.routes.projects.crud.get_all sfm.routes.projects.crud.update_project sfm.models.ProjectCreate sfm.routes.projects.crud.get_by_id sqlmodel.select pytest.raises sfm.models.ProjectUpdate sfm.routes.projects.crud.refresh_project_key sfm.routes.projects.crud.create_project sfm.routes.projects.crud.delete_project
[((409, 425), 'sfm.routes.projects.crud.get_all', 'crud.get_all', (['db'], {}), '(db)\n', (421, 425), False, 'from sfm.routes.projects import crud\n'), ((1792, 1824), 'sfm.routes.projects.crud.get_by_id', 'crud.get_by_id', (['db'], {'project_id': '(1)'}), '(db, project_id=1)\n', (1806, 1824), False, 'from sfm.routes.projects import crud\n'), ((2644, 2891), 'sfm.models.ProjectCreate', 'ProjectCreate', ([], {}), "(**{'name': 'Test Project 3', 'lead_name': '<NAME>',\n    'lead_email': '<EMAIL>', 'description':\n    'A test project for testing creation', 'location': 'Bikini Gotham',\n    'repo_url': 'github.com/crustyEnterprises', 'on_prem': True})\n", (2657, 2891), False, 'from sfm.models import Project, ProjectCreate, ProjectUpdate\n'), ((3005, 3065), 'sfm.routes.projects.crud.create_project', 'crud.create_project', (['db', 'project_data'], {'admin_key': '"""admin_key"""'}), "(db, project_data, admin_key='admin_key')\n", (3024, 3065), False, 'from sfm.routes.projects import crud\n'), ((4236, 4296), 'sfm.routes.projects.crud.delete_project', 'crud.delete_project', (['db'], {'project_id': '(1)', 'admin_key': '"""admin_key"""'}), "(db, project_id=1, admin_key='admin_key')\n", (4255, 4296), False, 'from sfm.routes.projects import crud\n'), ((5148, 5213), 'sfm.routes.projects.crud.refresh_project_key', 'crud.refresh_project_key', (['db'], {'project_id': '(1)', 'admin_key': '"""admin_key"""'}), "(db, project_id=1, admin_key='admin_key')\n", (5172, 5213), False, 'from sfm.routes.projects import crud\n'), ((6699, 6727), 'sfm.models.ProjectUpdate', 'ProjectUpdate', ([], {}), '(**update_dict)\n', (6712, 6727), False, 'from sfm.models import Project, ProjectCreate, ProjectUpdate\n'), ((6743, 6837), 'sfm.routes.projects.crud.update_project', 'crud.update_project', (['db'], {'project_id': '(1)', 'project_data': 'updated_project', 'admin_key': '"""admin_key"""'}), "(db, project_id=1, project_data=updated_project,\n    admin_key='admin_key')\n", (6762, 6837), False, 'from sfm.routes.projects import crud\n'), ((1570, 1594), 'pytest.raises', 'pytest.raises', (['Exception'], {}), '(Exception)\n', (1583, 1594), False, 'import pytest\n'), ((1610, 1626), 'sfm.routes.projects.crud.get_all', 'crud.get_all', (['db'], {}), '(db)\n', (1622, 1626), False, 'from sfm.routes.projects import crud\n'), ((2403, 2427), 'pytest.raises', 'pytest.raises', (['Exception'], {}), '(Exception)\n', (2416, 2427), False, 'import pytest\n'), ((2443, 2476), 'sfm.routes.projects.crud.get_by_id', 'crud.get_by_id', (['db'], {'project_id': '(15)'}), '(db, project_id=15)\n', (2457, 2476), False, 'from sfm.routes.projects import crud\n'), ((3657, 3681), 'pytest.raises', 'pytest.raises', (['Exception'], {}), '(Exception)\n', (3670, 3681), False, 'import pytest\n'), ((3708, 3768), 'sfm.routes.projects.crud.create_project', 'crud.create_project', (['db', 'project_data'], {'admin_key': '"""admin_key"""'}), "(db, project_data, admin_key='admin_key')\n", (3727, 3768), False, 'from sfm.routes.projects import crud\n'), ((3947, 3971), 'pytest.raises', 'pytest.raises', (['Exception'], {}), '(Exception)\n', (3960, 3971), False, 'import pytest\n'), ((3987, 4050), 'sfm.routes.projects.crud.create_project', 'crud.create_project', (['db', 'project_data'], {'admin_key': '"""Shmadmin_key"""'}), "(db, project_data, admin_key='Shmadmin_key')\n", (4006, 4050), False, 'from sfm.routes.projects import crud\n'), ((4581, 4605), 'pytest.raises', 'pytest.raises', (['Exception'], {}), '(Exception)\n', (4594, 4605), False, 'import pytest\n'), ((4621, 4682), 'sfm.routes.projects.crud.delete_project', 'crud.delete_project', (['db'], {'project_id': '(15)', 'admin_key': '"""admin_key"""'}), "(db, project_id=15, admin_key='admin_key')\n", (4640, 4682), False, 'from sfm.routes.projects import crud\n'), ((4849, 4873), 'pytest.raises', 'pytest.raises', (['Exception'], {}), '(Exception)\n', (4862, 4873), False, 'import pytest\n'), ((4889, 4952), 'sfm.routes.projects.crud.delete_project', 'crud.delete_project', (['db'], {'project_id': '(1)', 'admin_key': '"""Shmadmin_key"""'}), "(db, project_id=1, admin_key='Shmadmin_key')\n", (4908, 4952), False, 'from sfm.routes.projects import crud\n'), ((5904, 5928), 'pytest.raises', 'pytest.raises', (['Exception'], {}), '(Exception)\n', (5917, 5928), False, 'import pytest\n'), ((5944, 6010), 'sfm.routes.projects.crud.refresh_project_key', 'crud.refresh_project_key', (['db'], {'project_id': '(15)', 'admin_key': '"""admin_key"""'}), "(db, project_id=15, admin_key='admin_key')\n", (5968, 6010), False, 'from sfm.routes.projects import crud\n'), ((6177, 6201), 'pytest.raises', 'pytest.raises', (['Exception'], {}), '(Exception)\n', (6190, 6201), False, 'import pytest\n'), ((6217, 6285), 'sfm.routes.projects.crud.refresh_project_key', 'crud.refresh_project_key', (['db'], {'project_id': '(1)', 'admin_key': '"""Shmadmin_key"""'}), "(db, project_id=1, admin_key='Shmadmin_key')\n", (6241, 6285), False, 'from sfm.routes.projects import crud\n'), ((7445, 7469), 'pytest.raises', 'pytest.raises', (['Exception'], {}), '(Exception)\n', (7458, 7469), False, 'import pytest\n'), ((7485, 7578), 'sfm.routes.projects.crud.update_project', 'crud.update_project', (['db'], {'project_id': '(15)', 'project_data': '"""placeholder"""', 'admin_key': '"""admin_key"""'}), "(db, project_id=15, project_data='placeholder',\n    admin_key='admin_key')\n", (7504, 7578), False, 'from sfm.routes.projects import crud\n'), ((7800, 7824), 'pytest.raises', 'pytest.raises', (['Exception'], {}), '(Exception)\n', (7813, 7824), False, 'import pytest\n'), ((7840, 7936), 'sfm.routes.projects.crud.update_project', 'crud.update_project', (['db'], {'project_id': '(1)', 'project_data': '"""placeholder"""', 'admin_key': '"""Shmadmin_key"""'}), "(db, project_id=1, project_data='placeholder', admin_key\n    ='Shmadmin_key')\n", (7859, 7936), False, 'from sfm.routes.projects import crud\n'), ((4348, 4363), 'sqlmodel.select', 'select', (['Project'], {}), '(Project)\n', (4354, 4363), False, 'from sqlmodel import select, Session\n')]