"""Heat and filter relay GPIO outputs."""

from __future__ import annotations

import logging

from .config import GpioConfig

logger = logging.getLogger("hot_tub.control")


class RelayOutputs:
    """Thin wrapper so --dry-run can skip real GPIO."""

    def __init__(self, gpio: GpioConfig, *, dry_run: bool) -> None:
        self.dry_run = dry_run
        self.heat_on = False
        self.filter_on = False
        self._heat = None
        self._filter = None

        if dry_run:
            return

        try:
            from gpiozero import OutputDevice
        except ImportError as exc:
            raise SystemExit(
                "gpiozero is required on the Pi. Install with:\n"
                "  sudo apt install python3-gpiozero\n"
                "Or run with --dry-run to exercise the loop without GPIO."
            ) from exc

        self._heat = OutputDevice(
            gpio.heat_pump,
            active_high=gpio.active_high,
            initial_value=False,
        )
        self._filter = OutputDevice(
            gpio.filter_pump,
            active_high=gpio.active_high,
            initial_value=False,
        )
        logger.info(
            "GPIO initialized heat=%s filter=%s active_high=%s",
            gpio.heat_pump,
            gpio.filter_pump,
            gpio.active_high,
        )

    def set_heat(self, on: bool) -> None:
        if self.heat_on == on:
            return
        self.heat_on = on
        if self._heat is not None:
            self._heat.on() if on else self._heat.off()
        logger.info("heat relay %s", "ON" if on else "OFF")

    def set_filter(self, on: bool) -> None:
        if self.filter_on == on:
            return
        self.filter_on = on
        if self._filter is not None:
            self._filter.on() if on else self._filter.off()
        logger.info("filter relay %s", "ON" if on else "OFF")

    def sync(self, *, heat: bool, filter_pump: bool) -> None:
        self.set_heat(heat)
        self.set_filter(filter_pump)

    def all_off(self) -> None:
        self.set_heat(False)
        self.set_filter(False)

    def close(self) -> None:
        self.all_off()
        if self._heat is not None:
            self._heat.close()
        if self._filter is not None:
            self._filter.close()
