"""
Command line interface for Mallo framework.
"""

import argparse
import os
import re
import subprocess
import sys
import platform
from pathlib import Path
from textwrap import dedent


def _is_valid_project_name(name: str) -> bool:
    return bool(re.match(r"^[A-Za-z0-9._-]+$", name or ""))


def _write_file(path: Path, content: str, force: bool) -> None:
    if path.exists() and not force:
        raise FileExistsError(f"File already exists: {path}")
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(content, encoding="utf-8")


def create_project(name: str, template_folder: str = "templates", static_folder: str = "static", force: bool = False) -> int:
    """Create a new Mallo project scaffold safely."""
    if not name or not name.strip():
        print("Error: project name cannot be empty.")
        return 1
    if not _is_valid_project_name(name):
        print("Error: project name may only contain letters, numbers, '.', '_' or '-'.")
        return 1
    if not template_folder.strip() or not static_folder.strip():
        print("Error: template/static folder names cannot be empty.")
        return 1

    project_dir = Path(name).resolve()
    if project_dir.exists() and not project_dir.is_dir():
        print(f"Error: path exists and is not a directory: {project_dir}")
        return 1
    if project_dir.exists() and not force and any(project_dir.iterdir()):
        print(f"Error: directory is not empty: {project_dir}")
        print("Use --force to overwrite scaffold files.")
        return 1

    print(f"Creating new Mallo project: {name}")
    project_dir.mkdir(parents=True, exist_ok=True)

    app_content = dedent(
        f"""\
        \"\"\"
        Mallo application
        \"\"\"

        from mallo import Mallo

        app = Mallo(__name__, template_folder='{template_folder}', static_folder='{static_folder}')

        @app.get('/')
        def home(request):
            return app.render_template('index.html')

        @app.get('/hello/<name>')
        def hello(request, name):
            return f'<h1>Hello, {{name}}!</h1>'

        @app.get('/api/data')
        def api_data(request):
            return {{'message': 'Hello from Mallo!', 'status': 'success'}}

        if __name__ == '__main__':
            app.run(debug=True, use_reloader=True)
        """
    )

    index_content = dedent(
        """\
        <!DOCTYPE html>
        <html lang="en">
        <head>
          <meta charset="UTF-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1" />
          <title>Mallo App</title>
          <link rel="stylesheet" href="/static/style.css" />
        </head>
        <body>
          <main class="wrap">
            <h1>Mallo is running</h1>
            <p>Your project scaffold is ready.</p>
            <p>Try <a href="/hello/World">/hello/World</a> and <a href="/api/data">/api/data</a>.</p>
          </main>
        </body>
        </html>
        """
    )

    css_content = dedent(
        """\
        :root {
          --bg: #f6f2ea;
          --surface: #fffdf8;
          --ink: #1a1510;
          --muted: #6b5f52;
          --line: #e8ddcd;
          --accent: #b6551d;
        }

        body {
          margin: 0;
          font-family: "Segoe UI", Tahoma, sans-serif;
          color: var(--ink);
          background: var(--bg);
        }

        .wrap {
          max-width: 700px;
          margin: 40px auto;
          padding: 20px;
          border: 1px solid var(--line);
          border-radius: 12px;
          background: var(--surface);
        }

        h1 { margin-top: 0; }
        p { color: var(--muted); }
        a { color: var(--accent); }
        """
    )

    readme_content = dedent(
        f"""\
        # {name}

        Generated by Mallo CLI.

        ## Run

        ```bash
        python app.py
        ```
        """
    )

    gitignore_content = dedent(
        """\
        __pycache__/
        *.pyc
        .venv/
        """
    )

    try:
        _write_file(project_dir / "app.py", app_content, force)
        _write_file(project_dir / template_folder / "index.html", index_content, force)
        _write_file(project_dir / static_folder / "style.css", css_content, force)
        _write_file(project_dir / "README.md", readme_content, force)
        _write_file(project_dir / ".gitignore", gitignore_content, force)
    except Exception as exc:
        print(f"Error: failed to create project files: {exc}")
        return 1

    print(f"Project '{name}' created successfully.")
    print(f"cd {name}")
    print("python app.py")
    return 0


def run_server(app_path: str, host: str, port: int, debug: bool, reload: bool) -> int:
    """Run a Mallo application via gunicorn."""
    if platform.system().lower().startswith("win"):
        print("Gunicorn is not supported on Windows. Use 'python app.py' or run on Linux/WSL.")
        return 1

    env = os.environ.copy()
    env["MALLO_DEBUG"] = "1" if debug else "0"
    env["MALLO_LIVE_RELOAD"] = "1" if debug else "0"

    cmd = [
        "gunicorn",
        app_path,
        "--bind",
        f"{host}:{port}",
    ]
    if reload:
        cmd.append("--reload")

    try:
        result = subprocess.run(cmd, env=env, check=False)
        return result.returncode
    except FileNotFoundError:
        print("Error: gunicorn is not installed. Install it with: pip install gunicorn")
        return 1


def cli() -> None:
    """Main CLI entry point."""
    parser = argparse.ArgumentParser(description="Mallo web framework CLI")
    subparsers = parser.add_subparsers(dest="command", help="Commands")

    create_parser = subparsers.add_parser("create", help="Create a new project")
    create_parser.add_argument("name", help="Project name")
    create_parser.add_argument("--template-folder", default="templates", help="Template folder name")
    create_parser.add_argument("--static-folder", default="static", help="Static folder name")
    create_parser.add_argument("--force", action="store_true", help="Overwrite scaffold files if they exist")

    run_parser = subparsers.add_parser("run", help="Run the application")
    run_parser.add_argument("app", nargs="?", default="app:app", help="WSGI app path, e.g. app:app")
    run_parser.add_argument("--host", default="localhost", help="Host to bind to")
    run_parser.add_argument("--port", type=int, default=8000, help="Port to listen on")
    run_parser.add_argument("--debug", action="store_true", default=True, help="Enable debug mode")
    run_parser.add_argument("--no-debug", action="store_true", help="Disable debug mode")
    run_parser.add_argument("--no-reload", action="store_true", help="Disable hot reload")

    args = parser.parse_args()

    if args.command == "create":
        code = create_project(
            args.name,
            template_folder=args.template_folder,
            static_folder=args.static_folder,
            force=args.force,
        )
        sys.exit(code)
    if args.command == "run":
        debug = args.debug and not args.no_debug
        reload = not args.no_reload and debug
        code = run_server(args.app, args.host, args.port, debug, reload)
        sys.exit(code)

    parser.print_help()


if __name__ == "__main__":
    cli()
