from __future__ import annotations

import json
from pathlib import Path

import pytest

from osm_lead_source_service.errors import InvalidConfiguration
from osm_lead_source_service.writer.lifecycle import LifecycleApiConfig
from osm_lead_source_service.writer.runtime import (
    WriterRuntimeConfig,
    read_shadow_report,
    summary_json,
)
from osm_lead_source_service.writer.service import InsertRunSummary


def valid_environment() -> dict[str, str]:
    return {
        "OSM_LEAD_SOURCE_WRITER_ENABLED": "true",
        "OSM_LEAD_SOURCE_LEGACY_WRITER_DISABLED": "true",
        "OSM_LEAD_SOURCE_SIDECAR_DATABASE_URL": "postgresql://fixture:secret@db/sidecar",
        "OSM_LEAD_SOURCE_NOCO_BASE_URL": "https://nocodb.example",
        "OSM_LEAD_SOURCE_NOCO_API_TOKEN": "fixture-token",
        "OSM_LEAD_SOURCE_LIFECYCLE_URL": "http://lifecycle.internal:8000/api/w/admins/jobs/run_wait_result/p/f/website-enrichment/website-lifecycle-ingestion-gate",
        "OSM_LEAD_SOURCE_LIFECYCLE_TOKEN": "fixture-lifecycle-token",
    }


def test_writer_runtime_fails_closed_until_both_gates_are_true() -> None:
    environment = valid_environment()
    environment["OSM_LEAD_SOURCE_WRITER_ENABLED"] = "false"
    with pytest.raises(InvalidConfiguration, match="disabled"):
        WriterRuntimeConfig.from_env(environment)

    environment = valid_environment()
    environment["OSM_LEAD_SOURCE_LEGACY_WRITER_DISABLED"] = "false"
    with pytest.raises(InvalidConfiguration, match="legacy"):
        WriterRuntimeConfig.from_env(environment)


def test_writer_runtime_keeps_secrets_out_of_repr() -> None:
    config = WriterRuntimeConfig.from_env(valid_environment())

    rendered = repr(config)
    assert "fixture-token" not in rendered
    assert "fixture:secret" not in rendered
    assert config.writer_enabled is True
    assert config.legacy_writer_disabled is True


def test_lifecycle_config_normalizes_legacy_windmill_webhook() -> None:
    config = LifecycleApiConfig(
        base_url=valid_environment()["OSM_LEAD_SOURCE_LIFECYCLE_URL"],
        api_token="fixture-lifecycle-token",
    )

    assert config.base_url == "http://lead-website-enricher:3000"


def test_lifecycle_config_accepts_direct_repository_endpoint() -> None:
    config = LifecycleApiConfig(
        base_url="http://lead-website-enricher:3000/lifecycle/evaluate-batch",
        api_token="fixture-lifecycle-token",
    )

    assert config.base_url == "http://lead-website-enricher:3000"


def test_shadow_report_reader_accepts_only_bounded_regular_utf8(tmp_path: Path) -> None:
    report = tmp_path / "report.json"
    report.write_text('{"fixture":true}', encoding="utf-8")

    assert read_shadow_report(report, max_bytes=1024) == '{"fixture":true}'
    with pytest.raises(InvalidConfiguration, match="exceeds"):
        read_shadow_report(report, max_bytes=4)

    link = tmp_path / "report-link.json"
    link.symlink_to(report)
    with pytest.raises(InvalidConfiguration, match="opened safely"):
        read_shadow_report(link, max_bytes=1024)


def test_insert_summary_is_stable_and_secret_free() -> None:
    result = InsertRunSummary(
        report_hash="a" * 64,
        candidate_count=5,
        inserted_count=2,
        duplicate_count=1,
        already_applied_count=1,
        in_progress_count=1,
        suppressed_count=0,
        website_suppressed_count=1,
        restore_candidate_count=0,
        observation_failure_count=0,
    )

    assert json.loads(summary_json(result)) == {
        "already_applied_count": 1,
        "candidate_count": 5,
        "duplicate_count": 1,
        "in_progress_count": 1,
        "inserted_count": 2,
        "observation_failure_count": 0,
        "report_hash": "a" * 64,
        "restore_candidate_count": 0,
        "suppressed_count": 0,
        "website_suppressed_count": 1,
    }
