import copy
import json
import logging
import tomllib
from pathlib import Path
from typing import Any

logger = logging.getLogger(__name__)


def deep_update_dict(target: dict[str, Any], updates: dict[str, Any]) -> None:
    for key, value in updates.items():
        if isinstance(value, dict) and isinstance(target.get(key), dict):
            deep_update_dict(target[key], value)
        else:
            target[key] = value


def _normalize_str_list(raw: Any) -> list[str] | None:
    if not isinstance(raw, list):
        return None

    values: list[str] = []
    for item in raw:
        if not isinstance(item, str):
            return None
        stripped = item.strip()
        if stripped:
            values.append(stripped)
    return values


def _read_pyrightconfig(workspace: Path) -> dict[str, Any]:
    path = workspace / "pyrightconfig.json"
    if not path.is_file():
        return {}

    try:
        data = json.loads(path.read_text(encoding="utf-8"))
    except Exception as e:
        logger.debug("Failed to read pyrightconfig.json: %s", e)
        return {}

    if not isinstance(data, dict):
        return {}

    analysis: dict[str, Any] = {}
    for key in ("include", "exclude", "ignore"):
        values = _normalize_str_list(data.get(key))
        if values is not None:
            analysis[key] = values

    if not analysis:
        return {}
    return {"basedpyright": {"analysis": analysis}}


def _read_pyproject(workspace: Path) -> dict[str, Any]:
    path = workspace / "pyproject.toml"
    if not path.is_file():
        return {}

    try:
        data = tomllib.loads(path.read_text(encoding="utf-8"))
    except Exception as e:
        logger.debug("Failed to read pyproject.toml: %s", e)
        return {}

    if not isinstance(data, dict):
        return {}

    tool = data.get("tool")
    if not isinstance(tool, dict):
        return {}

    section = tool.get("basedpyright")
    if not isinstance(section, dict):
        section = tool.get("pyright")
    if not isinstance(section, dict):
        return {}

    analysis: dict[str, Any] = {}
    for key in ("include", "exclude", "ignore"):
        values = _normalize_str_list(section.get(key))
        if values is not None:
            analysis[key] = values

    if not analysis:
        return {}
    return {"basedpyright": {"analysis": analysis}}


def load_project_workspace_settings(workspace: Path) -> dict[str, Any]:
    settings: dict[str, Any] = {}
    deep_update_dict(settings, _read_pyproject(workspace))
    deep_update_dict(settings, _read_pyrightconfig(workspace))
    return settings


def build_workspace_settings(
    workspace_config: dict[str, Any],
    language_id: str,
    workspace: str,
) -> dict[str, Any]:
    settings = copy.deepcopy(workspace_config)
    if language_id == "python":
        project_settings = load_project_workspace_settings(Path(workspace))
        deep_update_dict(settings, project_settings)
    return settings
