# -*- coding: utf-8 -*-
"""mcp-config-sync CLI entry point."""
import sys
import os
import json
import argparse
from pathlib import Path

# Allow running as module or standalone
if __name__ == "__main__" or not __package__:
    sys.path.insert(0, str(Path(__file__).parent.parent))
from mcp_config_sync.config import (
    read_config, write_config, merge_configs, create_template, list_servers,
)
from mcp_config_sync.validator import validate_config
from mcp_config_sync.diff import diff_configs
from mcp_config_sync.registry import register_config, list_registered
from mcp_config_sync.detector import detect_configs, print_detection_report
from mcp_config_sync.sync_engine import build_sync_plan, apply_sync


def cmd_init(args):
    """Create .mcp.json template in current directory."""
    target = Path(args.path) if args.path else Path.cwd() / ".mcp.json"
    if target.exists() and not args.force:
        print(f"Error: {target} already exists. Use --force to overwrite.")
        return 1

    template = create_template()
    write_config(target, template)
    print(f"Created {target}")
    return 0


def cmd_validate(args):
    """Validate .mcp.json against schema."""
    path = args.path or ".mcp.json"
    try:
        config = read_config(path)
    except FileNotFoundError:
        print(f"Error: {path} not found")
        return 1
    except json.JSONDecodeError as e:
        print(f"Error: invalid JSON — {e}")
        return 1

    errors = validate_config(config)
    if not errors:
        servers = list_servers(config)
        print(f"Valid .mcp.json — {len(servers)} server(s)")
        for s in servers:
            print(f"  {s['name']} ({s['transport']}) -> {s['command']}")
        return 0

    print(f"Validation errors ({len(errors)}):")
    for err in errors:
        print(f"  - {err}")
    return 1


def cmd_diff(args):
    """Diff two .mcp.json files."""
    try:
        config_a = read_config(args.file1)
        config_b = read_config(args.file2)
    except FileNotFoundError as e:
        print(f"Error: {e}")
        return 1

    label_a = Path(args.file1).name
    label_b = Path(args.file2).name
    lines = diff_configs(config_a, config_b, label_a, label_b)

    if not lines:
        print("Configs are identical.")
    else:
        print(f"Diff: {label_a} vs {label_b}")
        print("-" * 40)
        for line in lines:
            print(line)
    return 0


def cmd_merge(args):
    """Merge two configs (overlay wins)."""
    try:
        base = read_config(args.base)
        overlay = read_config(args.overlay)
    except FileNotFoundError as e:
        print(f"Error: {e}")
        return 1

    merged = merge_configs(base, overlay)

    if args.output:
        write_config(args.output, merged)
        print(f"Merged config written to {args.output}")
    else:
        print(json.dumps(merged, indent=2))
    return 0


def cmd_export(args):
    """Export config in specified format."""
    try:
        config = read_config(args.path)
    except FileNotFoundError as e:
        print(f"Error: {e}")
        return 1

    fmt = args.format or "json"

    if fmt == "json":
        print(json.dumps(config, indent=2))
    elif fmt == "yaml":
        try:
            import yaml
            print(yaml.dump(config, default_flow_style=False, sort_keys=False))
        except ImportError:
            # Minimal YAML output without pyyaml dependency
            _print_yaml(config)
    else:
        print(f"Error: unsupported format '{fmt}'")
        return 1
    return 0


def _print_yaml(obj, indent=0):
    """Minimal YAML printer without pyyaml dependency."""
    prefix = "  " * indent
    if isinstance(obj, dict):
        for key, val in obj.items():
            if isinstance(val, (dict, list)):
                print(f"{prefix}{key}:")
                _print_yaml(val, indent + 1)
            else:
                print(f"{prefix}{key}: {val}")
    elif isinstance(obj, list):
        for item in obj:
            if isinstance(item, (dict, list)):
                print(f"{prefix}-")
                _print_yaml(item, indent + 1)
            else:
                print(f"{prefix}- {item}")


def cmd_list(args):
    """List registered configs."""
    configs = list_registered()
    if not configs:
        print("No registered configs. Use 'register' to add one.")
        return 0

    print(f"Registered configs ({len(configs)}):")
    for c in configs:
        status = "" if c["exists"] == "yes" else " [MISSING]"
        print(f"  {c['name']}: {c['path']}{status}")
    return 0


def cmd_register(args):
    """Register a config in the local registry."""
    try:
        alias = register_config(args.path, args.name)
        print(f"Registered '{alias}' -> {Path(args.path).resolve()}")
        return 0
    except FileNotFoundError as e:
        print(f"Error: {e}")
        return 1


def cmd_detect(args):
    """Detect MCP configs across all AI clients."""
    project = Path(args.project) if args.project else None
    configs = detect_configs(project)

    if args.json:
        print(json.dumps([c.to_dict() for c in configs], indent=2, ensure_ascii=False))
    else:
        print_detection_report(configs)
    return 0


def cmd_sync(args):
    """Sync MCP configs across all detected AI clients."""
    if getattr(args, "dry_run", False) and args.apply:
        print("Error: --dry-run and --apply are mutually exclusive.")
        return 1

    project = Path(args.project) if args.project else None
    configs = detect_configs(project)

    if not configs:
        print("No MCP configurations found. Nothing to sync.")
        return 1

    plan = build_sync_plan(configs)

    if args.json:
        out = {
            "merged_servers": plan.merged_servers,
            "changes": plan.changes_per_client,
            "conflicts": plan.conflicts,
            "total_changes": plan.total_changes,
            "timestamp": plan.timestamp,
        }
        print(json.dumps(out, indent=2, ensure_ascii=False))
    else:
        dry_run = not args.apply
        report = apply_sync(plan, dry_run=dry_run)
        print(report)
    return 0


def main(argv=None):
    """Main CLI entry point."""
    parser = argparse.ArgumentParser(
        prog="mcp-config-sync",
        description="Cross-platform MCP config management",
    )
    parser.add_argument("--version", action="version", version="mcp-config-sync 0.1.0")
    sub = parser.add_subparsers(dest="command", help="Available commands")

    # init
    p_init = sub.add_parser("init", help="Create .mcp.json template")
    p_init.add_argument("path", nargs="?", help="Target path (default: ./.mcp.json)")
    p_init.add_argument("--force", action="store_true", help="Overwrite existing")

    # validate
    p_val = sub.add_parser("validate", help="Validate .mcp.json")
    p_val.add_argument("path", nargs="?", help="Path to .mcp.json")

    # diff
    p_diff = sub.add_parser("diff", help="Diff two .mcp.json files")
    p_diff.add_argument("file1", help="First config file")
    p_diff.add_argument("file2", help="Second config file")

    # merge
    p_merge = sub.add_parser("merge", help="Merge two configs")
    p_merge.add_argument("base", help="Base config")
    p_merge.add_argument("overlay", help="Overlay config (wins on conflicts)")
    p_merge.add_argument("-o", "--output", help="Output file (default: stdout)")

    # export
    p_export = sub.add_parser("export", help="Export config")
    p_export.add_argument("path", help="Config file to export")
    p_export.add_argument("--format", choices=["json", "yaml"], default="json")

    # list
    sub.add_parser("list", help="List registered configs")

    # register
    p_reg = sub.add_parser("register", help="Register config in local registry")
    p_reg.add_argument("path", help="Path to .mcp.json")
    p_reg.add_argument("--name", help="Alias for the config")

    # detect (new in R010)
    p_detect = sub.add_parser("detect", help="Detect MCP configs across AI clients")
    p_detect.add_argument("--project", "-p", help="Project directory to scan")
    p_detect.add_argument("--json", action="store_true", help="Output as JSON")

    # sync (new in R010)
    p_sync = sub.add_parser("sync", help="Sync MCP configs across AI clients")
    p_sync.add_argument("--apply", action="store_true", help="Apply changes (default: dry-run)")
    p_sync.add_argument("--dry-run", action="store_true", dest="dry_run", help="Preview changes without writing (default behavior)")
    p_sync.add_argument("--project", "-p", help="Project directory to scan")
    p_sync.add_argument("--json", action="store_true", help="Output sync plan as JSON")

    args = parser.parse_args(argv)

    if not args.command:
        parser.print_help()
        return 1

    handlers = {
        "init": cmd_init,
        "validate": cmd_validate,
        "diff": cmd_diff,
        "merge": cmd_merge,
        "export": cmd_export,
        "list": cmd_list,
        "register": cmd_register,
        "detect": cmd_detect,
        "sync": cmd_sync,
    }
    return handlers[args.command](args)


if __name__ == "__main__":
    sys.exit(main())
