from __future__ import annotations

import os
from dataclasses import dataclass
from pathlib import Path

from .paths import DEFAULT_RUNTIME_DIR, RuntimePaths, is_relative_to


@dataclass(frozen=True)
class Settings:
    env: str = "local"
    base_currency: str = "CHF"
    timezone: str = "Europe/Zurich"
    runtime_paths: RuntimePaths = RuntimePaths.from_base(DEFAULT_RUNTIME_DIR)
    log_level: str = "INFO"
    block_runtime_inside_repo: bool = True

    @property
    def db_path(self) -> Path:
        return self.runtime_paths.db_path


def find_repo_root(start: Path | None = None) -> Path:
    current = (start or Path.cwd()).resolve()
    for candidate in [current, *current.parents]:
        if (candidate / ".git").exists() or (candidate / "pyproject.toml").exists():
            return candidate
    return current


def load_settings(repo_root: Path | None = None, environ: dict[str, str] | None = None) -> Settings:
    env = environ or os.environ
    runtime_dir = Path(env.get("JARVIS_FINANCE_RUNTIME_DIR", str(DEFAULT_RUNTIME_DIR))).expanduser()
    paths = RuntimePaths.from_base(runtime_dir)
    db_override = env.get("JARVIS_FINANCE_DB_PATH")
    if db_override:
        object.__setattr__(paths, "db_path", Path(db_override).expanduser().resolve())
    settings = Settings(
        env=env.get("JARVIS_FINANCE_ENV", "local"),
        base_currency=env.get("JARVIS_FINANCE_BASE_CURRENCY", "CHF"),
        timezone=env.get("JARVIS_FINANCE_TIMEZONE", "Europe/Zurich"),
        runtime_paths=paths,
        log_level=env.get("JARVIS_FINANCE_LOG_LEVEL", "INFO"),
        block_runtime_inside_repo=env.get("JARVIS_FINANCE_BLOCK_RUNTIME_INSIDE_REPO", "1") not in {"0", "false", "False"},
    )
    validate_settings(settings, repo_root=repo_root)
    return settings


def validate_settings(settings: Settings, repo_root: Path | None = None) -> None:
    root = (repo_root or find_repo_root()).resolve()
    if settings.block_runtime_inside_repo and is_relative_to(settings.runtime_paths.base_dir, root):
        raise ValueError(f"Runtime directory must be outside the Git repository: {settings.runtime_paths.base_dir}")
    if settings.base_currency != "CHF":
        raise ValueError("MVP 1 base currency must be CHF")


def ensure_runtime_dirs(settings: Settings) -> None:
    settings.runtime_paths.ensure_dirs()
