#!/usr/bin/env python3
from __future__ import annotations

import json
from pathlib import Path
from typing import Any, Dict, List

try:
    from .cheapclaw_runtime_state import CheapClawPaths, atomic_write_text, load_json
except ImportError:
    from cheapclaw_runtime_state import CheapClawPaths, atomic_write_text, load_json


def load_cheapclaw_app_config_example(example_path: str | Path) -> Dict[str, Any]:
    fallback = {
        "runtime": {
            "action_window_steps": 20,
            "thinking_interval": 20,
            "fresh_enabled": False,
            "fresh_interval_sec": 0,
        },
        "env": {
            "command_mode": "direct",
            "seed_builtin_resources": False,
        },
        "cheapclaw": {
            "watchdog_interval_sec": 86400,
            "default_exposed_skills": ["docx", "pptx", "xlsx", "find-skills"],
            "default_mcp_servers": [],
            "feishu_mode": "long_connection",
            "service_log_file": "cheapclaw_service.log",
        },
    }
    return load_json(Path(example_path).expanduser().resolve(), fallback)


def extract_cheapclaw_settings(payload: Dict[str, Any], *, example_path: str | Path) -> Dict[str, Any]:
    payload = payload if isinstance(payload, dict) else {}
    example_payload = load_cheapclaw_app_config_example(example_path)
    example_cheapclaw = example_payload.get("cheapclaw", {}) if isinstance(example_payload.get("cheapclaw"), dict) else {}
    cheapclaw = payload.get("cheapclaw", {}) if isinstance(payload.get("cheapclaw"), dict) else {}
    default_skills = cheapclaw.get(
        "default_exposed_skills",
        example_cheapclaw.get("default_exposed_skills", ["docx", "pptx", "xlsx", "find-skills"]),
    )
    if not isinstance(default_skills, list):
        default_skills = list(example_cheapclaw.get("default_exposed_skills", ["docx", "pptx", "xlsx", "find-skills"]))
    default_mcp_servers = cheapclaw.get("default_mcp_servers", example_cheapclaw.get("default_mcp_servers", []))
    if not isinstance(default_mcp_servers, list):
        default_mcp_servers = list(example_cheapclaw.get("default_mcp_servers", []))
    return {
        "watchdog_interval_sec": max(
            60,
            int(
                cheapclaw.get(
                    "watchdog_interval_sec",
                    example_cheapclaw.get("watchdog_interval_sec", 86400),
                )
                or example_cheapclaw.get("watchdog_interval_sec", 86400)
            ),
        ),
        "default_exposed_skills": [str(item).strip() for item in default_skills if str(item).strip()],
        "default_mcp_servers": [item for item in default_mcp_servers if isinstance(item, dict)],
        "feishu_mode": str(cheapclaw.get("feishu_mode") or example_cheapclaw.get("feishu_mode", "long_connection")).strip() or "long_connection",
        "service_log_file": str(cheapclaw.get("service_log_file") or example_cheapclaw.get("service_log_file", "cheapclaw_service.log")).strip() or "cheapclaw_service.log",
    }


def ensure_cheapclaw_app_config(paths: CheapClawPaths, *, example_path: str | Path) -> Dict[str, Any]:
    paths.config_dir.mkdir(parents=True, exist_ok=True)
    example_payload = load_cheapclaw_app_config_example(example_path)
    atomic_write_text(paths.app_config_example_path, json.dumps(example_payload, ensure_ascii=False, indent=2))
    if not paths.app_config_path.exists():
        atomic_write_text(paths.app_config_path, json.dumps(example_payload, ensure_ascii=False, indent=2))
    payload = load_json(paths.app_config_path, example_payload)
    if not isinstance(payload, dict):
        payload = {}
    runtime_cfg = payload.setdefault("runtime", {})
    if not isinstance(runtime_cfg, dict):
        runtime_cfg = {}
        payload["runtime"] = runtime_cfg
    runtime_cfg.setdefault("action_window_steps", example_payload["runtime"]["action_window_steps"])
    runtime_cfg.setdefault("thinking_interval", example_payload["runtime"]["thinking_interval"])
    runtime_cfg.setdefault("fresh_enabled", example_payload["runtime"]["fresh_enabled"])
    runtime_cfg.setdefault("fresh_interval_sec", example_payload["runtime"]["fresh_interval_sec"])
    if int(runtime_cfg.get("action_window_steps", 20) or 20) == 20 and int(runtime_cfg.get("thinking_interval", 20) or 20) == 10:
        runtime_cfg["thinking_interval"] = 20
    env_cfg = payload.setdefault("env", {})
    if not isinstance(env_cfg, dict):
        env_cfg = {}
        payload["env"] = env_cfg
    env_cfg["seed_builtin_resources"] = False
    env_cfg.setdefault("command_mode", example_payload["env"]["command_mode"])
    context_cfg = payload.setdefault("context", {})
    if not isinstance(context_cfg, dict):
        context_cfg = {}
        payload["context"] = context_cfg
    example_context = example_payload.get("context", {})
    if not isinstance(example_context, dict):
        example_context = {}
    context_cfg.setdefault(
        "user_history_compress_threshold_tokens",
        int(example_context.get("user_history_compress_threshold_tokens", 1500) or 1500),
    )
    context_cfg.setdefault(
        "structured_call_info_compress_threshold_agents",
        int(example_context.get("structured_call_info_compress_threshold_agents", 10) or 10),
    )
    context_cfg.setdefault(
        "structured_call_info_compress_threshold_tokens",
        int(example_context.get("structured_call_info_compress_threshold_tokens", 2200) or 2200),
    )
    context_cfg["user_history_compress_threshold_tokens"] = max(
        0,
        int(context_cfg.get("user_history_compress_threshold_tokens", 1500) or 1500),
    )
    context_cfg["structured_call_info_compress_threshold_agents"] = max(
        1,
        int(context_cfg.get("structured_call_info_compress_threshold_agents", 10) or 10),
    )
    context_cfg["structured_call_info_compress_threshold_tokens"] = max(
        0,
        int(context_cfg.get("structured_call_info_compress_threshold_tokens", 2200) or 2200),
    )
    cheapclaw_cfg = payload.setdefault("cheapclaw", {})
    if not isinstance(cheapclaw_cfg, dict):
        cheapclaw_cfg = {}
        payload["cheapclaw"] = cheapclaw_cfg
    for key, value in example_payload["cheapclaw"].items():
        cheapclaw_cfg.setdefault(key, value)
    default_skills = cheapclaw_cfg.get("default_exposed_skills", [])
    if not isinstance(default_skills, list):
        default_skills = list(example_payload["cheapclaw"].get("default_exposed_skills", []))
    for skill_name in example_payload["cheapclaw"].get("default_exposed_skills", []):
        if skill_name not in default_skills:
            default_skills.append(skill_name)
    cheapclaw_cfg["default_exposed_skills"] = default_skills
    if not isinstance(cheapclaw_cfg.get("default_mcp_servers"), list):
        cheapclaw_cfg["default_mcp_servers"] = list(example_payload["cheapclaw"].get("default_mcp_servers", []))
    atomic_write_text(paths.app_config_path, json.dumps(payload, ensure_ascii=False, indent=2))
    return payload


def sync_root_app_config_from_cheapclaw(user_data_root: Path, cheapclaw_cfg: Dict[str, Any]) -> None:
    root_path = Path(user_data_root).expanduser().resolve() / "config" / "app_config.json"
    root_path.parent.mkdir(parents=True, exist_ok=True)
    payload = load_json(root_path, {})
    if not isinstance(payload, dict):
        payload = {}
    runtime_cfg = cheapclaw_cfg.get("runtime", {}) if isinstance(cheapclaw_cfg, dict) else {}
    context_cfg = cheapclaw_cfg.get("context", {}) if isinstance(cheapclaw_cfg, dict) else {}
    env_cfg = payload.setdefault("env", {})
    env_cfg["seed_builtin_resources"] = False
    env_cfg.setdefault("command_mode", "direct")
    runtime = payload.setdefault("runtime", {})
    if isinstance(runtime_cfg, dict):
        for key in ("action_window_steps", "thinking_interval", "fresh_enabled", "fresh_interval_sec"):
            if key in runtime_cfg:
                runtime[key] = runtime_cfg[key]
    context = payload.setdefault("context", {})
    if isinstance(context_cfg, dict):
        for key in (
            "user_history_compress_threshold_tokens",
            "structured_call_info_compress_threshold_agents",
            "structured_call_info_compress_threshold_tokens",
        ):
            if key in context_cfg:
                context[key] = context_cfg[key]
    payload.pop("cheapclaw", None)
    root_path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")


def load_channels_config_for_root(user_data_root: str | Path, *, channels_example_path: str | Path) -> Dict[str, Any]:
    root = Path(user_data_root).expanduser().resolve()
    channels_path = root / "cheapclaw" / "config" / "channels.json"
    example_path = Path(channels_example_path).expanduser().resolve()
    return load_json(channels_path, load_json(example_path, {}))


def enabled_channel_bot_specs(config: Dict[str, Any]) -> List[Dict[str, str]]:
    specs: List[Dict[str, str]] = []
    if not isinstance(config, dict):
        return specs
    required_fields = {
        "telegram": ["bot_token"],
        "feishu": ["app_id", "app_secret"],
        "whatsapp": ["access_token", "phone_number_id"],
        "discord": ["bot_token"],
        "qq": ["onebot_api_base"],
        "wechat": ["onebot_api_base"],
        "localweb": [],
    }
    for channel, fields in required_fields.items():
        payload = config.get(channel) or {}
        if not isinstance(payload, dict) or not payload.get("enabled"):
            continue
        if not all(str(payload.get(field) or "").strip() for field in fields):
            continue
        bot_id = str(payload.get("bot_id") or channel).strip() or channel
        display_name = str(payload.get("display_name") or bot_id).strip() or bot_id
        specs.append({
            "channel": channel,
            "bot_id": bot_id,
            "display_name": display_name,
        })
    return specs
