"""Tests for self-service /api/auth/change-password endpoint."""
import os
import requests

BASE_URL = os.environ.get("REACT_APP_BACKEND_URL", "https://offline-billing-pro-2.preview.emergentagent.com").rstrip("/")
# Credentials sourced from environment with sane local defaults (matches .env primary admin).
ADMIN_EMAIL = os.environ.get("ADMIN_EMAIL", "regalmarketing2024@gmail.com")
ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD", "Rvasa@#9955")
TEMP_PASSWORD = os.environ.get("TEST_TEMP_PASSWORD", "TempChangePw@2024X")


def _fresh_admin_session():
    s = requests.Session()
    s.headers.update({"Content-Type": "application/json"})
    r = s.post(f"{BASE_URL}/api/auth/login", json={"email": ADMIN_EMAIL, "password": ADMIN_PASSWORD}, timeout=15)
    assert r.status_code == 200, r.text
    return s


class TestChangePassword:
    def test_requires_authentication(self):
        # No cookie → 401
        r = requests.post(
            f"{BASE_URL}/api/auth/change-password",
            json={"old_password": ADMIN_PASSWORD, "new_password": "AnyNewPass@123"},
            timeout=15,
        )
        assert r.status_code == 401, r.text

    def test_wrong_old_password_returns_401(self):
        s = _fresh_admin_session()
        r = s.post(
            f"{BASE_URL}/api/auth/change-password",
            json={"old_password": "DefinitelyNotMyPassword!", "new_password": TEMP_PASSWORD},
            timeout=15,
        )
        assert r.status_code == 401, r.text
        assert "incorrect" in r.json()["detail"].lower()

    def test_short_new_password_returns_400(self):
        s = _fresh_admin_session()
        r = s.post(
            f"{BASE_URL}/api/auth/change-password",
            json={"old_password": ADMIN_PASSWORD, "new_password": "abc"},
            timeout=15,
        )
        assert r.status_code == 400, r.text
        assert "8 characters" in r.json()["detail"]

    def test_same_as_old_returns_400(self):
        s = _fresh_admin_session()
        r = s.post(
            f"{BASE_URL}/api/auth/change-password",
            json={"old_password": ADMIN_PASSWORD, "new_password": ADMIN_PASSWORD},
            timeout=15,
        )
        assert r.status_code == 400, r.text
        assert "different" in r.json()["detail"].lower()

    def test_weak_new_password_returns_400(self):
        s = _fresh_admin_session()
        # 10 chars, all lowercase, all same letter — should score 0/1
        r = s.post(
            f"{BASE_URL}/api/auth/change-password",
            json={"old_password": ADMIN_PASSWORD, "new_password": "aaaaaaaaaa"},
            timeout=15,
        )
        assert r.status_code == 400, r.text
        assert "weak" in r.json()["detail"].lower()

    def test_happy_path_and_rollback(self):
        """Full cycle: change → login with new → change back → login with original.

        Last assertion is critical — leaves the admin password in its original
        state so other test suites don't break.
        """
        s = _fresh_admin_session()
        # 1. Change to temp
        r = s.post(
            f"{BASE_URL}/api/auth/change-password",
            json={"old_password": ADMIN_PASSWORD, "new_password": TEMP_PASSWORD},
            timeout=15,
        )
        assert r.status_code == 200, r.text
        assert r.json()["ok"] is True

        # 2. Login with NEW password works
        r = requests.post(
            f"{BASE_URL}/api/auth/login",
            json={"email": ADMIN_EMAIL, "password": TEMP_PASSWORD},
            timeout=15,
        )
        assert r.status_code == 200, r.text

        # 3. Login with OLD password fails
        r = requests.post(
            f"{BASE_URL}/api/auth/login",
            json={"email": ADMIN_EMAIL, "password": ADMIN_PASSWORD},
            timeout=15,
        )
        assert r.status_code == 401, r.text

        # 4. Change back to original — use the rotated cookie from step 1's session `s`
        r = s.post(
            f"{BASE_URL}/api/auth/change-password",
            json={"old_password": TEMP_PASSWORD, "new_password": ADMIN_PASSWORD},
            timeout=15,
        )
        assert r.status_code == 200, r.text

        # 5. Verify original works again
        r = requests.post(
            f"{BASE_URL}/api/auth/login",
            json={"email": ADMIN_EMAIL, "password": ADMIN_PASSWORD},
            timeout=15,
        )
        # Critical: original password must still work after rollback
        assert r.status_code == 200, r.text

    def test_empty_body_returns_400(self):
        s = _fresh_admin_session()
        r = s.post(
            f"{BASE_URL}/api/auth/change-password",
            json={"old_password": "", "new_password": ""},
            timeout=15,
        )
        assert r.status_code == 400, r.text
