"""
Bundle Command Implementation

Generates Databricks Asset Bundle resource files for SchemaX deployments.
Outputs a resource YAML and a deploy script that can be included in an
existing DAB project.
"""

from __future__ import annotations

import textwrap
from pathlib import Path
from typing import Any

from schemax.core.storage import read_project
from schemax.version import SCHEMAX_VERSION

_DEPLOY_SCRIPT_TEMPLATE = textwrap.dedent("""\
    \"\"\"SchemaX deploy script for Databricks Asset Bundles.

    This script is executed as a serverless Python task by a DAB job.
    It invokes `schemax apply` in-process so that Databricks runtime
    authentication is inherited (subprocess would lose the auth context).

    Parameters are passed via spark_python_task.parameters:
      argv[1] = environment (e.g. dev/test/prod)
      argv[2] = execution_mode (local/remote)
      argv[3] = auto_rollback (true/false)
      argv[4] = warehouse_id (optional, only for remote mode)

    Generated by schemax bundle v{schemax_version}.
    \"\"\"

    import os
    import sys
    from pathlib import Path


    def _find_workspace() -> str:
        \"\"\"Find the SchemaX project root by locating .schemax/ directory.\"\"\"
        # Try __file__ first (script on disk)
        try:
            script_dir = Path(os.path.dirname(os.path.abspath(__file__)))
            candidate = script_dir.parent
            if (candidate / ".schemax").is_dir():
                return str(candidate)
        except (NameError, OSError):
            pass
        # Walk up from cwd
        current = Path.cwd()
        for d in [current, *current.parents]:
            if (d / ".schemax").is_dir():
                return str(d)
        return str(current)


    def main() -> None:
        environment = sys.argv[1] if len(sys.argv) > 1 else "dev"
        execution_mode = sys.argv[2] if len(sys.argv) > 2 else "local"
        auto_rollback_str = sys.argv[3] if len(sys.argv) > 3 else "false"
        auto_rollback = auto_rollback_str.lower() == "true"
        warehouse_id = sys.argv[4] if len(sys.argv) > 4 else ""

        if execution_mode == "remote" and not warehouse_id:
            print("ERROR: warehouse_id is required for remote execution mode (passed as fourth parameter)")
            sys.exit(1)

        workspace_dir = _find_workspace()

        print(f"Running SchemaX apply: environment={{environment}}, mode={{execution_mode}}")
        print(f"Workspace: {{workspace_dir}}")

        # Invoke CLI in-process to inherit Databricks runtime auth context
        from schemax.cli import cli as schemax_cli

        args = [
            "apply",
            "--target", environment,
            "--execution-mode", execution_mode,
            "--no-interaction",
            workspace_dir,
        ]
        if warehouse_id:
            args.extend(["--warehouse-id", warehouse_id])
        if auto_rollback:
            args.append("--auto-rollback")

        try:
            schemax_cli(args, standalone_mode=False)
        except SystemExit as e:
            if e.code != 0:
                raise
            # Exit code 0 means success — don't re-raise in Databricks runtime


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


def _build_resource_yaml(
    *,
    project_name: str,
    environments: dict[str, Any],
    schemax_version: str,
) -> str:
    """Build the DAB resource YAML content for SchemaX deployment."""
    lines = [
        f"# SchemaX DAB resources - generated by schemax bundle v{schemax_version}",
        "#",
        "# Include this file in your databricks.yml:",
        "#   include:",
        "#     - resources/schemax.yml",
        "#",
        "# Variables (set in your databricks.yml targets):",
        "#   schemax_execution_mode: local (default) uses spark.sql(), remote uses SQL warehouse",
        "#   warehouse_id: only required when schemax_execution_mode is 'remote'",
        "#",
        "# The job uses ${bundle.target} as the SchemaX environment name,",
        "# so DAB target names should match your SchemaX environments",
        f"# ({', '.join(sorted(environments.keys()))}).",
        "#",
        "# Sync .schemax/ to the workspace by adding to your databricks.yml:",
        "#   sync:",
        "#     include:",
        "#       - .schemax/**",
        "#       - resources/schemax_deploy.py",
        "",
        "variables:",
        "  warehouse_id:",
        '    description: "SQL warehouse ID (required for remote mode, ignored in local mode)"',
        '    default: ""',
        "  schemax_execution_mode:",
        '    description: "Execution mode: local (spark.sql) or remote (SQL warehouse)"',
        '    default: "local"',
        "  schemax_auto_rollback:",
        '    description: "Auto-rollback on failure (true/false)"',
        '    default: "false"',
        "",
        "resources:",
        "  jobs:",
        f"    schemax_deploy_{project_name}:",
        f'      name: "schemax-deploy-{project_name}-${{bundle.target}}"',
        "      tags:",
        '        managed_by: "schemax"',
        f'        schemax_project: "{project_name}"',
        f'        schemax_version: "{schemax_version}"',
        "      environments:",
        "        - environment_key: schemax",
        "          spec:",
        '            environment_version: "2"',
        "            dependencies:",
        f"              - schemaxpy>={schemax_version}",
        "      tasks:",
        "        - task_key: schemax_apply",
        "          environment_key: schemax",
        "          spark_python_task:",
        "            python_file: schemax_deploy.py",
        "            parameters:",
        '              - "${bundle.target}"',
        '              - "${var.schemax_execution_mode}"',
        '              - "${var.schemax_auto_rollback}"',
        '              - "${var.warehouse_id}"',
    ]
    return "\n".join(lines) + "\n"


def generate_bundle(
    *,
    workspace: Path,
    output_dir: Path,
) -> dict[str, Any]:
    """Generate DAB resource files for SchemaX deployment.

    Creates:
      - <output_dir>/schemax.yml       - DAB resource fragment
      - <output_dir>/schemax_deploy.py  - Python deploy script

    Returns a summary dict with paths and metadata.
    """
    project = read_project(workspace)
    project_name: str = project.get("name", "schemax")
    provider_config = project.get("provider", {})
    environments: dict[str, Any] = provider_config.get("environments", {})

    if not environments:
        raise ValueError(
            "No environments configured in project.json. "
            "Run `schemax init` and configure environments first."
        )

    # Sanitize project name for use in YAML identifiers
    safe_name = project_name.replace("-", "_").replace(" ", "_").lower()

    output_dir.mkdir(parents=True, exist_ok=True)

    # Generate resource YAML
    resource_yaml = _build_resource_yaml(
        project_name=safe_name,
        environments=environments,
        schemax_version=SCHEMAX_VERSION,
    )
    resource_path = output_dir / "schemax.yml"
    resource_path.write_text(resource_yaml)

    # Generate deploy script
    deploy_script = _DEPLOY_SCRIPT_TEMPLATE.format(schemax_version=SCHEMAX_VERSION)
    deploy_path = output_dir / "schemax_deploy.py"
    deploy_path.write_text(deploy_script)

    return {
        "project_name": project_name,
        "environments": list(environments.keys()),
        "resource_file": str(resource_path),
        "deploy_script": str(deploy_path),
        "schemax_version": SCHEMAX_VERSION,
    }
