#!/usr/bin/env python3
"""
Cross-platform structure generator for Orion project.
Works on Windows, Linux, and macOS.

Usage:
    python show_structure.py frontend
    python show_structure.py backend
    python show_structure.py tests
    python show_structure.py all
"""

import os
import subprocess
import sys
from datetime import datetime
from pathlib import Path


def count_files(directory: str, pattern: str) -> int:
    """Count files matching pattern in directory."""
    if not os.path.exists(directory):
        return 0

    count = 0
    for _root, dirs, files in os.walk(directory):
        # Skip __pycache__ and other cache directories
        dirs[:] = [
            d
            for d in dirs
            if d not in ["__pycache__", ".pytest_cache", ".git", "node_modules"]
        ]

        for file in files:
            if pattern == "*" or file.endswith(pattern):
                count += 1
    return count


def get_tree_structure(directory: str, exclude_patterns: list[str] = None) -> str:
    """Generate tree structure for directory."""
    if not os.path.exists(directory):
        return f"Directory {directory} not found"

    # Try to use system tree command first
    try:
        if sys.platform == "win32":
            # Windows tree command
            result = subprocess.run(
                ["tree", "/F", "/A", directory],
                capture_output=True,
                text=True,
                encoding="utf-8",
                errors="replace",
            )
            return result.stdout
        # Linux/Mac tree command with exclusions
        exclude_args = []
        if exclude_patterns:
            exclude_args = ["-I", "|".join(exclude_patterns)]

        result = subprocess.run(
            ["tree", "-F", "-a"] + exclude_args + [directory],
            capture_output=True,
            text=True,
        )
        if result.returncode == 0:
            return result.stdout
    except (subprocess.SubprocessError, FileNotFoundError):
        pass

    # Fallback: generate tree structure manually
    return generate_manual_tree(directory, exclude_patterns)


def generate_manual_tree(
    directory: str, exclude_patterns: list[str] = None, prefix: str = ""
) -> str:
    """Generate tree structure manually when tree command is not available."""
    if exclude_patterns is None:
        exclude_patterns = [
            "__pycache__",
            ".pytest_cache",
            ".git",
            "node_modules",
            "*.pyc",
            "*.pyo",
        ]

    output = []
    path = Path(directory)

    try:
        items = sorted(path.iterdir(), key=lambda x: (not x.is_dir(), x.name))

        for i, item in enumerate(items):
            # Skip excluded patterns
            skip = False
            for pattern in exclude_patterns:
                if pattern.startswith("*"):
                    # File extension pattern
                    if item.name.endswith(pattern[1:]):
                        skip = True
                        break
                else:
                    # Directory or exact name pattern
                    if item.name == pattern or pattern in str(item):
                        skip = True
                        break

            if skip:
                continue

            is_last = i == len(items) - 1
            current_prefix = "└── " if is_last else "├── "

            if item.is_dir():
                output.append(f"{prefix}{current_prefix}{item.name}/")
                extension = "    " if is_last else "│   "
                subtree = generate_manual_tree(
                    str(item), exclude_patterns, prefix + extension
                )
                if subtree:
                    output.append(subtree)
            else:
                output.append(f"{prefix}{current_prefix}{item.name}")
    except PermissionError:
        output.append(f"{prefix}[Permission Denied]")

    return "\n".join(output)


def generate_frontend_structure() -> str:
    """Generate frontend structure report."""
    output = []
    output.append("Frontend Folder Structure")
    output.append(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    output.append("=" * 78)
    output.append("")

    # Templates section
    output.append("")
    output.append(
        "╔══════════════════════════════════════════════════════════════════╗"
    )
    output.append(
        "║                      JINJA2 TEMPLATES                            ║"
    )
    output.append(
        "║                      Location: app/templates                     ║"
    )
    output.append(
        "╚══════════════════════════════════════════════════════════════════╝"
    )
    output.append("")
    output.append(get_tree_structure("app/templates"))

    # Static assets section
    output.append("")
    output.append("")
    output.append(
        "╔══════════════════════════════════════════════════════════════════╗"
    )
    output.append(
        "║                      STATIC ASSETS                               ║"
    )
    output.append(
        "║                      Location: static                            ║"
    )
    output.append(
        "╚══════════════════════════════════════════════════════════════════╝"
    )
    output.append("")
    output.append(get_tree_structure("static"))

    # Documentation section (if exists)
    if os.path.exists("docs"):
        output.append("")
        output.append("")
        output.append(
            "╔══════════════════════════════════════════════════════════════════╗"
        )
        output.append(
            "║                      DOCUMENTATION                               ║"
        )
        output.append(
            "║                      Location: docs                              ║"
        )
        output.append(
            "║                      (also listed in tools structure)            ║"
        )
        output.append(
            "╚══════════════════════════════════════════════════════════════════╝"
        )
        output.append("")
        output.append("Note: Documentation is also included in tools structure")
        output.append("      for infrastructure/DevOps context.")

    # Statistics section
    output.append("")
    output.append("")
    output.append(
        "╔══════════════════════════════════════════════════════════════════╗"
    )
    output.append(
        "║                      STATISTICS                                  ║"
    )
    output.append(
        "╚══════════════════════════════════════════════════════════════════╝"
    )
    output.append("")

    output.append("Templates:")
    output.append(f"  - Total HTML files: {count_files('app/templates', '.html')}")
    output.append(f"  - Total Jinja2 files: {count_files('app/templates', '.j2')}")

    output.append("")
    output.append("Static Assets:")
    output.append(f"  - JavaScript files: {count_files('static', '.js')}")
    output.append(f"  - CSS files: {count_files('static', '.css')}")
    output.append("  - Image files:")
    for ext in ["png", "jpg", "jpeg", "gif", "svg", "webp", "ico"]:
        count = count_files("static", f".{ext}")
        if count > 0:
            output.append(f"    - .{ext}: {count}")

    if os.path.exists("docs"):
        output.append("")
        output.append("Documentation:")
        output.append(f"  - Markdown files: {count_files('docs', '.md')}")
        output.append(f"  - reStructuredText files: {count_files('docs', '.rst')}")

    output.append("")
    output.append("=" * 78)
    output.append("End of structure")

    return "\n".join(output)


def generate_backend_structure() -> str:
    """Generate backend structure report."""
    output = []
    output.append("Backend Folder Structure")
    output.append(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    output.append("=" * 78)
    output.append("")

    exclude = [
        "__pycache__",
        "*.pyc",
        "*.pyo",
        ".pytest_cache",
        "*.egg-info",
        "templates",
    ]

    # Backend directories to include
    backend_dirs = [
        ("app", "Application Code"),
        ("middleware", "Middleware Components"),
        ("models", "Database Models"),
        ("storage", "File Storage"),
        ("tasks", "Background Tasks"),
        ("logs", "Application Logs"),
    ]

    for directory, title in backend_dirs:
        if os.path.exists(directory):
            output.append("")
            output.append(
                "╔══════════════════════════════════════════════════════════════════╗"
            )
            output.append(f"║  {title.upper().center(62)}  ║")
            output.append(f"║  Location: {directory + '/'.ljust(51)}  ║")
            output.append(
                "╚══════════════════════════════════════════════════════════════════╝"
            )
            output.append("")
            output.append(get_tree_structure(directory, exclude))

    # Statistics section
    output.append("")
    output.append("")
    output.append(
        "╔══════════════════════════════════════════════════════════════════╗"
    )
    output.append(
        "║                      STATISTICS                                  ║"
    )
    output.append(
        "╚══════════════════════════════════════════════════════════════════╝"
    )
    output.append("")

    output.append("Python Files by Directory:")
    total_py_files = 0
    for directory, title in backend_dirs:
        if os.path.exists(directory):
            count = count_files(directory, ".py")
            total_py_files += count
            output.append(f"  - {directory}/: {count} files")

    output.append(f"  - Total Python files: {total_py_files}")

    output.append("")
    output.append("Application Components (if in app/):")
    components = ["routes", "services", "schemas", "exceptions", "utils"]
    for component in components:
        component_path = f"app/{component}"
        if os.path.exists(component_path):
            count = count_files(component_path, ".py")
            output.append(f"  - app/{component}: {count} files")

    output.append("")
    output.append("=" * 78)
    output.append("End of structure")

    return "\n".join(output)


def generate_tools_structure() -> str:
    """Generate tools/infrastructure structure report."""
    output = []
    output.append("Tools & Infrastructure Structure")
    output.append(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    output.append("=" * 78)
    output.append("")

    exclude = ["__pycache__", "*.pyc", "*.pyo", ".pytest_cache", "*.egg-info"]

    # Tools directories to include
    tools_dirs = [
        ("alembic", "Database Migrations"),
        ("scripts", "Utility Scripts"),
        ("docker", "Docker Configuration"),
        ("docs", "Documentation"),
    ]

    for directory, title in tools_dirs:
        if os.path.exists(directory):
            output.append("")
            output.append(
                "╔══════════════════════════════════════════════════════════════════╗"
            )
            output.append(f"║  {title.upper().center(62)}  ║")
            output.append(f"║  Location: {directory + '/'.ljust(51)}  ║")
            output.append(
                "╚══════════════════════════════════════════════════════════════════╝"
            )
            output.append("")
            output.append(get_tree_structure(directory, exclude))

    # Configuration files section
    output.append("")
    output.append("")
    output.append(
        "╔══════════════════════════════════════════════════════════════════╗"
    )
    output.append(
        "║                      CONFIGURATION FILES                         ║"
    )
    output.append(
        "╚══════════════════════════════════════════════════════════════════╝"
    )
    output.append("")

    output.append("Root configuration files:")
    config_files = [
        ("Makefile", "Build automation"),
        ("requirements.txt", "Python dependencies"),
        ("pyproject.toml", "Python project config"),
        ("setup.py", "Python setup script"),
        ("setup.cfg", "Setup configuration"),
        ("alembic.ini", "Alembic migrations config"),
        ("mkdocs.yml", "MkDocs documentation config"),
        ("Dockerfile", "Docker image definition"),
        ("docker-compose.yml", "Docker services"),
        (".dockerignore", "Docker ignore patterns"),
        (".gitignore", "Git ignore patterns"),
        (".env.example", "Environment variables template"),
    ]

    for file, description in config_files:
        if os.path.exists(file):
            output.append(f"  ✓ {file.ljust(25)} - {description}")

    # Statistics section
    output.append("")
    output.append("")
    output.append(
        "╔══════════════════════════════════════════════════════════════════╗"
    )
    output.append(
        "║                      STATISTICS                                  ║"
    )
    output.append(
        "╚══════════════════════════════════════════════════════════════════╝"
    )
    output.append("")

    output.append("Database Migrations:")
    if os.path.exists("alembic/versions"):
        migration_count = count_files("alembic/versions", ".py")
        output.append(f"  - Total migrations: {migration_count}")
        if migration_count > 0:
            # Get first and last migration
            try:
                migrations = sorted(
                    [f for f in os.listdir("alembic/versions") if f.endswith(".py")]
                )
                if migrations:
                    output.append(f"  - First: {migrations[0][:40]}...")
                    if len(migrations) > 1:
                        output.append(f"  - Latest: {migrations[-1][:40]}...")
            except Exception:
                pass
    else:
        output.append("  - No alembic/versions directory found")

    output.append("")
    output.append("Scripts:")
    if os.path.exists("scripts"):
        script_types = {
            ".py": "Python scripts",
            ".sh": "Shell scripts",
            ".bat": "Batch scripts",
        }
        for ext, desc in script_types.items():
            count = count_files("scripts", ext)
            if count > 0:
                output.append(f"  - {desc}: {count}")
    else:
        output.append("  - No scripts directory found")

    output.append("")
    output.append("Documentation:")
    if os.path.exists("docs"):
        doc_types = {
            ".md": "Markdown files",
            ".rst": "reStructuredText files",
        }
        for ext, desc in doc_types.items():
            count = count_files("docs", ext)
            if count > 0:
                output.append(f"  - {desc}: {count}")
    else:
        output.append("  - No docs directory found")

    output.append("")
    output.append("Docker:")
    docker_files = ["Dockerfile", "docker-compose.yml", ".dockerignore"]
    docker_exists = any(os.path.exists(f) for f in docker_files)
    if docker_exists:
        output.append("  ✓ Docker configuration present")
        if os.path.exists("docker"):
            output.append(f"  - Docker directory files: {count_files('docker', '*')}")
    else:
        output.append("  - No Docker configuration found")

    output.append("")
    output.append("=" * 78)
    output.append("End of structure")

    return "\n".join(output)


def generate_test_structure() -> str:
    """Generate test structure report."""
    output = []
    output.append("Test Folder Structure")
    output.append(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    output.append("=" * 78)
    output.append("")

    # Test files section
    output.append("")
    output.append(
        "╔══════════════════════════════════════════════════════════════════╗"
    )
    output.append(
        "║                      TEST FILES                                  ║"
    )
    output.append(
        "║                      Location: tests/                            ║"
    )
    output.append(
        "╚══════════════════════════════════════════════════════════════════╝"
    )
    output.append("")

    exclude = ["__pycache__", "*.pyc", "*.pyo", ".pytest_cache", "*.egg-info"]
    output.append(get_tree_structure("tests", exclude))

    # Configuration section
    output.append("")
    output.append("")
    output.append(
        "╔══════════════════════════════════════════════════════════════════╗"
    )
    output.append(
        "║                      TEST CONFIGURATION                          ║"
    )
    output.append(
        "╚══════════════════════════════════════════════════════════════════╝"
    )
    output.append("")

    output.append("Test configuration files:")
    test_config_files = [
        "pytest.ini",
        "conftest.py",
        "tests/conftest.py",
        ".coveragerc",
    ]
    for file in test_config_files:
        if os.path.exists(file):
            output.append(f"  ✓ {file}")

    # Statistics section
    output.append("")
    output.append("")
    output.append(
        "╔══════════════════════════════════════════════════════════════════╗"
    )
    output.append(
        "║                      STATISTICS                                  ║"
    )
    output.append(
        "╚══════════════════════════════════════════════════════════════════╝"
    )
    output.append("")

    # Count test files
    test_file_count = 0
    if os.path.exists("tests"):
        for root, dirs, files in os.walk("tests"):
            dirs[:] = [d for d in dirs if d != "__pycache__"]
            for file in files:
                if file.startswith("test_") and file.endswith(".py"):
                    test_file_count += 1

    output.append("Test Files:")
    output.append(f"  - Total test files: {test_file_count}")

    output.append("")
    output.append("By Category:")
    categories = ["unit", "integration", "system", "e2e", "performance"]
    for category in categories:
        category_path = f"tests/{category}"
        if os.path.exists(category_path):
            count = 0
            for root, dirs, files in os.walk(category_path):
                dirs[:] = [d for d in dirs if d != "__pycache__"]
                for file in files:
                    if file.startswith("test_") and file.endswith(".py"):
                        count += 1
            output.append(f"  - tests/{category}: {count} files")

    # Count test functions
    test_function_count = 0
    if os.path.exists("tests"):
        for root, dirs, files in os.walk("tests"):
            dirs[:] = [d for d in dirs if d != "__pycache__"]
            for file in files:
                if file.startswith("test_") and file.endswith(".py"):
                    filepath = os.path.join(root, file)
                    try:
                        with open(filepath, encoding="utf-8") as f:
                            for line in f:
                                if line.strip().startswith("def test_"):
                                    test_function_count += 1
                    except Exception:
                        pass

    output.append("")
    output.append("Test Functions:")
    output.append(f"  - Total test functions: {test_function_count}")

    output.append("")
    output.append("Coverage Files:")
    if os.path.exists(".coverage"):
        output.append("  ✓ .coverage (coverage data file exists)")
    if os.path.exists("htmlcov"):
        output.append("  ✓ htmlcov/ (HTML coverage report exists)")

    output.append("")
    output.append("=" * 78)
    output.append("End of structure")

    return "\n".join(output)


def main():
    """Main entry point."""
    if len(sys.argv) < 2:
        print("Usage: python show_structure.py [frontend|backend|tests|tools|all]")
        sys.exit(1)

    structure_type = sys.argv[1].lower()

    generators = {
        "frontend": ("frontend-structure.txt", generate_frontend_structure),
        "backend": ("backend-structure.txt", generate_backend_structure),
        "tests": ("test-structure.txt", generate_test_structure),
        "tools": ("tools-structure.txt", generate_tools_structure),
    }

    if structure_type == "all":
        for name, (filename, generator) in generators.items():
            print(f"\n{'=' * 60}")
            print(f"Generating {name} structure...")
            print("=" * 60)
            content = generator()
            with open(filename, "w", encoding="utf-8") as f:
                f.write(content)
            print(f"✅ {name.capitalize()} structure saved to {filename}")
            print(f"\n{content}\n")
    elif structure_type in generators:
        filename, generator = generators[structure_type]
        print(f"Generating {structure_type} structure...")
        content = generator()
        with open(filename, "w", encoding="utf-8") as f:
            f.write(content)
        print(f"\n✅ Structure saved to {filename}\n")
        print(content)
    else:
        print(f"Error: Unknown structure type '{structure_type}'")
        print("Valid options: frontend, backend, tests, tools, all")
        sys.exit(1)


if __name__ == "__main__":
    main()
