"""
Manages the .venvy/config.json file stored in each project directory.
This file is the equivalent of package.json metadata for venvy.
"""

from __future__ import annotations

import json
from pathlib import Path
from typing import Optional

VENVY_DIR = ".venvy"
CONFIG_FILE = "config.json"
DEFAULT_VENV_NAME = ".venv"
DEFAULT_REQ_FILE = "requirements.txt"


class VenvyConfig:
    """Represents the per-project venvy configuration."""

    def __init__(
        self,
        venv_name: str = DEFAULT_VENV_NAME,
        requirements_file: str = DEFAULT_REQ_FILE,
        install_ipykernel: bool = False,
    ) -> None:
        self.venv_name = venv_name
        self.requirements_file = requirements_file
        self.install_ipykernel = install_ipykernel

    def to_dict(self) -> dict:
        return {
            "venv_name": self.venv_name,
            "requirements_file": self.requirements_file,
            "install_ipykernel": self.install_ipykernel,
        }

    @classmethod
    def from_dict(cls, data: dict) -> "VenvyConfig":
        return cls(
            venv_name=data.get("venv_name", DEFAULT_VENV_NAME),
            requirements_file=data.get("requirements_file", DEFAULT_REQ_FILE),
            install_ipykernel=data.get("install_ipykernel", False),
        )


def get_config_path(cwd: Optional[Path] = None) -> Path:
    base = cwd or Path.cwd()
    return base / VENVY_DIR / CONFIG_FILE


def load_config(cwd: Optional[Path] = None) -> Optional[VenvyConfig]:
    """Load config from .venvy/config.json if it exists."""
    path = get_config_path(cwd)
    if not path.exists():
        return None
    try:
        data = json.loads(path.read_text(encoding="utf-8"))
        return VenvyConfig.from_dict(data)
    except (json.JSONDecodeError, OSError):
        return None


def save_config(config: VenvyConfig, cwd: Optional[Path] = None) -> None:
    """Persist config to .venvy/config.json."""
    path = get_config_path(cwd)
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(
        json.dumps(config.to_dict(), indent=2), encoding="utf-8"
    )


def find_project_root(start: Optional[Path] = None) -> Optional[Path]:
    """Walk up directory tree looking for a .venvy config directory."""
    current = (start or Path.cwd()).resolve()
    for directory in [current, *current.parents]:
        if (directory / VENVY_DIR / CONFIG_FILE).exists():
            return directory
    return None
