#!/usr/bin/env python3
"""
setup-reticulum-config.py
Automatically sets up a working Reticulum config with backbone TCP connection.

Usage:
    python3 setup-reticulum-config.py

Works on Linux, macOS, and Windows.
"""

import os
import sys
import shutil
import datetime

# ── Config paths by platform ──────────────────────────────────────────────────

if sys.platform == "win32":
    CONFIG_DIR  = os.path.join(os.environ.get("APPDATA", ""), "Reticulum")
else:
    CONFIG_DIR  = os.path.join(os.path.expanduser("~"), ".reticulum")

CONFIG_FILE = os.path.join(CONFIG_DIR, "config")

# ── Config template ───────────────────────────────────────────────────────────

CONFIG_TEMPLATE = """\
# Reticulum Configuration
# Generated by setup-reticulum-config.py on {date}
# Full documentation: https://reticulum.network/manual/

[reticulum]
  enable_transport = False
  share_instance = Yes
  shared_instance_port = 37428
  instance_control_port = 37429
  panic_on_interface_error = No

[logging]
  loglevel = 4

[interfaces]

  # AutoInterface — automatically finds other Reticulum nodes on your
  # local network via multicast. Works great for LAN setups and will
  # find rnsd or NomadNet running on any device on the same network.
  [[AutoInterface]]
    type = AutoInterface
    enabled = yes

  # TCP Backbone — connects you to the global Reticulum mesh over
  # the regular internet. You can add more than one of these.
{backbone_block}
"""

BACKBONE_BLOCK_TEMPLATE = """\
  [[{name}]]
    type = TCPClientInterface
    enabled = yes
    target_host = {host}
    target_port = {port}
"""

BANNER = """
╔══════════════════════════════════════════════════════╗
║       Reticulum Config Setup — Node Star             ║
║       https://nodestar.net                           ║
╚══════════════════════════════════════════════════════╝
"""

RMAP_NOTE = """
To find backbone nodes, visit:
  → https://rmap.world          (interactive map, click a node → Copy Configuration)
  → https://directory.rns.recipes  (curated list with copy-paste configs)

You'll need a host address and port number. They look like:
  Host: reticulum.somenode.net   Port: 4242

Enter as many as you like. Press Enter with a blank host when done.
"""

# ── Helpers ───────────────────────────────────────────────────────────────────

def prompt(msg, default=None):
    if default:
        val = input(f"{msg} [{default}]: ").strip()
        return val if val else default
    return input(f"{msg}: ").strip()

def yn(msg, default="y"):
    choices = "Y/n" if default == "y" else "y/N"
    val = input(f"{msg} [{choices}]: ").strip().lower()
    if not val:
        return default == "y"
    return val.startswith("y")

# ── Main ──────────────────────────────────────────────────────────────────────

def main():
    print(BANNER)

    # ── Check for existing config ──────────────────────────────────────────────
    if os.path.exists(CONFIG_FILE):
        print(f"Found existing config at:\n  {CONFIG_FILE}\n")
        if not yn("A config already exists. Back it up and replace it?", default="n"):
            print("\nNo changes made. Exiting.")
            sys.exit(0)

        # Back up the existing config
        ts      = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
        backup  = CONFIG_FILE + f".backup_{ts}"
        shutil.copy2(CONFIG_FILE, backup)
        print(f"\n✓ Backed up existing config to:\n  {backup}\n")

    # ── Collect backbone nodes ─────────────────────────────────────────────────
    print(RMAP_NOTE)
    backbone_entries = []
    entry_num = 1

    while True:
        host = prompt(f"Backbone node {entry_num} — host (or press Enter to finish)").strip()
        if not host:
            if not backbone_entries and entry_num == 1:
                print("\nNo backbone node entered. Your config will use AutoInterface only.")
                print("You can add backbone nodes later by editing the config file manually.\n")
            break

        port = prompt(f"  Port for {host}", default="4242").strip()
        try:
            port = int(port)
        except ValueError:
            print("  Invalid port number — skipping this entry.")
            continue

        name = prompt(f"  Nickname for this node", default=f"Backbone Node {entry_num}").strip()

        backbone_entries.append(BACKBONE_BLOCK_TEMPLATE.format(
            name=name,
            host=host,
            port=port,
        ))
        print(f"  ✓ Added {name} ({host}:{port})\n")
        entry_num += 1

    # ── Write config ───────────────────────────────────────────────────────────
    os.makedirs(CONFIG_DIR, exist_ok=True)

    backbone_block = "\n".join(backbone_entries) if backbone_entries else \
        "  # Add a TCP backbone node here — see https://rmap.world\n" \
        "  # [[My Backbone Node]]\n" \
        "  #   type = TCPClientInterface\n" \
        "  #   enabled = yes\n" \
        "  #   target_host = some.backbone.node\n" \
        "  #   target_port = 4242\n"

    config_content = CONFIG_TEMPLATE.format(
        date=datetime.datetime.now().strftime("%Y-%m-%d %H:%M"),
        backbone_block=backbone_block,
    )

    with open(CONFIG_FILE, "w") as f:
        f.write(config_content)

    print(f"✓ Config written to:\n  {CONFIG_FILE}\n")

    # ── Summary ────────────────────────────────────────────────────────────────
    print("═" * 54)
    print("  Setup complete!")
    print("═" * 54)
    print(f"\n  Config location:  {CONFIG_FILE}")
    print( "  AutoInterface:    enabled (local network discovery)")
    if backbone_entries:
        print(f"  Backbone nodes:   {len(backbone_entries)} configured")
    else:
        print( "  Backbone nodes:   none (add later via config file)")
    print()
    print("  Next steps:")
    print("  1. Restart Nomad NetBrowser (or rnsd if running separately)")
    print("  2. Visit a starter node to confirm you're connected:")
    print("     → 9a5548134799cfb6e9f60decc8708bc1  (Node Star)")
    print()
    print("  To add more backbone nodes later, edit the config file")
    print("  or visit https://rmap.world for a copy-paste snippet.")
    print()

if __name__ == "__main__":
    main()
