"""Codex-internal TOML config writing — ported from yt-mcp's codexInternal.ts."""

from __future__ import annotations

import json
import re
from pathlib import Path


def get_codex_internal_config_path(home_dir: Path | str | None = None) -> Path:
    """Return the codex-internal config path."""
    if home_dir is None:
        home_dir = Path.home()
    else:
        home_dir = Path(home_dir)
    return home_dir / ".codex-internal" / "config.toml"


def _format_codex_internal_section(
    server_name: str,
    command: str,
    args: list[str],
) -> str:
    """Format a codex-internal TOML section for an MCP server."""
    # Escape server name for TOML table name
    escaped_name = server_name.replace('"', '\\"')
    # Format args as TOML array
    args_json = json.dumps(args)
    return (
        f'[mcp_servers."{escaped_name}"]\n'
        f'command = "{command}"\n'
        f'args = {args_json}\n'
    )


def upsert_codex_internal_config_text(
    current_text: str | None,
    server_name: str,
    command: str,
    args: list[str],
) -> str:
    """Upsert a server entry in codex-internal TOML text using regex."""
    section = _format_codex_internal_section(server_name, command, args).rstrip("\n")

    escaped_name = re.escape(server_name)
    # Why: older installs wrote `[mcp_servers.reddit-mcp]`, newer ones use quoted TOML keys.
    section_pattern = re.compile(
        rf'(?:^|\n)\[mcp_servers(?:\."{escaped_name}"|\.{escaped_name})\]\n(?:.+\n?)*?(?=\n\[|$)',
        re.MULTILINE,
    )

    if not current_text or current_text.strip() == "":
        return f"{section}\n"

    if section_pattern.search(current_text):
        # Replace existing section
        result = section_pattern.sub(f"\n{section}\n", current_text)
        return result.strip() + "\n"
    else:
        # Append new section
        return f"{current_text.rstrip()}\n\n{section}\n"


def remove_codex_internal_config_entry_text(
    current_text: str | None,
    server_name: str,
) -> dict[str, str | bool | None]:
    """Remove a server entry from codex-internal TOML text."""
    if not current_text:
        return {"changed": False, "next_text": None}

    escaped_name = re.escape(server_name)
    section_pattern = re.compile(
        rf'(?:^|\n)\[mcp_servers(?:\."{escaped_name}"|\.{escaped_name})\]\n(?:.+\n?)*?(?=\n\[|$)',
        re.MULTILINE,
    )

    if not section_pattern.search(current_text):
        return {"changed": False, "next_text": current_text}

    next_text = section_pattern.sub("\n", current_text)
    next_text = re.sub(r"\n{3,}", "\n\n", next_text).strip()
    
    return {
        "changed": True,
        "next_text": f"{next_text}\n" if next_text else None,
    }


def write_codex_internal_config(
    *,
    server_name: str,
    command: str,
    args: list[str],
    config_path: Path | str | None = None,
) -> str:
    """Write codex-internal MCP config.
    
    Returns:
        "created" or "updated"
    """
    if config_path is None:
        config_path = get_codex_internal_config_path()
    else:
        config_path = Path(config_path)

    existing_text = config_path.read_text("utf-8") if config_path.exists() else None
    created = existing_text is None
    next_text = upsert_codex_internal_config_text(existing_text, server_name, command, args)
    
    config_path.parent.mkdir(parents=True, exist_ok=True)
    config_path.write_text(next_text, "utf-8")
    
    return "created" if created else "updated"


def remove_codex_internal_config(
    *,
    server_name: str,
    config_path: Path | str | None = None,
) -> str:
    """Remove codex-internal MCP config entry.
    
    Returns:
        "removed" or "missing"
    """
    if config_path is None:
        config_path = get_codex_internal_config_path()
    else:
        config_path = Path(config_path)

    existing_text = config_path.read_text("utf-8") if config_path.exists() else None
    result = remove_codex_internal_config_entry_text(existing_text, server_name)
    
    if not result["changed"]:
        return "missing"

    next_text = result["next_text"]
    if next_text is None:
        config_path.unlink(missing_ok=True)
    else:
        config_path.parent.mkdir(parents=True, exist_ok=True)
        config_path.write_text(next_text, "utf-8")
    
    return "removed"
