# tests/test_operator_login.py
import uuid
from tests.conftest import wire_operator_auth
from backend.operator_auth import (
    create_operator, make_operator_cookie, COOKIE_NAME, MAX_LOGIN_FAILURES,
)


def test_login_page_renders(client, db_session, monkeypatch):
    wire_operator_auth(monkeypatch, db_session, enabled=True)
    r = client.get("/login")
    assert r.status_code == 200
    assert "password" in r.text.lower()


def test_login_success_sets_cookie_and_redirects(client, db_session, monkeypatch):
    create_operator(db_session, "ok@x.com", "Ok", "admin", password="rightpw-9")
    wire_operator_auth(monkeypatch, db_session, enabled=True)
    r = client.post("/login", data={"email": "ok@x.com", "password": "rightpw-9"},
                    follow_redirects=False)
    assert r.status_code == 303
    assert r.headers["location"] == "/"
    assert f"{COOKIE_NAME}=" in r.headers.get("set-cookie", "")


def test_login_honors_next(client, db_session, monkeypatch):
    create_operator(db_session, "ok@x.com", "Ok", "admin", password="rightpw-9")
    wire_operator_auth(monkeypatch, db_session, enabled=True)
    r = client.post("/login?next=/settings", data={"email": "ok@x.com", "password": "rightpw-9"},
                    follow_redirects=False)
    assert r.headers["location"] == "/settings"


def test_login_wrong_password_no_cookie_generic_error(client, db_session, monkeypatch):
    create_operator(db_session, "ok@x.com", "Ok", "admin", password="rightpw-9")
    wire_operator_auth(monkeypatch, db_session, enabled=True)
    r = client.post("/login", data={"email": "ok@x.com", "password": "nope"},
                    follow_redirects=False)
    assert r.status_code == 200
    assert f"{COOKIE_NAME}=" not in r.headers.get("set-cookie", "")
    assert "invalid" in r.text.lower()


def test_login_must_change_redirects_to_change_password(client, db_session, monkeypatch):
    create_operator(db_session, "new@x.com", "New", "admin")  # generated temp → must_change
    from backend.models import OperatorUser
    user = db_session.query(OperatorUser).filter_by(email="new@x.com").first()
    from backend.auth_passwords import hash_password
    user.password_hash = hash_password("temp-pw-1")
    db_session.commit()
    wire_operator_auth(monkeypatch, db_session, enabled=True)
    r = client.post("/login", data={"email": "new@x.com", "password": "temp-pw-1"},
                    follow_redirects=False)
    assert r.status_code == 303
    assert r.headers["location"] == "/change-password"


def test_login_lockout_message_after_five(client, db_session, monkeypatch):
    create_operator(db_session, "lk@x.com", "Lk", "admin", password="rightpw-9")
    wire_operator_auth(monkeypatch, db_session, enabled=True)
    for _ in range(MAX_LOGIN_FAILURES):
        client.post("/login", data={"email": "lk@x.com", "password": "nope"}, follow_redirects=False)
    r = client.post("/login", data={"email": "lk@x.com", "password": "rightpw-9"}, follow_redirects=False)
    assert r.status_code == 200
    assert "too many" in r.text.lower()


def test_logout_clears_cookie(client, db_session, monkeypatch):
    wire_operator_auth(monkeypatch, db_session, enabled=True)
    r = client.get("/logout", follow_redirects=False)
    assert r.status_code == 303
    assert r.headers["location"] == "/login"
    set_cookie = r.headers.get("set-cookie", "").lower()
    assert COOKIE_NAME.lower() in set_cookie
    assert 'max-age=0' in set_cookie or 'expires=thu, 01 jan 1970' in set_cookie


def test_change_password_self_service(client, db_session, monkeypatch):
    user, _ = create_operator(db_session, "c@x.com", "C", "admin", password="orig-pw-1")
    wire_operator_auth(monkeypatch, db_session, enabled=True)
    client.cookies.set(COOKIE_NAME, make_operator_cookie(user.id))
    r = client.post("/change-password",
                    data={"current_password": "orig-pw-1", "new_password": "brand-new-2",
                          "confirm_password": "brand-new-2"}, follow_redirects=False)
    assert r.status_code == 303
    from backend.auth_passwords import verify_password
    db_session.refresh(user)
    assert verify_password("brand-new-2", user.password_hash)
    assert user.must_change_password is False


def test_safe_next_blocks_open_redirect():
    from backend.routers.operator_auth_routes import _safe_next
    assert _safe_next("//evil.com") == "/"
    assert _safe_next("/\\evil.com") == "/"        # backslash authority bypass
    assert _safe_next("https://evil.com") == "/"
    assert _safe_next("") == "/"
    assert _safe_next("/settings") == "/settings"
