"""Configuration for optimization sessions."""

from __future__ import annotations

import sys
from pathlib import Path

import attrs

if sys.version_info >= (3, 11):
    from typing import Self
else:
    from typing_extensions import Self


@attrs.frozen
class OptimizationConfig:
    """Configuration for an optimization session.

    Carries project paths, test settings, and AI client
    configuration.  All fields are validated at construction
    time.  Use :meth:`from_dict` to restore a previously
    serialized config.
    """

    project_root: Path = attrs.field(converter=Path)
    module_root: Path = attrs.field(converter=Path)
    tests_root: Path = attrs.field(
        converter=Path,
        default=Path("tests"),
    )
    test_framework: str = "pytest"
    pytest_cmd: str = "pytest"
    ignore_paths: tuple[Path, ...] = ()
    api_key: str = ""
    n_candidates: int = 5
    ai_timeout: float = 120.0

    def to_dict(self) -> dict[str, object]:
        """Serialize to a plain dictionary."""
        return {
            "project_root": str(self.project_root),
            "module_root": str(self.module_root),
            "tests_root": str(self.tests_root),
            "test_framework": self.test_framework,
            "pytest_cmd": self.pytest_cmd,
            "ignore_paths": [str(p) for p in self.ignore_paths],
            "api_key": self.api_key,
            "n_candidates": self.n_candidates,
            "ai_timeout": self.ai_timeout,
        }

    @classmethod
    def from_dict(cls, data: dict[str, object]) -> Self:
        """Restore from a previously serialized dictionary."""
        ignore_raw: list[str] = data.get(  # type: ignore[assignment]
            "ignore_paths",
            [],
        )
        return cls(
            project_root=Path(str(data["project_root"])),
            module_root=Path(str(data["module_root"])),
            tests_root=Path(
                str(data.get("tests_root", "tests")),
            ),
            test_framework=str(
                data.get("test_framework", "pytest"),
            ),
            pytest_cmd=str(data.get("pytest_cmd", "pytest")),
            ignore_paths=tuple(Path(str(p)) for p in ignore_raw),
            api_key=str(data.get("api_key", "")),
            n_candidates=int(
                str(data.get("n_candidates", 5)),
            ),
            ai_timeout=float(
                str(data.get("ai_timeout", 120.0)),
            ),
        )
