"""Fail-closed configuration tests for isolated sidecar migrations."""

from __future__ import annotations

import traceback

import pytest

from osm_lead_source_service.sidecar.migration_config import (
    PRODUCTION_APPROVAL_VALUE,
    MigrationSafetyError,
    load_migration_settings,
    load_production_migration_settings,
    load_test_migration_settings,
    validate_production_migration_url,
    validate_test_migration_url,
)

GOOD_TEST_ENV = {
    "OSM_LEAD_SOURCE_MIGRATION_ENV": "test",
    "OSM_LEAD_SOURCE_TEST_DATABASE_URL": (
        "postgresql+psycopg://test_user:test_password@127.0.0.1:55432/osm_lead_source_test"
    ),
}
GOOD_PRODUCTION_ENV = {
    "OSM_LEAD_SOURCE_MIGRATION_ENV": "production",
    "OSM_LEAD_SOURCE_PRODUCTION_MIGRATION_APPROVAL": PRODUCTION_APPROVAL_VALUE,
    "OSM_LEAD_SOURCE_PRODUCTION_DATABASE_URL": (
        "postgresql+psycopg://sidecar_user:sidecar_password@osm-sidecar-db:5432/osm_lead_source"
    ),
}


def test_valid_test_settings_are_parsed_without_exposing_secrets() -> None:
    settings = load_test_migration_settings(GOOD_TEST_ENV)
    assert settings.database_name == "osm_lead_source_test"
    assert settings.host == "127.0.0.1"
    assert settings.port == 55432
    assert settings.environment == "test"
    assert "127.0.0.1:55432" not in repr(settings)
    assert "test_password" not in repr(settings)


def test_valid_production_settings_require_exact_sidecar_and_approval() -> None:
    settings = load_production_migration_settings(GOOD_PRODUCTION_ENV)
    assert settings.database_name == "osm_lead_source"
    assert settings.host == "osm-sidecar-db"
    assert settings.port == 5432
    assert settings.environment == "production"
    assert "sidecar_password" not in repr(settings)
    assert load_migration_settings(GOOD_PRODUCTION_ENV) == settings


@pytest.mark.parametrize(
    "environ",
    [
        {},
        {"OSM_LEAD_SOURCE_MIGRATION_ENV": "production"},
        {"OSM_LEAD_SOURCE_MIGRATION_ENV": "test"},
    ],
)
def test_missing_or_wrong_test_environment_fails_closed(environ: dict[str, str]) -> None:
    with pytest.raises(MigrationSafetyError):
        load_test_migration_settings(environ)


def test_generic_database_url_is_ignored() -> None:
    environ = {
        "OSM_LEAD_SOURCE_MIGRATION_ENV": "production",
        "OSM_LEAD_SOURCE_PRODUCTION_MIGRATION_APPROVAL": PRODUCTION_APPROVAL_VALUE,
        "DATABASE_URL": "postgresql+psycopg://prod:secret@nocodb/nocodb",
    }
    with pytest.raises(MigrationSafetyError):
        load_production_migration_settings(environ)


@pytest.mark.parametrize(
    "url",
    [
        "postgresql+psycopg://test_user:test_password@unknown.example/osm_lead_source_test",
        "postgresql+psycopg://test_user:test_password@127.0.0.1/production",
        "postgresql://test_user:test_password@127.0.0.1/osm_lead_source_test",
    ],
)
def test_unsafe_test_urls_fail_without_url_or_password_in_error(url: str) -> None:
    with pytest.raises(MigrationSafetyError) as raised:
        validate_test_migration_url(url)
    message = str(raised.value)
    assert url not in message
    assert "test_password" not in message


@pytest.mark.parametrize(
    "url",
    [
        "postgresql+psycopg://sidecar:secret@127.0.0.1:5432/osm_lead_source",
        "postgresql+psycopg://sidecar:secret@sidecar-db:5432/nocodb",
        "postgresql://sidecar:secret@sidecar-db:5432/osm_lead_source",
        "postgresql+psycopg://sidecar@sidecar-db:5432/osm_lead_source",
    ],
)
def test_unsafe_production_targets_are_rejected_and_sanitized(url: str) -> None:
    with pytest.raises(MigrationSafetyError) as raised:
        validate_production_migration_url(url)
    message = str(raised.value)
    assert url not in message
    assert "secret" not in message


def test_production_approval_must_be_exact() -> None:
    environ = dict(GOOD_PRODUCTION_ENV)
    environ["OSM_LEAD_SOURCE_PRODUCTION_MIGRATION_APPROVAL"] = "yes"
    with pytest.raises(MigrationSafetyError, match="approval"):
        load_production_migration_settings(environ)


@pytest.mark.parametrize(
    "url",
    [
        "not a database URL",
        "postgresql+psycopg://test_user:test_password@127.0.0.1:bad/osm_lead_source_test",
        "postgresql+psycopg://test_user:test_password@127.0.0.1:55432",
    ],
)
def test_malformed_urls_are_sanitized_even_in_formatted_tracebacks(url: str) -> None:
    try:
        validate_test_migration_url(url)
    except MigrationSafetyError as error:
        formatted = "".join(traceback.format_exception(error))
    else:  # pragma: no cover - the validator must reject every case above
        raise AssertionError("expected migration validation to fail")
    assert url not in formatted
    assert "test_password" not in formatted


def test_passwordless_url_is_allowed_only_through_exact_test_environment() -> None:
    passwordless = {
        "OSM_LEAD_SOURCE_MIGRATION_ENV": "test",
        "OSM_LEAD_SOURCE_TEST_DATABASE_URL": "postgresql+psycopg://test_user@127.0.0.1:5432/osm_lead_source_test",
    }
    settings = load_test_migration_settings(passwordless)
    assert settings.port == 5432
    with pytest.raises(MigrationSafetyError):
        validate_test_migration_url(passwordless["OSM_LEAD_SOURCE_TEST_DATABASE_URL"])
