"""
Template strings for scaffolding new djust projects.

All templates use ``%(variable)s`` substitution to avoid conflicts with
Django template syntax (``{%%}``, ``{{ }}``).
"""

# ---------------------------------------------------------------------------
# manage.py
# ---------------------------------------------------------------------------

MANAGE_PY = """\
#!/usr/bin/env python
\"\"\"Django's command-line utility for administrative tasks.\"\"\"
import os
import sys


def main():
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "%(app_name)s.settings")
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)


if __name__ == "__main__":
    main()
"""

# ---------------------------------------------------------------------------
# __init__.py (app package)
# ---------------------------------------------------------------------------

INIT_PY = ""

# ---------------------------------------------------------------------------
# apps.py
# ---------------------------------------------------------------------------

APPS_PY = """\
from django.apps import AppConfig


class %(app_class)sConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "%(app_name)s"
"""

# ---------------------------------------------------------------------------
# settings.py
# ---------------------------------------------------------------------------

SETTINGS_PY = """\
\"\"\"
Django settings for %(app_name)s project.
Generated by ``python -m djust new``.
\"\"\"

import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

SECRET_KEY = os.environ.get(
    "SECRET_KEY",
    "django-insecure-%(secret_key)s",
)  # noqa: S105

DEBUG = True

ALLOWED_HOSTS = ["*"]

INSTALLED_APPS = [
    "daphne",
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "djust",
    "%(app_name)s",
]

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "whitenoise.middleware.WhiteNoiseMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

ROOT_URLCONF = "%(app_name)s.urls"

TEMPLATES = [
    {
        "BACKEND": "djust.template_backend.DjustTemplateBackend",
        "DIRS": [BASE_DIR / "templates"],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

ASGI_APPLICATION = "%(app_name)s.asgi.application"

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels.layers.InMemoryChannelLayer",
    },
}

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "db.sqlite3",
    }
}

LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_TZ = True

STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

LIVEVIEW_ALLOWED_MODULES = [
    "%(app_name)s.views",
]
%(extra_settings)s"""

# ---------------------------------------------------------------------------
# asgi.py
# ---------------------------------------------------------------------------

ASGI_PY = """\
\"\"\"ASGI config for %(app_name)s project.\"\"\"

import os
import django

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "%(app_name)s.settings")
django.setup()

from djust.routing import live_session  # noqa: E402

application = live_session()
"""

# ---------------------------------------------------------------------------
# wsgi.py
# ---------------------------------------------------------------------------

WSGI_PY = """\
\"\"\"WSGI config for %(app_name)s project.\"\"\"

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "%(app_name)s.settings")

application = get_wsgi_application()
"""

# ---------------------------------------------------------------------------
# urls.py
# ---------------------------------------------------------------------------

URLS_PY = """\
\"\"\"URL configuration for %(app_name)s project.\"\"\"

from django.contrib import admin
from django.urls import path

from .views import %(view_class)s

urlpatterns = [
    path("admin/", admin.site.urls),
    path("", %(view_class)s.as_view(), name="index"),
]
%(extra_urls)s"""

# ---------------------------------------------------------------------------
# views.py — base (no features)
# ---------------------------------------------------------------------------

VIEWS_PY_BASE = """\
\"\"\"LiveView for %(app_name)s.\"\"\"

from djust import LiveView
from djust.decorators import event_handler
%(extra_imports)s

%(extra_data)s
class %(view_class)s(%(view_bases)s):
    template_name = "%(app_name)s/index.html"

    def mount(self, request, **kwargs):
        self.items = [
            {"id": 1, "name": "First item", "done": False},
            {"id": 2, "name": "Second item", "done": False},
            {"id": 3, "name": "Third item", "done": True},
        ]
        self.search_query = ""
        self._next_id = 4
%(extra_mount)s
    def _compute(self):
        \"\"\"Recompute filtered items.\"\"\"
        if self.search_query:
            q = self.search_query.lower()
            self.filtered_items = [
                i for i in self.items if q in i["name"].lower()
            ]
        else:
            self.filtered_items = self.items[:]
        self.total_count = len(self.items)
        self.done_count = sum(1 for i in self.items if i["done"])

    @event_handler()
    def search(self, value: str = "", **kwargs):
        \"\"\"Filter items by search query.\"\"\"
        self.search_query = value
        self._compute()

    @event_handler()
    def add_item(self, name: str = "", **kwargs):
        \"\"\"Add a new item.\"\"\"
        if name.strip():
            self.items.append({
                "id": self._next_id,
                "name": name.strip(),
                "done": False,
            })
            self._next_id += 1
            self._compute()

    @event_handler()
    def toggle_item(self, item_id: int = 0, **kwargs):
        \"\"\"Toggle item done state.\"\"\"
        for item in self.items:
            if item["id"] == item_id:
                item["done"] = not item["done"]
                break
        self._compute()

    @event_handler()
    def delete_item(self, item_id: int = 0, **kwargs):
        \"\"\"Delete an item.\"\"\"
        self.items = [i for i in self.items if i["id"] != item_id]
        self._compute()

    def get_context_data(self, **kwargs):
        self._compute()
        return {
            "items": self.filtered_items,
            "search_query": self.search_query,
            "total_count": self.total_count,
            "done_count": self.done_count,
%(extra_context)s        }
%(extra_methods)s"""

# ---------------------------------------------------------------------------
# base.html
# ---------------------------------------------------------------------------

BASE_HTML = """\
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{%% block title %%}%(display_name)s{%% endblock %%}</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        surface: { 700: '#2a2a3e', 800: '#1e1e2e', 900: '#11111b', 950: '#0a0a14' }
                    }
                }
            }
        }
    </script>
    <style>
        body { background: #0a0a14; }
        .glass { background: rgba(30,30,46,0.6); backdrop-filter: blur(16px); border: 1px solid rgba(255,255,255,0.06); }
    </style>
    {%% load static %%}
</head>
<body class="text-gray-200 antialiased min-h-screen">
    <nav class="border-b border-white/5 bg-surface-950">
        <div class="max-w-7xl mx-auto px-4 py-3 flex items-center justify-between">
            <span class="text-white font-bold text-lg">%(display_name)s</span>
%(nav_extra)s\
        </div>
    </nav>
    <main class="max-w-7xl mx-auto px-4 py-8">
        {%% block content %%}{%% endblock %%}
    </main>
    <script src="{%% static 'djust/client.js' %%}" defer></script>
</body>
</html>
"""

# ---------------------------------------------------------------------------
# index.html — list view template
# ---------------------------------------------------------------------------

INDEX_HTML = """\
{%% extends "%(app_name)s/base.html" %%}

{%% block content %%}
{%% csrf_token %%}
<div data-djust-root data-djust-view="%(app_name)s.views.%(view_class)s">

    <!-- Stats bar -->
    <div class="flex items-center gap-4 mb-6">
        <span class="text-sm text-gray-400">{{ total_count }} total</span>
        <span class="text-sm text-emerald-400">{{ done_count }} done</span>
    </div>

    <!-- Search + Add -->
    <div class="flex gap-3 mb-6">
        <input type="text"
               dj-input="search"
               name="value"
               value="{{ search_query }}"
               placeholder="Search items..."
               class="flex-1 px-4 py-2 rounded-lg bg-surface-800 border border-white/10 text-gray-200 placeholder-gray-500 focus:outline-none focus:border-indigo-500">
        <form dj-submit="add_item" class="flex gap-2">
            <input type="text"
                   name="name"
                   placeholder="New item..."
                   class="px-4 py-2 rounded-lg bg-surface-800 border border-white/10 text-gray-200 placeholder-gray-500 focus:outline-none focus:border-indigo-500">
            <button type="submit"
                    class="px-4 py-2 rounded-lg bg-indigo-600 text-white hover:bg-indigo-500 transition"
                    dj-loading.class="opacity-50"
                    dj-loading.disable>
                Add
            </button>
        </form>
    </div>

    <!-- Item list -->
    <div class="space-y-2">
        {%% for item in items %%}
        <div class="glass rounded-lg px-4 py-3 flex items-center justify-between group">
            <div class="flex items-center gap-3">
                <button dj-click="toggle_item"
                        data-item_id:int="{{ item.id }}"
                        class="w-5 h-5 rounded border {%% if item.done %%}bg-emerald-500 border-emerald-500{%% else %%}border-gray-500{%% endif %%} flex items-center justify-center transition">
                    {%% if item.done %%}
                    <svg class="w-3 h-3 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"/>
                    </svg>
                    {%% endif %%}
                </button>
                <span class="{%% if item.done %%}line-through text-gray-500{%% else %%}text-gray-200{%% endif %%}">
                    {{ item.name }}
                </span>
            </div>
            <button dj-click="delete_item"
                    data-item_id:int="{{ item.id }}"
                    dj-confirm="Delete this item?"
                    class="text-red-400 opacity-0 group-hover:opacity-100 hover:text-red-300 transition">
                <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
                </svg>
            </button>
        </div>
        {%% empty %%}
        <div class="text-center text-gray-500 py-12">
            {%% if search_query %%}
                No items match "{{ search_query }}"
            {%% else %%}
                No items yet. Add one above!
            {%% endif %%}
        </div>
        {%% endfor %%}
    </div>

%(template_extra)s\
</div>
{%% endblock %%}
"""

# ---------------------------------------------------------------------------
# Makefile
# ---------------------------------------------------------------------------

MAKEFILE = """\
.PHONY: dev test migrate check install

dev:
\tdaphne -b 127.0.0.1 -p 8000 %(app_name)s.asgi:application

test:
\tpython manage.py test

migrate:
\tpython manage.py migrate

check:
\tpython manage.py djust_check

install:
\tuv pip install -r requirements.txt

collectstatic:
\tpython manage.py collectstatic --noinput
"""

# ---------------------------------------------------------------------------
# requirements.txt
# ---------------------------------------------------------------------------

REQUIREMENTS_TXT = """\
django>=5.1
djust>=0.3.0
channels>=4.0
daphne>=4.0
whitenoise>=6.6
"""

# ---------------------------------------------------------------------------
# .gitignore
# ---------------------------------------------------------------------------

GITIGNORE = """\
__pycache__/
*.py[cod]
*.so
.venv/
venv/
db.sqlite3
db.sqlite3-journal
staticfiles/
*.egg-info/
dist/
build/
.eggs/
.env
*.log
.DS_Store
"""

# ---------------------------------------------------------------------------
# Feature: --with-auth — login template
# ---------------------------------------------------------------------------

LOGIN_HTML = """\
{%% extends "%(app_name)s/base.html" %%}

{%% block title %%}Login - %(display_name)s{%% endblock %%}

{%% block content %%}
<div class="max-w-md mx-auto mt-16">
    <div class="glass rounded-xl p-8">
        <h2 class="text-2xl font-bold text-white mb-6 text-center">Sign In</h2>
        <form method="post" action="{%% url 'login' %%}">
            {%% csrf_token %%}
            <input type="hidden" name="next" value="{{ next }}">
            {%% if form.errors %%}
            <div class="mb-4 p-3 rounded-lg bg-red-500/10 border border-red-500/30 text-red-400 text-sm">
                Invalid username or password.
            </div>
            {%% endif %%}
            <div class="mb-4">
                <label class="block text-sm text-gray-400 mb-1">Username</label>
                <input type="text" name="username" autofocus
                       class="w-full px-4 py-2 rounded-lg bg-surface-800 border border-white/10 text-gray-200 focus:outline-none focus:border-indigo-500">
            </div>
            <div class="mb-6">
                <label class="block text-sm text-gray-400 mb-1">Password</label>
                <input type="password" name="password"
                       class="w-full px-4 py-2 rounded-lg bg-surface-800 border border-white/10 text-gray-200 focus:outline-none focus:border-indigo-500">
            </div>
            <button type="submit"
                    class="w-full py-2 rounded-lg bg-indigo-600 text-white hover:bg-indigo-500 transition font-medium">
                Sign In
            </button>
        </form>
    </div>
</div>
{%% endblock %%}
"""

# ---------------------------------------------------------------------------
# Feature: --with-auth — extra settings
# ---------------------------------------------------------------------------

AUTH_SETTINGS_EXTRA = """
LOGIN_URL = "/login/"
LOGIN_REDIRECT_URL = "/"
LOGOUT_REDIRECT_URL = "/"
"""

# ---------------------------------------------------------------------------
# Feature: --with-auth — extra urls
# ---------------------------------------------------------------------------

AUTH_URLS_EXTRA = """
# Auth URLs
from django.contrib.auth import views as auth_views

urlpatterns += [
    path(
        "login/",
        auth_views.LoginView.as_view(
            template_name="%(app_name)s/login.html",
        ),
        name="login",
    ),
    path("logout/", auth_views.LogoutView.as_view(), name="logout"),
]
"""

# ---------------------------------------------------------------------------
# Feature: --with-auth — nav extra (username + logout link)
# ---------------------------------------------------------------------------

AUTH_NAV_EXTRA = """\
            <div class="flex items-center gap-3">
                {%% if user.is_authenticated %%}
                <span class="text-sm text-gray-400">{{ user.username }}</span>
                <a href="{%% url 'logout' %%}" class="text-sm text-indigo-400 hover:text-indigo-300">Logout</a>
                {%% else %%}
                <a href="{%% url 'login' %%}" class="text-sm text-indigo-400 hover:text-indigo-300">Login</a>
                {%% endif %%}
            </div>
"""

# ---------------------------------------------------------------------------
# Feature: --with-db — models.py
# ---------------------------------------------------------------------------

MODELS_PY = """\
\"\"\"Models for %(app_name)s.\"\"\"

from django.db import models


class Item(models.Model):
    name = models.CharField(max_length=200)
    done = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return self.name
"""

# ---------------------------------------------------------------------------
# Feature: --with-db — admin.py
# ---------------------------------------------------------------------------

ADMIN_PY = """\
from django.contrib import admin

from .models import Item


@admin.register(Item)
class ItemAdmin(admin.ModelAdmin):
    list_display = ["name", "done", "created_at"]
    list_filter = ["done"]
    search_fields = ["name"]
"""

# ---------------------------------------------------------------------------
# Feature: --with-db — views.py overrides (DB-backed items)
# ---------------------------------------------------------------------------

DB_VIEWS_EXTRA_IMPORTS = """\
from .models import Item
"""

DB_VIEWS_MOUNT_OVERRIDE = """\
        self.search_query = ""
"""

DB_VIEWS_COMPUTE_OVERRIDE = """\
    def _compute(self):
        \"\"\"Recompute filtered items from database.\"\"\"
        qs = Item.objects.all()
        if self.search_query:
            qs = qs.filter(name__icontains=self.search_query)
        self.items = [
            {"id": i.pk, "name": i.name, "done": i.done}
            for i in qs
        ]
        self.total_count = Item.objects.count()
        self.done_count = Item.objects.filter(done=True).count()
"""

DB_VIEWS_ADD_ITEM_OVERRIDE = """\
    @event_handler()
    def add_item(self, name: str = "", **kwargs):
        \"\"\"Add a new item to the database.\"\"\"
        if name.strip():
            Item.objects.create(name=name.strip())
            self._compute()
"""

DB_VIEWS_TOGGLE_OVERRIDE = """\
    @event_handler()
    def toggle_item(self, item_id: int = 0, **kwargs):
        \"\"\"Toggle item done state in database.\"\"\"
        try:
            item = Item.objects.get(pk=item_id)
            item.done = not item.done
            item.save(update_fields=["done"])
        except Item.DoesNotExist:
            pass
        self._compute()
"""

DB_VIEWS_DELETE_OVERRIDE = """\
    @event_handler()
    def delete_item(self, item_id: int = 0, **kwargs):
        \"\"\"Delete an item from the database.\"\"\"
        Item.objects.filter(pk=item_id).delete()
        self._compute()
"""

# ---------------------------------------------------------------------------
# Feature: --with-presence — template partial
# ---------------------------------------------------------------------------

PRESENCE_TEMPLATE_EXTRA = """\

    <!-- Presence indicators -->
    <div class="mt-8 border-t border-white/5 pt-4">
        <div class="flex items-center gap-2 text-sm text-gray-400">
            <span class="w-2 h-2 rounded-full bg-emerald-400"></span>
            {{ presence_count }} user{{ presence_count|pluralize }} online
        </div>
        <div class="flex gap-1 mt-2">
            {%% for user in presence_list %%}
            <div class="w-8 h-8 rounded-full bg-indigo-600 flex items-center justify-center text-xs text-white"
                 title="{{ user.username }}">
                {{ user.username|first|upper }}
            </div>
            {%% endfor %%}
        </div>
    </div>
"""

# ---------------------------------------------------------------------------
# Feature: --with-streaming — template partial
# ---------------------------------------------------------------------------

STREAMING_TEMPLATE_EXTRA = """\

    <!-- Stream output -->
    <div class="mt-8 border-t border-white/5 pt-4">
        <h3 class="text-sm font-medium text-gray-400 mb-2">Live Feed</h3>
        <div dj-stream="feed" dj-stream-mode="append"
             class="glass rounded-lg p-4 max-h-64 overflow-y-auto space-y-1 text-sm font-mono">
            {%% for entry in streams.feed %%}
            <div class="text-gray-300">{{ entry }}</div>
            {%% endfor %%}
        </div>
    </div>
"""

# ---------------------------------------------------------------------------
# Feature: --from-schema — views.py for schema-generated app
# ---------------------------------------------------------------------------

SCHEMA_VIEWS_PY = """\
\"\"\"LiveViews for %(app_name)s — generated from schema.\"\"\"

from djust import LiveView
from djust.decorators import event_handler
%(schema_model_imports)s


%(schema_view_classes)s"""

SCHEMA_VIEW_CLASS = """\
class %(view_class)s(LiveView):
    template_name = "%(app_name)s/%(template_name)s"

    def mount(self, request, **kwargs):
%(mount_body)s
        self._compute()

    def _compute(self):
        \"\"\"Recompute from database.\"\"\"
%(compute_body)s

%(handler_methods)s
    def get_context_data(self, **kwargs):
        self._compute()
        return {
%(context_body)s        }
"""

SCHEMA_MODELS_PY = """\
\"\"\"Models for %(app_name)s — generated from schema.\"\"\"

from django.db import models

%(model_classes)s"""

SCHEMA_MODEL_CLASS = """\

class %(model_name)s(models.Model):
%(field_definitions)s
    class Meta:
        ordering = ["-pk"]

    def __str__(self):
        return %(str_field)s
"""

SCHEMA_ADMIN_PY = """\
from django.contrib import admin

%(admin_imports)s

%(admin_registrations)s"""

SCHEMA_LIST_HTML = """\
{%% extends "%(app_name)s/base.html" %%}

{%% block title %%}%(model_display)s - %(display_name)s{%% endblock %%}

{%% block content %%}
{%% csrf_token %%}
<div data-djust-root data-djust-view="%(app_name)s.views.%(view_class)s">

    <h1 class="text-2xl font-bold text-white mb-6">%(model_display)s</h1>

    <!-- Search -->
    <div class="mb-6">
        <input type="text"
               dj-input="search"
               name="value"
               value="{{ search_query }}"
               placeholder="Search %(model_display_lower)s..."
               class="w-full px-4 py-2 rounded-lg bg-surface-800 border border-white/10 text-gray-200 placeholder-gray-500 focus:outline-none focus:border-indigo-500">
    </div>

    <!-- Add form -->
    <form dj-submit="create" class="glass rounded-lg p-4 mb-6 grid grid-cols-1 sm:grid-cols-2 gap-3">
%(form_fields_html)s\
        <div class="sm:col-span-2">
            <button type="submit"
                    class="px-4 py-2 rounded-lg bg-indigo-600 text-white hover:bg-indigo-500 transition"
                    dj-loading.class="opacity-50" dj-loading.disable>
                Add %(model_display_singular)s
            </button>
        </div>
    </form>

    <!-- List -->
    <div class="space-y-2">
        {%% for item in items %%}
        <div class="glass rounded-lg px-4 py-3 flex items-center justify-between group">
            <div class="flex items-center gap-4">
%(list_item_fields)s\
            </div>
            <button dj-click="delete"
                    data-item_id:int="{{ item.id }}"
                    dj-confirm="Delete this %(model_display_singular_lower)s?"
                    class="text-red-400 opacity-0 group-hover:opacity-100 hover:text-red-300 transition text-sm">
                Delete
            </button>
        </div>
        {%% empty %%}
        <div class="text-center text-gray-500 py-12">No %(model_display_lower)s yet.</div>
        {%% endfor %%}
    </div>

</div>
{%% endblock %%}
"""
