import os
import unittest


os.environ.setdefault("DATABASE_URL", "mysql+pymysql://test:test@127.0.0.1/documenta")
os.environ.setdefault("REDIS_URL", "redis://127.0.0.1:6379/0")
os.environ.setdefault("APP_ENCRYPTION_KEY", "test-encryption-key")
os.environ.setdefault("PII_HMAC_KEY", "test-pii-key")
os.environ.setdefault("ACCESS_TOKEN_HMAC_KEY", "test-access-key")

from pydantic import ValidationError

from app.api.finder_routes import LocationIn, RANKING_VERSION, _ranking
from app.main import app


class H6FinderContractTests(unittest.TestCase):
    def test_public_and_admin_routes_are_registered(self):
        paths = {route.path for route in app.routes}
        expected = {
            "/api/v1/portal/finder/options",
            "/api/v1/portal/finder/suggestions",
            "/api/v1/portal/finder/search",
            "/api/v1/portal/entidades/{entity_uuid}",
            "/api/v1/panel/admin/territory",
            "/api/v1/panel/admin/territory/entities/{entity_id}/location",
            "/api/v1/panel/admin/territory/rebuild-index",
        }
        self.assertTrue(expected.issubset(paths), expected - paths)

    def test_location_requires_a_coordinate_pair(self):
        with self.assertRaises(ValidationError):
            LocationIn(latitud=-33.45, precision_codigo="EXACTA", fuente="Catastro")
        without_coordinates = LocationIn(
            precision_codigo="SIN_COORDENADAS", fuente="Pendiente"
        )
        self.assertIsNone(without_coordinates.latitud)
        self.assertIsNone(without_coordinates.longitud)

    def test_ranking_is_reproducible_and_explained(self):
        item = {
            "tipo_cobertura": "PERSONALIZADA",
            "comuna_id": 10,
            "latitud": -33.45,
            "longitud": -70.66,
            "distancia_km": 4.2,
        }
        first = _ranking(item, commune_id=10, jurisdiction_id=4, use_location=True)
        second = _ranking(item, commune_id=10, jurisdiction_id=4, use_location=True)
        self.assertEqual(first, second)
        self.assertGreater(first[0], 100)
        self.assertTrue(any("oferta" in reason.lower() for reason in first[1]))
        self.assertTrue(any("km" in reason for reason in first[1]))
        self.assertEqual(RANKING_VERSION, "H6-1.0")


if __name__ == "__main__":
    unittest.main()
