"""
VS Code Integration

Provides configuration generation and setup for VS Code.
Includes:
- settings.json configuration
- tasks.json for running groknroll commands
- launch.json for debugging
- Keybindings configuration
"""

import json
import logging
from dataclasses import dataclass, field
from typing import Any

from groknroll.ide.base import IDEConfig, IDEType, IntegrationResult

logger = logging.getLogger(__name__)


@dataclass
class VSCodeExtension:
    """
    VS Code extension recommendation

    Attributes:
        identifier: Extension identifier (publisher.name)
        name: Display name
        description: Brief description
        required: Whether the extension is required
    """

    identifier: str
    name: str
    description: str = ""
    required: bool = False


@dataclass
class VSCodeConfig:
    """
    VS Code specific configuration

    Attributes:
        settings: settings.json content
        tasks: tasks.json content
        launch: launch.json content
        keybindings: Keybindings configuration
        extensions: Recommended extensions
    """

    settings: dict[str, Any] = field(default_factory=dict)
    tasks: dict[str, Any] = field(default_factory=dict)
    launch: dict[str, Any] = field(default_factory=dict)
    keybindings: list[dict[str, Any]] = field(default_factory=list)
    extensions: list[VSCodeExtension] = field(default_factory=list)


# Recommended extensions for groknroll
RECOMMENDED_EXTENSIONS = [
    VSCodeExtension(
        identifier="ms-python.python",
        name="Python",
        description="Python language support",
        required=True,
    ),
    VSCodeExtension(
        identifier="ms-python.vscode-pylance",
        name="Pylance",
        description="Python language server",
        required=True,
    ),
    VSCodeExtension(
        identifier="charliermarsh.ruff",
        name="Ruff",
        description="Python linter",
        required=False,
    ),
    VSCodeExtension(
        identifier="tamasfe.even-better-toml",
        name="Even Better TOML",
        description="TOML language support",
        required=False,
    ),
]


def generate_vscode_settings(
    config: IDEConfig,
    include_python: bool = True,
    include_format: bool = True,
) -> dict[str, Any]:
    """
    Generate VS Code settings.json content

    Args:
        config: IDE configuration
        include_python: Include Python settings
        include_format: Include format on save settings

    Returns:
        Settings dictionary
    """
    settings: dict[str, Any] = {
        # groknroll specific settings
        "groknroll.enable": True,
        "groknroll.path": config.groknroll_path or "groknroll",
        "groknroll.autoActivate": True,
        # Terminal settings for groknroll
        "terminal.integrated.env.osx": {
            "GROKNROLL_PROJECT": str(config.project_root),
        },
        "terminal.integrated.env.linux": {
            "GROKNROLL_PROJECT": str(config.project_root),
        },
        "terminal.integrated.env.windows": {
            "GROKNROLL_PROJECT": str(config.project_root),
        },
    }

    if include_python:
        settings.update(
            {
                # Python settings
                "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
                "python.analysis.typeCheckingMode": "basic",
                "python.analysis.autoImportCompletions": True,
                "python.analysis.autoSearchPaths": True,
                # Pylance settings
                "[python]": {
                    "editor.defaultFormatter": "charliermarsh.ruff",
                    "editor.formatOnSave": include_format,
                    "editor.codeActionsOnSave": {
                        "source.fixAll.ruff": "explicit" if include_format else "never",
                        "source.organizeImports.ruff": "explicit" if include_format else "never",
                    },
                },
            }
        )

    if include_format:
        settings.update(
            {
                "editor.formatOnSave": True,
                "editor.formatOnPaste": False,
                "files.trimTrailingWhitespace": True,
                "files.insertFinalNewline": True,
            }
        )

    # Merge with custom settings from config
    settings.update(config.settings)

    return settings


def generate_vscode_tasks(
    config: IDEConfig,
    include_common: bool = True,
) -> dict[str, Any]:
    """
    Generate VS Code tasks.json content

    Args:
        config: IDE configuration
        include_common: Include common development tasks

    Returns:
        Tasks dictionary
    """
    groknroll_cmd = config.groknroll_path or "groknroll"

    tasks: dict[str, Any] = {
        "version": "2.0.0",
        "tasks": [
            # groknroll build agent
            {
                "label": "groknroll: Build Agent",
                "type": "shell",
                "command": groknroll_cmd,
                "args": ["build", "${input:buildPrompt}"],
                "group": "build",
                "presentation": {
                    "reveal": "always",
                    "panel": "new",
                    "focus": True,
                },
                "problemMatcher": [],
            },
            # groknroll plan agent
            {
                "label": "groknroll: Plan Agent",
                "type": "shell",
                "command": groknroll_cmd,
                "args": ["build", "--agent", "plan", "${input:planPrompt}"],
                "group": "build",
                "presentation": {
                    "reveal": "always",
                    "panel": "new",
                    "focus": True,
                },
                "problemMatcher": [],
            },
            # groknroll oracle
            {
                "label": "groknroll: Oracle Query",
                "type": "shell",
                "command": groknroll_cmd,
                "args": ["oracle", "${input:oracleQuery}"],
                "group": "build",
                "presentation": {
                    "reveal": "always",
                    "panel": "new",
                    "focus": True,
                },
                "problemMatcher": [],
            },
            # groknroll analyze
            {
                "label": "groknroll: Analyze File",
                "type": "shell",
                "command": groknroll_cmd,
                "args": ["analyze", "${file}"],
                "group": "build",
                "presentation": {
                    "reveal": "always",
                    "panel": "shared",
                },
                "problemMatcher": [],
            },
            # groknroll review
            {
                "label": "groknroll: Code Review",
                "type": "shell",
                "command": groknroll_cmd,
                "args": ["review", "${file}"],
                "group": "build",
                "presentation": {
                    "reveal": "always",
                    "panel": "new",
                },
                "problemMatcher": [],
            },
            # groknroll search
            {
                "label": "groknroll: Search Codebase",
                "type": "shell",
                "command": groknroll_cmd,
                "args": ["search", "${input:searchQuery}"],
                "group": "build",
                "presentation": {
                    "reveal": "always",
                    "panel": "shared",
                },
                "problemMatcher": [],
            },
            # groknroll TUI
            {
                "label": "groknroll: Open TUI",
                "type": "shell",
                "command": groknroll_cmd,
                "group": "build",
                "presentation": {
                    "reveal": "always",
                    "panel": "new",
                    "focus": True,
                },
                "problemMatcher": [],
                "isBackground": True,
            },
        ],
        "inputs": [
            {
                "id": "buildPrompt",
                "type": "promptString",
                "description": "Enter task for build agent",
                "default": "",
            },
            {
                "id": "planPrompt",
                "type": "promptString",
                "description": "Enter task for plan agent",
                "default": "",
            },
            {
                "id": "oracleQuery",
                "type": "promptString",
                "description": "Enter oracle query",
                "default": "",
            },
            {
                "id": "searchQuery",
                "type": "promptString",
                "description": "Enter search query",
                "default": "",
            },
        ],
    }

    if include_common:
        tasks["tasks"].extend(
            [
                # Run tests
                {
                    "label": "Run Tests",
                    "type": "shell",
                    "command": "uv",
                    "args": ["run", "pytest", "tests/", "-v"],
                    "group": "test",
                    "presentation": {
                        "reveal": "always",
                        "panel": "shared",
                    },
                    "problemMatcher": "$python",
                },
                # Run linter
                {
                    "label": "Lint",
                    "type": "shell",
                    "command": "uv",
                    "args": ["run", "ruff", "check", "."],
                    "group": "build",
                    "presentation": {
                        "reveal": "always",
                        "panel": "shared",
                    },
                    "problemMatcher": [],
                },
                # Format code
                {
                    "label": "Format",
                    "type": "shell",
                    "command": "uv",
                    "args": ["run", "ruff", "format", "."],
                    "group": "build",
                    "presentation": {
                        "reveal": "always",
                        "panel": "shared",
                    },
                    "problemMatcher": [],
                },
            ]
        )

    return tasks


def generate_vscode_launch(config: IDEConfig) -> dict[str, Any]:
    """
    Generate VS Code launch.json content

    Args:
        config: IDE configuration

    Returns:
        Launch configuration dictionary
    """
    return {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "groknroll: Debug Build Agent",
                "type": "debugpy",
                "request": "launch",
                "module": "groknroll.cli",
                "args": ["build", "${input:debugPrompt}"],
                "console": "integratedTerminal",
                "justMyCode": False,
            },
            {
                "name": "groknroll: Debug Current File",
                "type": "debugpy",
                "request": "launch",
                "program": "${file}",
                "console": "integratedTerminal",
                "justMyCode": True,
            },
            {
                "name": "Python: Current File",
                "type": "debugpy",
                "request": "launch",
                "program": "${file}",
                "console": "integratedTerminal",
            },
        ],
        "inputs": [
            {
                "id": "debugPrompt",
                "type": "promptString",
                "description": "Enter task for debugging",
                "default": "",
            },
        ],
    }


def generate_vscode_keybindings() -> list[dict[str, Any]]:
    """
    Generate VS Code keybindings for groknroll

    Returns:
        List of keybinding configurations
    """
    return [
        {
            "key": "ctrl+shift+g",
            "command": "workbench.action.tasks.runTask",
            "args": "groknroll: Open TUI",
        },
        {
            "key": "ctrl+shift+b",
            "command": "workbench.action.tasks.runTask",
            "args": "groknroll: Build Agent",
        },
        {
            "key": "ctrl+shift+p",
            "command": "workbench.action.tasks.runTask",
            "args": "groknroll: Plan Agent",
        },
        {
            "key": "ctrl+shift+o",
            "command": "workbench.action.tasks.runTask",
            "args": "groknroll: Oracle Query",
        },
        {
            "key": "ctrl+shift+r",
            "command": "workbench.action.tasks.runTask",
            "args": "groknroll: Code Review",
        },
    ]


def generate_vscode_extensions() -> dict[str, Any]:
    """
    Generate VS Code extensions.json content

    Returns:
        Extensions recommendations dictionary
    """
    return {
        "recommendations": [ext.identifier for ext in RECOMMENDED_EXTENSIONS],
        "unwantedRecommendations": [],
    }


def setup_vscode_integration(
    config: IDEConfig,
    create_settings: bool = True,
    create_tasks: bool = True,
    create_launch: bool = True,
    create_extensions: bool = True,
    backup_existing: bool = True,
) -> IntegrationResult:
    """
    Setup VS Code integration for a project

    Args:
        config: IDE configuration
        create_settings: Create/update settings.json
        create_tasks: Create tasks.json
        create_launch: Create launch.json
        create_extensions: Create extensions.json
        backup_existing: Backup existing files

    Returns:
        IntegrationResult with status
    """
    vscode_dir = config.project_root / ".vscode"
    vscode_dir.mkdir(exist_ok=True)

    files_created = []
    files_modified = []

    try:
        # Settings
        if create_settings:
            settings_file = vscode_dir / "settings.json"
            existing_settings = {}

            if settings_file.exists():
                if backup_existing:
                    backup_file = settings_file.with_suffix(".json.bak")
                    backup_file.write_text(settings_file.read_text())

                try:
                    existing_settings = json.loads(settings_file.read_text())
                except json.JSONDecodeError:
                    pass

            new_settings = generate_vscode_settings(config)

            # Merge with existing
            merged_settings = {**existing_settings, **new_settings}

            settings_file.write_text(json.dumps(merged_settings, indent=4) + "\n")

            if settings_file not in files_created:
                files_modified.append(settings_file)

        # Tasks
        if create_tasks:
            tasks_file = vscode_dir / "tasks.json"
            tasks = generate_vscode_tasks(config)

            tasks_file.write_text(json.dumps(tasks, indent=4) + "\n")
            files_created.append(tasks_file)

        # Launch
        if create_launch:
            launch_file = vscode_dir / "launch.json"
            launch = generate_vscode_launch(config)

            launch_file.write_text(json.dumps(launch, indent=4) + "\n")
            files_created.append(launch_file)

        # Extensions
        if create_extensions:
            extensions_file = vscode_dir / "extensions.json"
            extensions = generate_vscode_extensions()

            extensions_file.write_text(json.dumps(extensions, indent=4) + "\n")
            files_created.append(extensions_file)

        return IntegrationResult(
            success=True,
            ide_type=IDEType.VSCODE,
            files_created=files_created,
            files_modified=files_modified,
            message=f"VS Code integration setup in {vscode_dir}",
        )

    except Exception as e:
        logger.error(f"Failed to setup VS Code integration: {e}")
        return IntegrationResult(
            success=False,
            ide_type=IDEType.VSCODE,
            error=str(e),
        )
