import os
from typing import Generator

import pytest
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

os.environ.setdefault("WEB_SENTINEL_POSTGRES_URL", "sqlite:///./test_admin_config.db")
os.environ.setdefault("WEB_SENTINEL_ADMIN_JWT_SECRET", "test-secret")

from admin.backend.app.database import get_session
from admin.backend.app.main import create_app
from admin.backend.app.models import Base
from admin.backend.app.models.admin_user import AdminUser
from admin.backend.app.security import hash_password

engine = create_engine(os.environ["WEB_SENTINEL_POSTGRES_URL"], future=True)
TestingSession = sessionmaker(bind=engine, autoflush=False, autocommit=False, future=True)

Base.metadata.create_all(bind=engine)


def override_session() -> Generator:
    db = TestingSession()
    try:
        yield db
    finally:
        db.close()


app = create_app()
app.dependency_overrides[get_session] = override_session
client = TestClient(app)


def setup_module() -> None:
    Base.metadata.create_all(bind=engine)
    with TestingSession() as session:
        session.query(AdminUser).delete()
        session.add(
            AdminUser(
                email="sysop@web-sentinel.com",
                hashed_password=hash_password("secret"),
                role="super-admin",
            )
        )
        session.commit()


def teardown_module() -> None:
    Base.metadata.drop_all(bind=engine)


def _login() -> str:
    response = client.post(
        "/api/v1/auth/login",
        data={"username": "sysop@web-sentinel.com", "password": "secret"},
        headers={"Content-Type": "application/x-www-form-urlencoded"},
    )
    assert response.status_code == 200
    return response.json()["access_token"]


def test_set_and_get_config():
    token = _login()
    response = client.put(
        "/api/v1/config/dashboard",
        json={"refresh_minutes": 5},
        headers={"Authorization": f"Bearer {token}"},
    )
    assert response.status_code == 200
    response = client.get(
        "/api/v1/config/",
        headers={"Authorization": f"Bearer {token}"},
    )
    assert response.status_code == 200
    assert response.json()["dashboard"]["refresh_minutes"] == 5


def test_i18n_configuration_roundtrip():
    token = _login()
    payload = {
        "default_locale": "fr",
        "locales": ["en", "fr"],
        "translations": {
            "fr": {
                "dashboard.title": "Tableau de bord",
            }
        },
    }
    resp = client.put(
        "/api/v1/config/i18n",
        json=payload,
        headers={"Authorization": f"Bearer {token}"},
    )
    assert resp.status_code == 200
    assert resp.json()["default_locale"] == "fr"

    resp = client.get(
        "/api/v1/config/i18n",
        headers={"Authorization": f"Bearer {token}"},
    )
    assert resp.status_code == 200
    data = resp.json()
    assert data["translations"]["fr"]["dashboard.title"] == "Tableau de bord"


def test_security_configuration_with_validation():
    token = _login()
    payload = {
        "allowed_ips": ["10.0.0.0/24", "192.168.0.10"],
        "webhook_targets": {"slack": "https://hooks.slack.com/services/test"},
    }
    resp = client.put(
        "/api/v1/config/security",
        json=payload,
        headers={"Authorization": f"Bearer {token}"},
    )
    assert resp.status_code == 200
    assert resp.json()["allowed_ips"] == payload["allowed_ips"]

    resp = client.get(
        "/api/v1/config/security",
        headers={"Authorization": f"Bearer {token}"},
    )
    assert resp.status_code == 200
    assert resp.json()["webhook_targets"]["slack"].startswith("https://")


@pytest.mark.parametrize(
    "invalid_payload",
    [
        {"allowed_ips": ["999.0.0.1"], "webhook_targets": {"slack": "https://valid"}},
        {"allowed_ips": ["10.0.0.0/24"], "webhook_targets": {"hook": "http://insecure"}},
    ],
)
def test_security_configuration_rejects_invalid_payload(invalid_payload):
    token = _login()
    resp = client.put(
        "/api/v1/config/security",
        json=invalid_payload,
        headers={"Authorization": f"Bearer {token}"},
    )
    assert resp.status_code == 422
