# Copyright © 2025-26 l5yth & contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""High-level API for the potato-mesh ingestor."""

from __future__ import annotations

import signal as signal  # re-exported for compatibility
import threading as threading  # re-exported for compatibility
import sys
import types

from .. import VERSION as _PACKAGE_VERSION
from . import (
    channels,
    config,
    daemon,
    handlers,
    ingestors,
    interfaces,
    queue,
    serialization,
)

__all__: list[str] = []


def _reexport(module) -> None:
    names = getattr(module, "__all__", [])
    for name in names:
        globals()[name] = getattr(module, name)
    __all__.extend(names)


def _export_constants() -> None:
    globals()["json"] = queue.json
    globals()["urllib"] = queue.urllib
    globals()["glob"] = interfaces.glob
    __all__.extend(["json", "urllib", "glob", "threading", "signal"])


for _module in (
    channels,
    daemon,
    handlers,
    interfaces,
    queue,
    serialization,
    ingestors,
):
    _reexport(_module)

_export_constants()

_CONFIG_ATTRS = {
    "CONNECTION",
    "SNAPSHOT_SECS",
    "CHANNEL_INDEX",
    "DEBUG",
    "INSTANCE",
    "API_TOKEN",
    "ALLOWED_CHANNELS",
    "HIDDEN_CHANNELS",
    "LORA_FREQ",
    "MODEM_PRESET",
    "_RECONNECT_INITIAL_DELAY_SECS",
    "_RECONNECT_MAX_DELAY_SECS",
    "_CLOSE_TIMEOUT_SECS",
    "_INGESTOR_HEARTBEAT_SECS",
    "_debug_log",
}

# Legacy export maintained for backwards compatibility.
_CONFIG_ATTRS.add("PORT")

_INTERFACE_ATTRS = {"BLEInterface", "SerialInterface", "TCPInterface"}

_QUEUE_ATTRS = set(queue.__all__)
_HANDLER_ATTRS = set(handlers.__all__)
_DAEMON_ATTRS = set(daemon.__all__)
_SERIALIZATION_ATTRS = set(serialization.__all__)
_INTERFACE_EXPORTS = set(interfaces.__all__)
_INGESTOR_ATTRS = set(ingestors.__all__)

# Re-export the package version for callers that previously referenced
# data.mesh_ingestor.VERSION directly.
VERSION = _PACKAGE_VERSION
__all__.append("VERSION")

__all__.extend(sorted(_CONFIG_ATTRS))
__all__.extend(sorted(_INTERFACE_ATTRS))
__all__.append("VERSION")


class _MeshIngestorModule(types.ModuleType):
    """Module proxy that forwards config and interface state."""

    def __getattr__(self, name: str):  # type: ignore[override]
        """Resolve attributes by delegating to the underlying submodules."""

        if name in _CONFIG_ATTRS:
            return getattr(config, name)
        if name in _INTERFACE_ATTRS:
            return getattr(interfaces, name)
        if name in _INTERFACE_EXPORTS:
            return getattr(interfaces, name)
        if name in _INGESTOR_ATTRS:
            return getattr(ingestors, name)
        if name == "VERSION":
            return VERSION
        raise AttributeError(name)

    def __setattr__(self, name: str, value):  # type: ignore[override]
        """Propagate assignments to the appropriate submodule."""

        if name in _CONFIG_ATTRS:
            setattr(config, name, value)
            super().__setattr__(name, value)
            return
        if name in _INTERFACE_ATTRS:
            setattr(interfaces, name, value)
            super().__setattr__(name, value)
            return
        handled = False
        if name in _INTERFACE_EXPORTS:
            setattr(interfaces, name, value)
            super().__setattr__(name, getattr(interfaces, name, value))
            handled = True
        if name in _QUEUE_ATTRS:
            setattr(queue, name, value)
            super().__setattr__(name, getattr(queue, name, value))
            handled = True
        if name in _HANDLER_ATTRS:
            setattr(handlers, name, value)
            super().__setattr__(name, getattr(handlers, name, value))
            handled = True
        if name in _DAEMON_ATTRS:
            setattr(daemon, name, value)
            super().__setattr__(name, getattr(daemon, name, value))
            handled = True
        if name in _SERIALIZATION_ATTRS:
            setattr(serialization, name, value)
            super().__setattr__(name, getattr(serialization, name, value))
            handled = True
        if name in _INGESTOR_ATTRS:
            setattr(ingestors, name, value)
            super().__setattr__(name, getattr(ingestors, name, value))
            handled = True
        if handled:
            return
        super().__setattr__(name, value)


sys.modules[__name__].__class__ = _MeshIngestorModule
