from __future__ import print_function
from .bayou_radar import BayouRadarClient
from .nws import NWSClient
from .source_result import FetchResult


class AlertSourceCoordinator(object):
    """Bayou Radar primary source with direct NWS per-area fallback."""

    def __init__(self, config):
        self.config = config
        self.primary = BayouRadarClient(config.get("bayou_radar") or {})
        self.fallback = NWSClient(config.get("nws") or {})

    @staticmethod
    def _merge_alerts(target, source):
        for alert in source.alerts.values():
            target.add_alert(alert)

    def fetch(self, areas):
        final = FetchResult()
        primary = self.primary.fetch(areas)
        self._merge_alerts(final, primary)
        final.primary_successful_areas = set(primary.successful_areas)
        final.primary_failed_areas = set(primary.failed_areas)
        final.primary_healthy = not bool(primary.failed_areas)
        final.errors.extend(primary.errors)
        final.source_by_area.update(primary.source_by_area)

        area_codes = [str((area.get("code") if isinstance(area, dict) else area) or "").strip().upper() for area in areas]
        fallback_enabled = bool((self.config.get("data_sources") or {}).get("fallback_enabled", True))
        fallback_codes = sorted(primary.failed_areas) if fallback_enabled else []
        fallback_result = self.fallback.fetch(fallback_codes) if fallback_codes else FetchResult()
        self._merge_alerts(final, fallback_result)
        final.errors.extend(["NWS fallback %s" % error for error in fallback_result.errors])

        for code in area_codes:
            if not code:
                continue
            if code in primary.successful_areas:
                final.successful_areas.add(code)
                final.source_by_area[code] = "bayou_radar"
            elif code in fallback_result.successful_areas:
                final.successful_areas.add(code)
                final.fallback_areas.add(code)
                final.source_by_area[code] = "nws_fallback"
            else:
                final.failed_areas.add(code)
                final.source_by_area[code] = "unavailable"
        return final
