import os
import sys
import json
import shutil
import argparse
from pathlib import Path
from flask import Flask, jsonify, request
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from rich.console import Console
from rich.panel import Panel

console = Console()

# -----------------------------
# FILE WATCHER
# -----------------------------

class RoPyHandler(FileSystemEventHandler):
    def on_modified(self, event):
        path = Path(str(event.src_path))
        if not event.is_directory and path.suffix in [".lua", ".luau"]:
            console.print(f"[bold green]✓[/bold green] Changed: [cyan]{path.name}[/cyan]")

# -----------------------------
# DIRECTORY SCANNER
# -----------------------------

def scan_directory(current_path):
    structure = {}
    if not os.path.exists(current_path):
        return structure

    for item in os.listdir(current_path):
        if item.startswith("."):
            continue

        full_path = os.path.join(current_path, item)

        if os.path.isdir(full_path):
            structure[item] = scan_directory(full_path)
        else:
            structure[item] = {"$path": full_path}

    return structure

# -----------------------------
# PROJECT TREE BUILDER
# -----------------------------

def build_tree_from_mapping(mapping):
    result = {}

    for key, value in mapping.items():
        if key.startswith("$"):
            continue

        if isinstance(value, dict):
            if "$path" in value:
                result[key] = scan_directory(value["$path"])
            else:
                result[key] = build_tree_from_mapping(value)

    return result

# -----------------------------
# INIT COMMAND
# -----------------------------

def init_project():
    if os.path.exists("default.project.json"):
        console.print("[yellow]Project already initialized[/yellow]")
        return

    config = {
        "name": "RoPyProject",
        "tree": {
            "$className": "DataModel",
            "ReplicatedStorage": {
                "Shared": {"$path": "src/shared"}
            },
            "ServerScriptService": {
                "Server": {"$path": "src/server"}
            },
            "StarterPlayer": {
                "StarterPlayerScripts": {
                    "Client": {"$path": "src/client"}
                }
            }
        }
    }

    os.makedirs("src/server", exist_ok=True)
    os.makedirs("src/client", exist_ok=True)
    os.makedirs("src/shared", exist_ok=True)

    with open("default.project.json", "w") as f:
        json.dump(config, f, indent=4)

    console.print("[bold green]✓ RoPy project initialized[/bold green]")

# -----------------------------
# BUILD COMMAND
# -----------------------------

def build_project():
    if not os.path.exists("src"):
        console.print("[red]No src folder found[/red]")
        return

    if os.path.exists("build"):
        shutil.rmtree("build")

    shutil.copytree("src", "build")

    console.print("[bold green]✓ Build complete[/bold green]")

# -----------------------------
# SERVER COMMAND
# -----------------------------

def serve(port=34872):

    if not os.path.exists("default.project.json"):
        console.print("[red]Missing default.project.json[/red]")
        return

    observer = Observer()
    observer.schedule(RoPyHandler(), "src", recursive=True)
    observer.start()

    app = Flask(__name__)

    @app.route("/")
    def health():
        return "RoPy Active", 200

    @app.route("/project")
    def get_project():
        with open("default.project.json", "r") as f:
            config = json.load(f)

        tree = build_tree_from_mapping(config["tree"])

        return jsonify({
            "name": config["name"],
            "tree": tree
        })

    @app.route("/fetch-file")
    def fetch_file():
        path = request.args.get("path")
        if path and os.path.exists(path):
            with open(path, "r", encoding="utf-8") as f:
                return f.read()
        return "Not Found", 404

    console.print(
        Panel(
            f"[magenta]RoPy Server[/magenta]\n"
            f"Status: [bold green]Online[/bold green]\n"
            f"Port: {port}\n"
            f"Watching: src/"
        )
    )

    app.run(port=port, debug=False, use_reloader=False)

# -----------------------------
# CLI ENTRY
# -----------------------------

def main():
    parser = argparse.ArgumentParser(prog="ropy")
    sub = parser.add_subparsers(dest="command")

    sub.add_parser("init")
    sub.add_parser("build")

    serve_parser = sub.add_parser("serve")
    serve_parser.add_argument("--port", type=int, default=34872)

    args = parser.parse_args()

    if args.command == "init":
        init_project()
    elif args.command == "build":
        build_project()
    elif args.command == "rohost":
        serve(args.port)
    else:
        parser.print_help()

if __name__ == "__main__":
    main()
