import importlib
import sys
from pathlib import Path

import pytest
from flask import Flask, session

PROJECT_ROOT = Path(__file__).resolve().parents[1]
if str(PROJECT_ROOT) not in sys.path:
    sys.path.insert(0, str(PROJECT_ROOT))

import app_security
import crypto_utils
from db import users as db_users


def test_user_lookup_rejects_dynamic_field_name():
    with pytest.raises(ValueError):
        db_users._get_user_by_field("username OR 1=1 --", "demo")


def test_rate_limit_ip_does_not_trust_proxy_headers_by_default(monkeypatch):
    monkeypatch.delenv("TRUST_PROXY_HEADERS", raising=False)
    monkeypatch.delenv("TRUSTED_PROXY_CIDRS", raising=False)
    security_module = importlib.reload(app_security)

    app = Flask(__name__)
    with app.test_request_context(
        "/",
        environ_base={"REMOTE_ADDR": "10.0.0.9"},
        headers={"X-Forwarded-For": "198.51.100.10"},
    ):
        assert security_module.get_rate_limit_ip() == "10.0.0.9"


def test_rate_limit_ip_can_use_forwarded_chain_when_explicitly_enabled(monkeypatch):
    monkeypatch.setenv("TRUST_PROXY_HEADERS", "true")
    monkeypatch.setenv("TRUSTED_PROXY_CIDRS", "10.0.0.0/8")
    security_module = importlib.reload(app_security)

    app = Flask(__name__)
    with app.test_request_context(
        "/",
        environ_base={"REMOTE_ADDR": "10.2.3.4"},
        headers={"X-Forwarded-For": "198.51.100.10, 10.2.3.4"},
    ):
        assert security_module.get_rate_limit_ip() == "198.51.100.10"


def test_get_encryption_key_refuses_regeneration_when_encrypted_data_exists(monkeypatch, tmp_path):
    monkeypatch.setenv("ALLOW_NEW_KEY", "true")
    monkeypatch.delenv("ENCRYPTION_KEY_RAW", raising=False)
    monkeypatch.delenv("ENCRYPTION_KEY", raising=False)
    monkeypatch.setattr(crypto_utils, "ENCRYPTION_KEY_FILE", str(tmp_path / "missing_key.bin"))
    monkeypatch.setattr(crypto_utils, "_check_existing_encrypted_data", lambda: True)

    with pytest.raises(RuntimeError):
        crypto_utils.get_encryption_key()


def test_validate_csrf_token_requires_matching_session_token():
    app = Flask(__name__)
    app.secret_key = "test-secret-key"

    with app.test_request_context("/", method="POST"):
        session["csrf_token"] = "fixed-token"
        assert app_security.validate_csrf_token("fixed-token") is True
        assert app_security.validate_csrf_token("wrong-token") is False
        assert app_security.validate_csrf_token("") is False


def test_decrypt_password_returns_empty_for_unreadable_encrypted_payload(monkeypatch):
    class BrokenFernet:
        def decrypt(self, *_args, **_kwargs):
            raise ValueError("bad token")

    monkeypatch.setattr(crypto_utils, "_get_fernet", lambda: BrokenFernet())
    encrypted_like_value = "gAAAAABrokenPayload"
    assert crypto_utils.decrypt_password(encrypted_like_value) == ""
