"""
Windsurf adapter implementation.
"""

from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List, Optional, Union

import click

from ..core.exceptions import ValidationError
from ..core.models import (
    DocumentConfig,
    PromptMetadata,
    UniversalPrompt,
    UniversalPromptV2,
)
from .base import EditorAdapter
from .mcp_mixin import MCPGenerationMixin
from .sync_mixin import MarkdownSyncMixin


class WindsurfAdapter(MCPGenerationMixin, MarkdownSyncMixin, EditorAdapter):
    """Adapter for Windsurf AI assistant."""

    _description = "Windsurf (.windsurf/rules/)"
    _file_patterns = [".windsurf/rules/*.md"]

    def __init__(self) -> None:
        super().__init__(
            name="windsurf",
            description=self._description,
            file_patterns=self._file_patterns,
        )

    def get_mcp_config_strategy(self) -> Dict[str, Any]:
        """Get MCP configuration strategy for Windsurf adapter."""
        return {
            "supports_project": False,  # Windsurf only supports system-wide
            "project_path": None,
            "system_path": str(
                Path.home() / ".codeium" / "windsurf" / "mcp_config.json"
            ),
            "requires_confirmation": True,  # Always confirm system-wide changes
            "config_format": "json",
        }

    def generate(
        self,
        prompt: Union[UniversalPrompt, UniversalPromptV2],
        output_dir: Path,
        dry_run: bool = False,
        verbose: bool = False,
        variables: Optional[Dict[str, Any]] = None,
        headless: bool = False,
    ) -> List[Path]:
        """Generate Windsurf configuration files."""

        # V2.1: Handle plugins if present
        if isinstance(prompt, UniversalPromptV2) and prompt.plugins:
            return self._generate_v21_plugins(
                prompt, output_dir, dry_run, verbose, variables
            )

        # V2: Use documents field for multi-file generation
        if isinstance(prompt, UniversalPromptV2):
            return self._generate_v2(prompt, output_dir, dry_run, verbose, variables)

        # V1: Apply variable substitution if supported
        processed_prompt = self.substitute_variables(prompt, variables)

        # Process conditionals if supported
        conditional_content = self.process_conditionals(processed_prompt, variables)

        # Generate rules directory system
        rules_files = self._generate_rules_system(
            processed_prompt, conditional_content, output_dir, dry_run, verbose
        )

        return rules_files

    def _generate_v2(
        self,
        prompt: UniversalPromptV2,
        output_dir: Path,
        dry_run: bool,
        verbose: bool,
        variables: Optional[Dict[str, Any]] = None,
    ) -> List[Path]:
        """Generate Windsurf files from v2 schema."""
        rules_dir = output_dir / ".windsurf" / "rules"
        created_files = []

        # If documents field is present, generate separate files
        if prompt.documents:
            for doc in prompt.documents:
                # Apply variable substitution
                content = doc.content
                if variables:
                    for var_name, var_value in variables.items():
                        placeholder = "{{{ " + var_name + " }}}"
                        content = content.replace(placeholder, var_value)

                # Generate filename from document name
                filename = (
                    f"{doc.name}.md" if not doc.name.endswith(".md") else doc.name
                )
                output_file = rules_dir / filename

                if dry_run:
                    click.echo(f"  📁 Would create: {output_file}")
                    if verbose:
                        preview = (
                            content[:200] + "..." if len(content) > 200 else content
                        )
                        click.echo(f"    {preview}")
                    created_files.append(output_file)
                else:
                    rules_dir.mkdir(parents=True, exist_ok=True)
                    with open(output_file, "w", encoding="utf-8") as f:
                        f.write(content)
                    click.echo(f"✅ Generated: {output_file}")
                    created_files.append(output_file)
        else:
            # No documents, use main content as general rules
            content = prompt.content
            if variables:
                for var_name, var_value in variables.items():
                    placeholder = "{{{ " + var_name + " }}}"
                    content = content.replace(placeholder, var_value)

            output_file = rules_dir / "general.md"

            if dry_run:
                click.echo(f"  📁 Would create: {output_file}")
                if verbose:
                    preview = content[:200] + "..." if len(content) > 200 else content
                    click.echo(f"    {preview}")
                created_files.append(output_file)
            else:
                rules_dir.mkdir(parents=True, exist_ok=True)
                with open(output_file, "w", encoding="utf-8") as f:
                    f.write(content)
                click.echo(f"✅ Generated: {output_file}")
                created_files.append(output_file)

        return created_files

    def _generate_v21_plugins(
        self,
        prompt: UniversalPromptV2,
        output_dir: Path,
        dry_run: bool,
        verbose: bool,
        variables: Optional[Dict[str, Any]] = None,
    ) -> List[Path]:
        """Generate Windsurf files from v2.1 schema with plugin support."""
        created_files = []

        # First, generate the regular v2 markdown files
        markdown_files = self._generate_v2(
            prompt, output_dir, dry_run, verbose, variables
        )
        created_files.extend(markdown_files)

        # Then, handle plugins if present
        if prompt.plugins and prompt.plugins.mcp_servers:
            mcp_files = self._generate_mcp_config(
                prompt.plugins.mcp_servers,
                output_dir,
                dry_run,
                verbose,
                variables,
            )
            created_files.extend(mcp_files)

        return created_files

    def _generate_mcp_config(
        self,
        mcp_servers: list,
        output_dir: Path,
        dry_run: bool,
        verbose: bool,
        variables: Optional[Dict[str, Any]] = None,
    ) -> List[Path]:
        """Generate MCP configuration for Windsurf (system-wide only with confirmation)."""
        strategy = self.get_mcp_config_strategy()
        created_files: List[Path] = []

        # Windsurf only supports system-wide
        if strategy["system_path"]:
            system_path = Path(strategy["system_path"]).expanduser()

            # Always confirm with user for system-wide changes
            if not self.confirm_system_wide_mcp_update(
                "Windsurf", system_path, dry_run
            ):
                if verbose:
                    click.echo("  ⏭️  Skipping Windsurf MCP configuration")
                return created_files

            # Build MCP servers config (uses standard MCP format)
            mcp_config = self.build_mcp_servers_config(
                mcp_servers, variables, format_style="standard"
            )

            # Check if config already exists
            existing_config = self.read_existing_mcp_config(system_path)

            if existing_config:
                # Merge with existing config
                if verbose:
                    click.echo("  ℹ️  Merging MCP servers with existing Windsurf config")
                merged_config = self.merge_mcp_config(
                    existing_config, mcp_config, format_style="standard"
                )
            else:
                merged_config = mcp_config

            # Write the config
            if self.write_mcp_config_file(merged_config, system_path, dry_run, verbose):
                created_files.append(system_path)

        return created_files

    def validate(
        self, prompt: Union[UniversalPrompt, UniversalPromptV2]
    ) -> List[ValidationError]:
        """Validate prompt for Windsurf."""
        errors = []

        # V2 validation: check content exists
        if isinstance(prompt, UniversalPromptV2):
            if not prompt.content or not prompt.content.strip():
                errors.append(
                    ValidationError(
                        field="content",
                        message="Windsurf requires content",
                        severity="error",
                    )
                )
            return errors

        # V1 validation: Windsurf works well with structured instructions
        if not prompt.instructions:
            errors.append(
                ValidationError(
                    field="instructions",
                    message="Windsurf works best with structured instructions",
                    severity="warning",
                )
            )

        return errors

    def supports_variables(self) -> bool:
        """Windsurf supports variable substitution."""
        return True

    def supports_conditionals(self) -> bool:
        """Windsurf supports conditional configuration."""
        return True

    def parse_files(
        self, source_dir: Path
    ) -> Union[UniversalPrompt, UniversalPromptV2]:
        """Parse Windsurf files back into a UniversalPromptV2."""
        # Parse markdown files from .windsurf/rules/
        rules_dir = source_dir / ".windsurf" / "rules"

        if not rules_dir.exists():
            # Fallback to v1 parsing if no rules directory
            return self.parse_markdown_rules_files(
                source_dir=source_dir,
                rules_subdir=".windsurf/rules",
                file_extension="md",
                editor_name="Windsurf",
            )

        # V2: Parse each markdown file as a document
        documents = []
        main_content_parts = []

        for md_file in sorted(rules_dir.glob("*.md")):
            try:
                with open(md_file, "r", encoding="utf-8") as f:
                    content = f.read()

                # Create document for this file
                doc_name = md_file.stem  # Remove .md extension
                documents.append(
                    DocumentConfig(
                        name=doc_name,
                        content=content.strip(),
                    )
                )

                # Also add to main content for backwards compatibility
                main_content_parts.append(
                    f"## {doc_name.replace('-', ' ').title()}\n\n{content}"
                )

            except Exception as e:
                click.echo(f"Warning: Could not parse {md_file}: {e}")

        # Create metadata
        metadata = PromptMetadata(
            title="Windsurf AI Assistant",
            description="Configuration synced from Windsurf rules",
            version="1.0.0",
            author="PrompTrek Sync",
            created=datetime.now().isoformat(),
            updated=datetime.now().isoformat(),
            tags=["windsurf", "synced"],
        )

        # Build main content from all documents
        main_content = (
            "\n\n".join(main_content_parts)
            if main_content_parts
            else "# Windsurf AI Assistant\n\nNo rules found."
        )

        return UniversalPromptV2(
            schema_version="2.0.0",
            metadata=metadata,
            content=main_content,
            documents=documents if documents else None,
            variables={},
        )

    def _generate_rules_system(
        self,
        prompt: Union[UniversalPrompt, UniversalPromptV2],
        conditional_content: Optional[Dict[str, Any]],
        output_dir: Path,
        dry_run: bool,
        verbose: bool,
    ) -> List[Path]:
        """Generate .windsurf/rules/ directory with markdown files."""
        rules_dir = output_dir / ".windsurf" / "rules"
        created_files = []

        # Generate general coding rules
        all_instructions: list[str] = []
        if (
            isinstance(prompt, UniversalPrompt)
            and prompt.instructions
            and prompt.instructions.general
        ):
            all_instructions.extend(prompt.instructions.general)
        if (
            conditional_content
            and "instructions" in conditional_content
            and "general" in conditional_content["instructions"]
        ):
            all_instructions.extend(conditional_content["instructions"]["general"])

        if all_instructions:
            general_file = rules_dir / "general.md"
            general_content = self._build_rules_content(
                "General Coding Rules", all_instructions
            )

            if dry_run:
                click.echo(f"  📁 Would create: {general_file}")
                if verbose:
                    preview = (
                        general_content[:200] + "..."
                        if len(general_content) > 200
                        else general_content
                    )
                    click.echo(f"    {preview}")
                created_files.append(general_file)
            else:
                rules_dir.mkdir(parents=True, exist_ok=True)
                with open(general_file, "w", encoding="utf-8") as f:
                    f.write(general_content)
                click.echo(f"✅ Generated: {general_file}")
                created_files.append(general_file)

        # Generate code style rules
        if (
            isinstance(prompt, UniversalPrompt)
            and prompt.instructions
            and prompt.instructions.code_style
        ):
            style_file = rules_dir / "code-style.md"
            style_content = self._build_rules_content(
                "Code Style Rules", prompt.instructions.code_style
            )

            if dry_run:
                click.echo(f"  📁 Would create: {style_file}")
                if verbose:
                    preview = (
                        style_content[:200] + "..."
                        if len(style_content) > 200
                        else style_content
                    )
                    click.echo(f"    {preview}")
                created_files.append(style_file)
            else:
                rules_dir.mkdir(parents=True, exist_ok=True)
                with open(style_file, "w", encoding="utf-8") as f:
                    f.write(style_content)
                click.echo(f"✅ Generated: {style_file}")
                created_files.append(style_file)

        # Generate testing rules
        if (
            isinstance(prompt, UniversalPrompt)
            and prompt.instructions
            and prompt.instructions.testing
        ):
            testing_file = rules_dir / "testing.md"
            testing_content = self._build_rules_content(
                "Testing Rules", prompt.instructions.testing
            )

            if dry_run:
                click.echo(f"  📁 Would create: {testing_file}")
                if verbose:
                    preview = (
                        testing_content[:200] + "..."
                        if len(testing_content) > 200
                        else testing_content
                    )
                    click.echo(f"    {preview}")
                created_files.append(testing_file)
            else:
                rules_dir.mkdir(parents=True, exist_ok=True)
                with open(testing_file, "w", encoding="utf-8") as f:
                    f.write(testing_content)
                click.echo(f"✅ Generated: {testing_file}")
                created_files.append(testing_file)

        # Generate technology-specific rules
        if (
            isinstance(prompt, UniversalPrompt)
            and prompt.context
            and prompt.context.technologies
        ):
            for tech in prompt.context.technologies[:2]:  # Limit to 2 main technologies
                tech_file = rules_dir / f"{tech.lower()}-rules.md"
                tech_content = self._build_tech_rules_content(tech, prompt)

                if dry_run:
                    click.echo(f"  📁 Would create: {tech_file}")
                    if verbose:
                        preview = (
                            tech_content[:200] + "..."
                            if len(tech_content) > 200
                            else tech_content
                        )
                        click.echo(f"    {preview}")
                    created_files.append(tech_file)
                else:
                    rules_dir.mkdir(parents=True, exist_ok=True)
                    with open(tech_file, "w", encoding="utf-8") as f:
                        f.write(tech_content)
                    click.echo(f"✅ Generated: {tech_file}")
                    created_files.append(tech_file)

        return created_files

    def _build_rules_content(self, title: str, instructions: List[str]) -> str:
        """Build markdown rules content for .windsurf/rules/ files."""
        lines = []

        lines.append(f"# {title}")
        lines.append("")

        for instruction in instructions:
            lines.append(f"- {instruction}")

        lines.append("")
        lines.append("## Additional Guidelines")
        lines.append("- Follow project-specific patterns and conventions")
        lines.append("- Maintain consistency with existing codebase")
        lines.append("- Consider performance and security implications")

        return "\n".join(lines)

    def _build_tech_rules_content(
        self, tech: str, prompt: Union[UniversalPrompt, UniversalPromptV2]
    ) -> str:
        """Build technology-specific rules content."""
        lines = []

        lines.append(f"# {tech.title()} Rules")
        lines.append("")

        # Add general instructions that apply to this tech (V1 only)
        if (
            isinstance(prompt, UniversalPrompt)
            and prompt.instructions
            and prompt.instructions.general
        ):
            lines.append("## General Guidelines")
            for instruction in prompt.instructions.general:
                lines.append(f"- {instruction}")
            lines.append("")

        # Add tech-specific best practices
        lines.append(f"## {tech.title()} Best Practices")
        tech_practices = {
            "typescript": [
                "Use strict TypeScript configuration",
                "Prefer interfaces over types for object shapes",
                "Use proper typing for all function parameters and returns",
                "Leverage TypeScript's utility types when appropriate",
            ],
            "react": [
                "Use functional components with hooks",
                "Implement proper prop typing with TypeScript",
                "Follow React best practices for state management",
                "Use React.memo for performance optimization when needed",
            ],
            "python": [
                "Follow PEP 8 style guidelines",
                "Use type hints for function signatures",
                "Implement proper error handling with try/except blocks",
                "Use docstrings for all functions and classes",
            ],
            "javascript": [
                "Use modern ES6+ syntax",
                "Prefer const and let over var",
                "Use arrow functions appropriately",
                "Implement proper error handling with try/catch blocks",
            ],
        }

        if tech.lower() in tech_practices:
            for practice in tech_practices[tech.lower()]:
                lines.append(f"- {practice}")
        else:
            lines.append(f"- Follow {tech} best practices and conventions")
            lines.append(f"- Maintain consistency with existing {tech} code")
            lines.append(f"- Use {tech} idioms and patterns appropriately")

        return "\n".join(lines)
