"""Green-Acres source — wraps the existing legacy implementation.

This is a thin adapter rather than a rewrite: the legacy search_greenacres()
in search_properties.py works fine; rewriting it would risk regressions for
no behavioral gain. The adapter:
- Translates SearchCriteria → the legacy fixed-regions iteration
- Yields normalized PropertyHit records
- Adds a health() preflight (HEAD against green-acres.fr to detect blocks)

When upstream filtering is added (price/size in URL), it should land here
and bypass the legacy code path.
"""
from __future__ import annotations

import sys
from pathlib import Path
from typing import Iterator

import requests

# Allow `from store import ...` and importing the legacy module
SCRIPT_DIR = Path(__file__).resolve().parent.parent
if str(SCRIPT_DIR) not in sys.path:
    sys.path.insert(0, str(SCRIPT_DIR))

from store import load                                       # noqa: E402
from sources._base import PropertyHit, SearchCriteria, Source  # noqa: E402

# Region map: SearchCriteria.region slug → (country_tld, region_slug, display_name)
# Built from the legacy REGIONS_GREENACRES in search_properties.py
REGION_MAP = {
    # France — top vibe (★★★★★)
    'drome':           ('fr', 'drome', 'Drôme'),
    'ardeche':         ('fr', 'ardeche', 'Ardèche'),
    'herault':         ('fr', 'herault', 'Hérault'),
    'cotes-d-armor':   ('fr', 'cotes-d-armor', "Côtes-d'Armor"),
    'morbihan':        ('fr', 'morbihan', 'Morbihan'),
    'finistere':       ('fr', 'finistere', 'Finistère'),
    # France — strong vibe (★★★★)
    'charente':         ('fr', 'charente', 'Charente'),
    'charente-maritime': ('fr', 'charente-maritime', 'Charente-Maritime'),
    # France — good vibe (★★★)
    'dordogne':        ('fr', 'dordogne', 'Dordogne'),
    'gard':            ('fr', 'gard', 'Gard'),
    'lot':             ('fr', 'lot', 'Lot'),
    'correze':         ('fr', 'correze', 'Corrèze'),
    'creuse':          ('fr', 'creuse', 'Creuse'),
    # France — favourite (★★)
    'gers':            ('fr', 'gers', 'Gers'),
    'lot-et-garonne':  ('fr', 'lot-et-garonne', 'Lot-et-Garonne'),
    'mayenne':         ('fr', 'mayenne', 'Mayenne'),
    # France — adjacent
    'orne':            ('fr', 'orne', 'Orne'),
    'indre':           ('fr', 'indre', 'Indre'),
    'deux-sevres':     ('fr', 'deux-sevres', 'Deux-Sèvres'),
    'sarthe':          ('fr', 'sarthe', 'Sarthe'),
    # France — Massif Central + Pyrenean + south-Languedoc (added 2026-05-27)
    'cantal':          ('fr', 'cantal', 'Cantal'),
    'aveyron':         ('fr', 'aveyron', 'Aveyron'),
    'lozere':          ('fr', 'lozere', 'Lozère'),
    'tarn':            ('fr', 'tarn', 'Tarn'),
    'tarn-et-garonne': ('fr', 'tarn-et-garonne', 'Tarn-et-Garonne'),
    'pyrenees-atlantiques': ('fr', 'pyrenees-atlantiques', 'Pyrénées-Atlantiques'),
    'hautes-pyrenees': ('fr', 'hautes-pyrenees', 'Hautes-Pyrénées'),
    'aude':            ('fr', 'aude', 'Aude'),
    'pyrenees-orientales': ('fr', 'pyrenees-orientales', 'Pyrénées-Orientales'),
    # Italy
    'marche':          ('it', 'marche', 'Le Marche'),
    'umbria':          ('it', 'umbria', 'Umbria'),
    'toscana':         ('it', 'toscana', 'Tuscany'),
    'liguria':         ('it', 'liguria', 'Liguria'),
}


class GreenAcresSource(Source):
    name = 'greenacres'
    countries = ['FR', 'IT']
    requires_auth = False

    def health(self) -> tuple[bool, str]:
        """GET probe against green-acres.fr root.
        Note: HEAD often returns 405 on these sites, so we use a tiny GET."""
        try:
            r = requests.get('https://www.green-acres.fr/',
                             headers={'User-Agent': 'paradisomatch/1.0'},
                             timeout=8, allow_redirects=True, stream=True)
            if r.status_code >= 400:
                return False, f'HTTP {r.status_code}'
            r.close()
            return True, 'reachable'
        except requests.RequestException as e:
            return False, f'{type(e).__name__}'

    def search(self, criteria: SearchCriteria,
               known_urls: set[str] | None = None) -> Iterator[PropertyHit]:
        """Run the legacy search for a single region, yield normalized hits.

        The legacy implementation handles the full regions list internally,
        so we filter its output to the requested region. For multi-region
        campaigns, the orchestrator calls search() once per region.

        IMPORTANT: known_urls is converted to a {url: True} dict and passed
        as the legacy `store` argument. Without this, the legacy function
        re-parses every cached card on every run and `limit` counts cached
        re-discoveries toward the cap (eval bug #2, #3).
        """
        # Import lazily — avoids loading the heavy legacy module unless needed
        from search_properties import search_greenacres

        if criteria.region and criteria.region not in REGION_MAP:
            return  # unknown region for this source

        # Temporarily restrict the legacy regions list to the one we want.
        # The legacy code reads REGIONS_GREENACRES at call time, so we mutate
        # the module-level list (restoring after). Safe because the orchestrator
        # is single-threaded and we restore in a finally block.
        import search_properties as legacy
        original_regions = legacy.REGIONS_GREENACRES
        original_criteria = legacy.CRITERIA.copy()

        try:
            if criteria.region:
                target = REGION_MAP[criteria.region]
                legacy.REGIONS_GREENACRES = [target]
            # Push upstream filters by overriding the legacy CRITERIA dict
            if criteria.min_price is not None:
                legacy.CRITERIA['price_min'] = criteria.min_price
            if criteria.max_price is not None:
                legacy.CRITERIA['price_max'] = criteria.max_price
            if criteria.min_bedrooms is not None:
                legacy.CRITERIA['bedrooms_min'] = criteria.min_bedrooms

            # Pass known URLs as a fake "store" — legacy code only does
            # `set(store.keys())` then `prop_url in existing`. Limit defaults
            # to 50 (sane cap) if None, NOT 0 which legacy treats as unlimited.
            seed_store = {u: True for u in (known_urls or ())}
            limit = criteria.limit if criteria.limit is not None else 50
            results = search_greenacres(seed_store, limit, criteria.max_pages)
        finally:
            legacy.REGIONS_GREENACRES = original_regions
            legacy.CRITERIA = original_criteria

        for r in results:
            # Apply min_land_m2 / min_building_m2 downstream filtering
            # (Green-Acres URL doesn't support these as query params,
            # so we filter the returned cards instead).
            if criteria.min_land_m2 and (r.get('land_size') or 0) < criteria.min_land_m2:
                continue
            if criteria.min_building_m2 and (r.get('building_size') or 0) < criteria.min_building_m2:
                continue
            yield PropertyHit(
                url=r['url'],
                source=r['source'],
                title=r.get('title'),
                price=r.get('price'),
                city=r.get('city'),
                country=r.get('country'),
                building_size=r.get('building_size'),
                land_size=r.get('land_size'),
                bedrooms=r.get('bedrooms'),
                rooms=r.get('rooms'),
                thumbnail=r.get('thumbnail'),
                search_region=r.get('search_region'),
            )
