import os
import json
from typing import Dict, Any, Optional
from .utils import load_dotenv
from .schema import validate, SchemaError

try:
    import yaml
except ImportError:
    yaml = None

class EnvGenie:
    def __init__(self, config_path: str = "config.yaml", defaults: Dict[str, Any] = None):
        self.config_path = config_path
        self.defaults = defaults or {}
        self.file_config = self._load_file_config()
        self.dotenv = load_dotenv(".env")
        self.env = dict(os.environ)
        self.profile = os.environ.get("ENVGENIE_PROFILE") or self.file_config.get("profile") or "development"

    def _load_file_config(self) -> Dict[str, Any]:
        try:
            with open(self.config_path, "r", encoding="utf-8") as f:
                text = f.read()
                if yaml:
                    return yaml.safe_load(text) or {}
                return json.loads(text)
        except Exception:
            return {}

    def _resolve_key(self, key: str) -> Optional[str]:
        if key in self.env:
            return self.env[key]
        if key in self.dotenv:
            return self.dotenv[key]
        profile_data = self.file_config.get(self.profile, {})
        if isinstance(profile_data, dict) and key in profile_data:
            return profile_data[key]
        if key in self.file_config:
            return self.file_config[key]
        if key in self.defaults:
            return self.defaults[key]
        return None

    def get(self, key: str, cast: type = str, default: Any = None) -> Any:
        raw = self._resolve_key(key)
        if raw is None:
            raw = default
        if raw is None:
            return None
        try:
            if cast is bool:
                if isinstance(raw, bool):
                    return raw
                if raw.lower() in ("1", "true", "yes", "on"):
                    return True
                if raw.lower() in ("0", "false", "no", "off"):
                    return False
            return cast(raw)
        except Exception:
            raise ValueError(f"Cannot convert {key!r}: {raw!r}")

    def load_schema(self, schema: Dict[str, type]) -> Dict[str, Any]:
        resolved = {key: self._resolve_key(key) for key in schema.keys()}
        validate(schema, resolved)
        return {key: self.get(key, cast=t) for key, t in schema.items()}

    def explain(self, key: str) -> str:
        if key in self.env:
            return "environment"
        if key in self.dotenv:
            return ".env file"
        profile_data = self.file_config.get(self.profile, {})
        if isinstance(profile_data, dict) and key in profile_data:
            return f"config file (profile={self.profile})"
        if key in self.file_config:
            return "config file (top-level)"
        if key in self.defaults:
            return "defaults"
        return "not set"
