"""
SAYTHON Framework - CLI

Commands:
    saython new <project-name>       Create a new project
    saython run [--host] [--port]    Start dev server
    saython routes                   Print all routes
    saython version                  Show version
"""
import os
import sys
import argparse
from saython import __version__


# ------------------------------------------------------------------ #
#  Templates for a new project
# ------------------------------------------------------------------ #
_MAIN_PY = '''\
from saython import (
    Saython, Model, Field,
    auth_required, get_auth_router,
    Router, Response, ValidationError,
)

# ── App setup ────────────────────────────────────────────────────────────────
app = Saython(__name__)
app.configure(
    SECRET_KEY="change-this-secret-in-production",
    DATABASE_URL="app.db",   # switch to "postgresql://..." for Postgres
    DEBUG=True,
    CORS=True,
)

# ── Models ────────────────────────────────────────────────────────────────────
class Post(Model):
    title   = Field(str, required=True)
    content = Field(str, required=True)
    author  = Field(str, default="anonymous")
    views   = Field(int, default=0)

# ── Auth routes (/auth/register, /auth/login, /auth/me) ──────────────────────
app.include("/auth", get_auth_router())

# ── Post routes ───────────────────────────────────────────────────────────────
post_router = Router()

@post_router.get("/")
def list_posts(req):
    page  = int(req.query.get("page", 1))
    limit = min(int(req.query.get("limit", 20)), 100)
    return Post.paginate(page=page, limit=limit)

@post_router.get("/<id>")
def get_post(req):
    return Post.get(int(req.params["id"])).to_dict()

@post_router.post("/")
@auth_required
def create_post(req):
    data = req.json
    errors = {{}}
    if not data.get("title"):   errors["title"]   = "required"
    if not data.get("content"): errors["content"] = "required"
    if errors:
        raise ValidationError(errors)
    post = Post.create(
        title=data["title"],
        content=data["content"],
        author=data.get("author", req.user.username),
    )
    return Response(post.to_dict(), 201)

@post_router.put("/<id>")
@auth_required
def update_post(req):
    post = Post.get(int(req.params["id"]))
    data = req.json
    if "title"   in data: post.title   = data["title"]
    if "content" in data: post.content = data["content"]
    post.save()
    return post.to_dict()

@post_router.delete("/<id>")
@auth_required
def delete_post(req):
    Post.get(int(req.params["id"])).delete()
    return {{"message": "Post deleted"}}

app.include("/posts", post_router)

# ── Other endpoints ───────────────────────────────────────────────────────────
@app.get("/")
def index(req):
    return {{"message": "Welcome to {name}!", "version": "1.0.0"}}

@app.get("/dashboard")
@auth_required
def dashboard(req):
    return {{"hello": req.user.username, "posts": Post.count()}}

# ── Entry point ───────────────────────────────────────────────────────────────
if __name__ == "__main__":
    app.print_routes()
    app.run()
'''

_MODELS_PY = '''\
"""
Define your database models here.
Import them in main.py and use them in your route handlers.
"""
from saython import Model, Field


# Example: uncomment and customise

# class Product(Model):
#     name        = Field(str, required=True)
#     description = Field(str)
#     price       = Field(float, required=True, default=0.0)
#     in_stock    = Field(bool, default=True)


# class Category(Model):
#     name = Field(str, required=True, unique=True)
'''

_ENV = '''\
SECRET_KEY=change-this-in-production
DATABASE_URL=app.db
DEBUG=true
TOKEN_EXPIRY_HOURS=24
'''

_GITIGNORE = '''\
__pycache__/
*.py[cod]
*.db
*.db-shm
*.db-wal
.env
.venv/
venv/
'''

_README = '''\
# {name}

A SAYTHON-powered web app.

## Run

    pip install saython
    python main.py

## Endpoints

| Method | Path               | Description          |
|--------|--------------------|----------------------|
| POST   | /auth/register     | Register a new user  |
| POST   | /auth/login        | Login -> get token   |
| GET    | /auth/me           | Current user info    |
| GET    | /posts             | List all posts       |
| POST   | /posts             | Create a post (auth) |
| GET    | /posts/<id>        | Get a post           |
| PUT    | /posts/<id>        | Update a post (auth) |
| DELETE | /posts/<id>        | Delete a post (auth) |

## Auth

Protected endpoints require a Bearer token in the Authorization header:

    Authorization: Bearer <token from /auth/login>
'''

_REQUIREMENTS = '''\
saython
# optional extras:
# PyJWT           # faster JWT (fallback is built-in)
# bcrypt          # stronger password hashing (fallback is built-in PBKDF2)
# psycopg2-binary # PostgreSQL support
# gunicorn        # production WSGI server
'''


# ------------------------------------------------------------------ #
#  CLI commands
# ------------------------------------------------------------------ #
def cmd_new(args):
    name = args.name
    target = os.path.join(os.getcwd(), name)

    if os.path.exists(target):
        print(f"  Error: directory '{name}' already exists.")
        sys.exit(1)

    os.makedirs(target)

    def write(filename, content):
        with open(os.path.join(target, filename), "w", encoding="utf-8") as f:
            f.write(content.replace("{name}", name))

    write("main.py",           _MAIN_PY.replace("{name}", name))
    write("models.py",         _MODELS_PY)
    write(".env",               _ENV)
    write(".gitignore",         _GITIGNORE)
    write("README.md",          _README.replace("{name}", name))
    write("requirements.txt",   _REQUIREMENTS)

    print(f"\n  SAYTHON project created: {name}/\n")
    print(f"  Get started:")
    print(f"    cd {name}")
    print(f"    pip install saython")
    print(f"    python main.py\n")


def cmd_run(args):
    """Load main.py from cwd and run the app."""
    sys.path.insert(0, os.getcwd())
    try:
        import importlib
        mod = importlib.import_module("main")
        app = getattr(mod, "app", None)
        if app is None:
            print("  Error: no 'app' found in main.py")
            sys.exit(1)
        app.run(
            host=getattr(args, "host", "127.0.0.1"),
            port=int(getattr(args, "port", 8000)),
            debug=getattr(args, "debug", False),
        )
    except ImportError as e:
        print(f"  Error loading main.py: {e}")
        sys.exit(1)


def cmd_routes(args):
    sys.path.insert(0, os.getcwd())
    try:
        import importlib
        mod = importlib.import_module("main")
        app = getattr(mod, "app", None)
        if app is None:
            print("  Error: no 'app' found in main.py")
            sys.exit(1)
        app.print_routes()
    except ImportError as e:
        print(f"  Error loading main.py: {e}")
        sys.exit(1)


# ------------------------------------------------------------------ #
#  Entry point
# ------------------------------------------------------------------ #
def main():
    parser = argparse.ArgumentParser(
        prog="saython",
        description="SAYTHON — beginner-friendly Python web framework",
    )
    sub = parser.add_subparsers(dest="command")

    # new
    p_new = sub.add_parser("new", help="Create a new project")
    p_new.add_argument("name", help="Project name")

    # run
    p_run = sub.add_parser("run", help="Start the dev server")
    p_run.add_argument("--host", default="127.0.0.1")
    p_run.add_argument("--port", type=int, default=8000)
    p_run.add_argument("--debug", action="store_true")

    # routes
    sub.add_parser("routes", help="Print all registered routes")

    # version
    sub.add_parser("version", help="Show version")

    args = parser.parse_args()

    if args.command == "new":
        cmd_new(args)
    elif args.command == "run":
        cmd_run(args)
    elif args.command == "routes":
        cmd_routes(args)
    elif args.command == "version":
        print(f"SAYTHON {__version__}")
    else:
        parser.print_help()


if __name__ == "__main__":
    main()
