from __future__ import annotations

"""
Core generator for Python -> TypeScript declarations (orchestrator).

- Parses static types (dataclasses, Enums, TypedDicts, type aliases) from .py
  files via AST (no runtime import side effects).
- Captures Python function signatures into TS interfaces via a decorator.
- Emits a single .ts file with all collected declarations.
"""

from pathlib import Path
from typing import Any, Iterable

from .typescript import (
    DEFAULT_RESOLVER,
    ts_from_ast as _ts_from_ast_resolver,
    anno_to_ts as _anno_to_ts_resolver,
    string_anno_to_ts as _string_anno_to_ts_resolver,
)
from .static_extract import python_file_to_ts as _python_file_to_ts
from .interfaces import InterfaceCollector


def _ts_from_ast(expr) -> str:
    """Compatibility wrapper - use shared resolver."""
    return _ts_from_ast_resolver(expr)


def _string_anno_to_ts(text: str) -> str:
    return _string_anno_to_ts_resolver(text)


def _anno_to_ts(anno: Any) -> str:
    return _anno_to_ts_resolver(anno)


class TsGen:
    """Collect static types and function signatures -> emit TypeScript.

    Parameters
    ----------
    py_types : str | Path | list[str|Path]
        Python files to scan (dataclasses, Enums, type aliases).
    out_ts : Path | str
        Output .ts file.
    return_wrapper : str | None
        Optional format string wrapping function return type, with `{ret}`
        placeholder. Example for Eel: "() => Promise<{ret}>".
    """

    def __init__(
        self,
        *,
        py_types: str | Path | Iterable[str | Path] = (),
        out_ts: Path | str = Path("types.generated.ts"),
        return_wrapper: str | None = None,
    ) -> None:
        self._py_files: list[Path] = []
        if isinstance(py_types, (str, Path)):
            if py_types:
                self._py_files = [Path(py_types)]
        else:
            self._py_files = [Path(p) for p in py_types]
        self._out_ts = Path(out_ts)
        self._collector = InterfaceCollector(DEFAULT_RESOLVER, return_wrapper)

    # Decorator to capture functions
    def interface(self, name: str):
        return self._collector.interface(name)

    def _emit_static(self) -> str:
        blocks = [_python_file_to_ts(p, DEFAULT_RESOLVER) for p in self._py_files]
        return "\n\n".join(b for b in blocks if b)

    def _emit_interfaces(self) -> str:
        return self._collector.emit()

    def produce_ts(self) -> str:
        header = [
            "// This file is auto-generated by bisex.",
            "// Do not edit manually.",
        ]
        static = self._emit_static()
        inter = self._emit_interfaces()
        return "\n\n".join([s for s in ["\n".join(header), static, inter] if s]).rstrip() + "\n"

    def generate(self) -> Path:
        out = self.produce_ts()
        self._out_ts.parent.mkdir(parents=True, exist_ok=True)
        self._out_ts.write_text(out, encoding="utf-8")
        return self._out_ts
