from fastapi.testclient import TestClient

def test_login_ftth_success(client: TestClient, mocker):
    mocker.patch("app.routers.auth_ftth.AuthService.login_user", return_value={
        "data": {
            "id": 1,
            "username": "test_dse",
            "role": "DSE",
            "territory": "Jakarta",
            "brand": "IOH"
        },
        "token": {
            "access_token": "fake-token",
            "token_type": "bearer"
        }
    })

    response = client.post(
        "/auth/login-ftth",
        json={"username": "test_dse", "password": "password123"}
    )
    
    assert response.status_code == 200
    assert response.json()["meta"]["success"] is True
    assert response.json()["data"]["username"] == "test_dse"
    assert response.json()["token"]["access_token"] == "fake-token"


def test_login_ftth_failure(client: TestClient, mocker):
    mocker.patch("app.routers.auth_ftth.AuthService.login_user", side_effect=ValueError("Invalid username or password"))

    response = client.post(
        "/auth/login-ftth",
        json={"username": "wrong_user", "password": "wrong_pass"}
    )
    
    assert response.status_code == 400
    assert response.json()["meta"]["error"] == "Invalid username or password"


def test_refresh_token_ftth_success(client: TestClient, mocker):
    mocker.patch("app.routers.auth_ftth.get_current_user", return_value=type("User", (), {"username": "test_dse"}))
    mocker.patch("app.routers.auth_ftth.AuthService.refresh_token_for_user", return_value="new-fake-token")

    # Override get_current_user logic for this test to bypass real JWT checking
    from app.main import app
    from app.utils.dependencies import get_current_user
    app.dependency_overrides[get_current_user] = lambda: type("User", (), {"username": "test_dse"})

    response = client.post("/auth/refresh-token-ftth")
    
    assert response.status_code == 200
    assert response.json()["token"]["access_token"] == "new-fake-token"
    
    # Clean up overrides
    app.dependency_overrides.pop(get_current_user, None)

def test_login_ftth_inactive_user(client: TestClient, mocker):
    mocker.patch("app.routers.auth_ftth.AuthService.login_user", side_effect=ValueError("User is not active"))

    response = client.post(
        "/auth/login-ftth",
        json={"username": "inactive_user", "password": "password123"}
    )
    
    assert response.status_code == 400
    assert response.json()["meta"]["error"] == "User is not active"


def test_login_ftth_unauthorized_role(client: TestClient, mocker):
    mocker.patch("app.routers.auth_ftth.AuthService.login_user", side_effect=ValueError("User does not have access to this application"))

    response = client.post(
        "/auth/login-ftth",
        json={"username": "wrong_role", "password": "password123"}
    )
    
    assert response.status_code == 400
    assert response.json()["meta"]["error"] == "User does not have access to this application"


def test_change_password_success(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.auth_ftth.AuthService.change_user_password", return_value=None)

    response = authenticated_client.post(
        "/auth/change-password-ftth",
        json={"current_password": "old_password", "new_password": "new_password"}
    )
    
    assert response.status_code == 200
    assert response.json()["meta"]["success"] is True


def test_change_password_wrong_current(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.auth_ftth.AuthService.change_user_password", side_effect=ValueError("Invalid username or password"))

    response = authenticated_client.post(
        "/auth/change-password-ftth",
        json={"current_password": "wrong_old_password", "new_password": "new_password"}
    )
    
    assert response.status_code == 400
    assert response.json()["meta"]["error"] == "Invalid username or password"


def test_change_password_no_auth(client: TestClient):
    response = client.post(
        "/auth/change-password-ftth",
        json={"current_password": "old", "new_password": "new"}
    )
    
    # Should be rejected by FastAPI dependency
    assert response.status_code == 401
