"""App initializer — generate complete boilerplate for a SciTeX app plugin."""

from __future__ import annotations

import logging
from pathlib import Path
from typing import Optional

from ._license import generate_license_text
from ._scaffold_agent_context import _agents_md
from ._scaffold_html import (
    _agents_json,
    _app_css,
    _apps_py,
    _index_html,
    _index_partial_html,
    _manifest_json,
    _readme_md,
    _skill_py,
    _tests_py,
    _urls_py,
    _views_py,
)
from ._scaffold_react import build_react_files

logger = logging.getLogger(__name__)


def init_app(
    target_dir: str | Path,
    name: str,
    *,
    label: str = "",
    icon: str = "fas fa-puzzle-piece",
    description: str = "",
    manifest: Optional[dict] = None,
    license_id: str = "AGPL-3.0",
    overwrite: bool = False,
    frontend_type: str = "html",
) -> list[str]:
    """Generate complete app boilerplate in target_dir.

    Parameters
    ----------
    target_dir : path
        Project directory (e.g. data/users/alice/proj/my_app/).
    name : str
        Python module name (must end with _app, e.g. 'my_awesome_app').
    label : str
        Human-readable label (default: derived from name).
    icon : str
        Font Awesome icon class (default: 'fas fa-puzzle-piece').
    description : str
        Short description for the app.
    manifest : dict, optional
        Extra manifest fields to merge.
    license_id : str
        SPDX license identifier (default: 'AGPL-3.0').
    overwrite : bool
        If True, overwrite existing files (default: False).
    frontend_type : str
        Frontend type: 'html' (default) or 'react' for React+Vite+Zustand.

    Returns
    -------
    list[str]
        Relative paths of created files.
    """
    target = Path(target_dir)
    if not target.exists():
        target.mkdir(parents=True, exist_ok=True)

    if not label:
        label = name.replace("_", " ").title().removesuffix(" App")

    class_name = label.replace(" ", "") + "App"
    files = _build_all_files(
        name,
        label,
        class_name,
        icon,
        description,
        manifest,
        license_id,
        frontend_type=frontend_type,
    )

    created = []
    for relpath, content in files.items():
        filepath = target / relpath
        if filepath.exists() and not overwrite:
            logger.debug("Skipping existing file: %s", relpath)
            continue
        filepath.parent.mkdir(parents=True, exist_ok=True)
        filepath.write_text(content, encoding="utf-8")
        created.append(relpath)
        logger.debug("Created: %s", relpath)

    logger.info("Scaffolded %d/%d files in %s", len(created), len(files), target)
    return created


def _build_all_files(
    name,
    label,
    class_name,
    icon,
    description,
    manifest,
    license_id,
    *,
    frontend_type: str = "html",
):
    """Build dict of relpath -> content for all scaffold files."""
    use_react = frontend_type == "react"
    files = {}

    # __init__.py
    files["__init__.py"] = f'"""SciTeX Cloud App: {label}."""\n'

    # apps.py
    files["apps.py"] = _apps_py(name, label, class_name)

    # views.py
    files["views.py"] = _views_py(name, label, description)

    # urls.py
    files["urls.py"] = _urls_py(name)

    # tests.py
    files["tests.py"] = _tests_py(name, label)

    # skill.py
    files["skill.py"] = _skill_py(name, label, description)

    # manifest.json
    files["manifest.json"] = _manifest_json(
        name, label, icon, description, manifest, license_id, frontend_type
    )

    # Templates
    files[f"templates/{name}/index.html"] = _index_html(
        name, label, include_js_bundle=use_react
    )
    files[f"templates/{name}/index_partial.html"] = _index_partial_html(
        name, label, icon, react_mount=use_react
    )

    # Static CSS
    files[f"static/{name}/css/{name}.css"] = _app_css(name, label)

    # Agents config
    files[".agents/agents.json"] = _agents_json(name, label)
    files["AGENTS.md"] = _agents_md(name, label, icon, description, frontend_type)

    # Platform docs for agents
    from ._scaffold_docs import _platform_docs_md

    files["docs/PLATFORM.md"] = _platform_docs_md(name)

    # README
    files["README.md"] = _readme_md(
        name, label, description, license_id, frontend_type=frontend_type
    )

    # LICENSE
    license_text = generate_license_text(license_id)
    if license_text is None:
        license_text = generate_license_text("AGPL-3.0")
    files["LICENSE"] = license_text

    # .gitignore
    files[".gitignore"] = "\n".join(
        [
            "# Runtime data (created by platform, not app source)",
            "scitex/",
            "",
            "# Python",
            "__pycache__/",
            "*.pyc",
            "*.pyo",
            "*.egg-info/",
            "",
            "# Environment",
            ".env",
            ".env.*",
            ".venv/",
            "venv/",
            "node_modules/",
            "",
            "# IDE",
            ".vscode/",
            ".idea/",
            "",
            "# OS",
            ".DS_Store",
            "Thumbs.db",
            "",
        ]
    )

    # pyproject.toml for dual-mode (standalone + extension)
    files["pyproject.toml"] = _pyproject_toml(name, label, description, license_id)

    # CLI with gui command for standalone mode
    files["_cli.py"] = _cli_py(name, label)

    # React frontend files
    if use_react:
        files.update(build_react_files(name, label, icon))

    return files


def _cli_py(name, label):
    """Generate _cli.py — standalone GUI launcher."""
    slug = name.replace("_", "-")
    return f'''"""CLI for {label} — standalone GUI launcher."""

import click


@click.group(invoke_without_command=True)
@click.pass_context
def main(ctx):
    """{label} — SciTeX Cloud App."""
    if ctx.invoked_subcommand is None:
        click.echo(ctx.get_help())


@main.command()
@click.option("--port", "-p", default=8050, help="Server port")
@click.option("--host", "-h", default="127.0.0.1", help="Host to bind")
@click.option("--no-browser", is_flag=True, help="Don't open browser")
@click.option("--force", is_flag=True, help="Kill existing process on port")
def gui(port, host, no_browser, force):
    """Launch standalone GUI with workspace shell."""
    if force:
        import subprocess
        subprocess.run(
            ["fuser", "-k", f"{{port}}/tcp"],
            capture_output=True,
        )

    from scitex_app._standalone import run_standalone

    run_standalone(
        app_module="{name}",
        port=port,
        host=host,
        open_browser=not no_browser,
    )
'''


def _pyproject_toml(name, label, description, license_id):
    """Generate pyproject.toml for dual-mode app (standalone + scitex-cloud extension)."""
    slug = name.replace("_", "-")
    desc = description or f"{label} — a SciTeX Cloud app."
    return f"""[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "{slug}"
version = "0.1.0"
description = "{desc}"
requires-python = ">=3.10"
license = "{license_id}"

[project.scripts]
{slug} = "{name}._cli:main"

[project.optional-dependencies]
scitex = ["scitex-app>=0.1.0", "scitex-ui>=0.1.0"]
dev = ["pytest>=7.0.0"]

[project.entry-points."scitex_modules"]
{name} = "{name}:get_module_config"
"""


# EOF
