import sys
import shutil
import argparse
from pathlib import Path
from typing import Optional
from subprocess import run


class AIOpsGenerator:
    """Chandan AIOps – Production-ready MLOps project generator."""

    def __init__(self, verbose: bool = False):
        self.verbose = verbose
        self.package_dir = Path(__file__).parent
        self.template_dir = self.package_dir / "templates" / "aiops_project"

    # ------------------------------------------------------------------ #
    # Template Validation
    # ------------------------------------------------------------------ #

    def validate_template(self) -> bool:
        if not self.template_dir.exists():
            print(f"ERROR: Template directory not found:\n{self.template_dir}")
            return False

        required_files = [
            "src/__init__.py",
            "main.py",
            "pyproject.toml",
            "README.md",
            "params.yaml",
        ]

        missing = [
            f for f in required_files
            if not (self.template_dir / f).exists()
        ]

        if missing:
            print("ERROR: Missing essential template files:")
            for f in missing:
                print(f"  - {f}")
            return False

        return True

    # ------------------------------------------------------------------ #
    # Project Creation
    # ------------------------------------------------------------------ #

    def create_project(
        self,
        name: str,
        output_dir: Optional[Path] = None,
    ) -> bool:

        if not name.strip():
            print("ERROR: Project name cannot be empty.")
            return False

        if not self.validate_template():
            return False

        # Case 1: Initialize in current directory
        if name == ".":
            project_path = Path.cwd()

            if any(project_path.iterdir()):
                print("ERROR: Current directory is not empty.")
                print("Use a clean directory or commit existing files first.")
                return False

        # Case 2: Create new project folder
        else:
            base = output_dir if output_dir else Path.cwd()
            project_path = base / name

            if project_path.exists():
                print(f"ERROR: Directory '{name}' already exists.")
                return False

            project_path.mkdir(parents=True)

        try:
            self._copy_template(project_path)
            self._display_success(project_path, name)
            return True

        except Exception as e:
            if name != ".":
                shutil.rmtree(project_path, ignore_errors=True)
            print(f"ERROR: {e}")
            return False

    # ------------------------------------------------------------------ #
    # Internal Helpers
    # ------------------------------------------------------------------ #

    def _copy_template(self, destination: Path):
        for item in self.template_dir.iterdir():
            target = destination / item.name
            if item.is_dir():
                shutil.copytree(item, target)
            else:
                shutil.copy2(item, target)

    def _display_success(self, project_path: Path, name: str):
        print("\n" + "=" * 60)
        print("PROJECT SUCCESSFULLY INITIALIZED")
        print("=" * 60)
        print(f"Location: {project_path.resolve()}\n")

        print("NEXT STEPS:\n")

        step = 1

        if name != ".":
            print(f"{step}) Navigate to project:")
            print(f"   cd {name}\n")
            step += 1

        print(f"{step}) Create virtual environment:")
        print("   Option A (Recommended - uv):")
        print("     uv venv")
        print("     uv sync\n")

        print("   Option B (Standard venv):")
        print("     python -m venv venv")
        print("     venv\\Scripts\\activate  (Windows)")
        print("     source venv/bin/activate (Mac/Linux)")
        print("     pip install -e .\n")
        step += 1

        print(f"{step}) Initialize and run DVC pipeline:")
        print("     dvc init")
        print("     dvc repro\n")
        step += 1

        print(f"{step}) Start MLflow UI (optional):")
        print("     mlflow ui\n")
        step += 1

        print(f"{step}) Run pipeline manually:")
        print("     python main.py\n")
        step += 1

        print(f"{step}) Visualize DVC pipeline:")
        print("     chandan-aiops visualize\n")

        print("=" * 60)
        print("Your AIOps project is ready.")
        print("=" * 60 + "\n")


# ---------------------------------------------------------------------- #
# Validation Command
# ---------------------------------------------------------------------- #

def validate_command(directory: str = ".") -> bool:
    base = Path(directory)

    required = [
        "src",
        "data/raw",
        "models",
        "params.yaml",
        "dvc.yaml",
    ]

    missing = [p for p in required if not (base / p).exists()]

    if missing:
        print("Project validation failed. Missing:")
        for m in missing:
            print(f"  - {m}")
        return False

    print("Project structure is valid.")
    return True


# ---------------------------------------------------------------------- #
# Visualize Command
# ---------------------------------------------------------------------- #

def visualize_pipeline():
    try:
        run(["dvc", "dag"], check=True)
    except Exception:
        print("ERROR: DVC not initialized or dvc.yaml not found.")


# ---------------------------------------------------------------------- #
# CLI Entry Point
# ---------------------------------------------------------------------- #

def main():
    parser = argparse.ArgumentParser(
        description="Chandan AIOps – Enterprise MLOps Project Generator"
    )

    sub = parser.add_subparsers(dest="command")

    # create
    create_parser = sub.add_parser("create", help="Create new project")
    create_parser.add_argument("name", help="Project name or '.'")
    create_parser.add_argument("-o", "--output", help="Output directory")
    create_parser.add_argument("-v", "--verbose", action="store_true")

    # validate
    validate_parser = sub.add_parser("validate", help="Validate project structure")
    validate_parser.add_argument("directory", nargs="?", default=".")

    # visualize
    sub.add_parser("visualize", help="Visualize DVC pipeline")

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

    args = parser.parse_args()

    if args.command == "create":
        generator = AIOpsGenerator(verbose=args.verbose)
        out = Path(args.output) if args.output else None
        sys.exit(0 if generator.create_project(args.name, out) else 1)

    elif args.command == "validate":
        sys.exit(0 if validate_command(args.directory) else 1)

    elif args.command == "visualize":
        visualize_pipeline()

    elif args.command == "version":
        from chandan_aiops import __version__
        print(__version__)

    else:
        parser.print_help()


def app():
    main()


if __name__ == "__main__":
    main()