"""
Data models for FileManager V2.

Includes:
- LintIssue: Individual linting issue
- LintResults: Aggregated linting results from multiple linters
- FileBlock: XMLComponent representing a file with linting results
- FileManagerState: Scaffold state with change detection
"""

from typing import Dict, List, Optional
from datetime import datetime
from pydantic import Field, BaseModel

from egregore.core.context_management.pact.components.core import XMLComponent
from egregore.core.context_scaffolds.data_types import ScaffoldState


# =============================================================================
# LINTING DATA MODELS
# =============================================================================

class LintIssue(BaseModel):
    """Individual linting issue from a linter."""
    line: int
    column: Optional[int] = None
    type: str  # "error", "warning", "info"
    message: str
    linter: str
    code: Optional[str] = None  # Error code like E501, F401


class LintResults(BaseModel):
    """Aggregated linting results from multiple linters."""
    errors: List[LintIssue] = Field(default_factory=list)
    warnings: List[LintIssue] = Field(default_factory=list)
    info: List[LintIssue] = Field(default_factory=list)
    linter_runs: Dict[str, bool] = Field(default_factory=dict)  # linter -> success

    def has_issues(self) -> bool:
        """Check if there are any errors or warnings."""
        return len(self.errors) > 0 or len(self.warnings) > 0

    def get_issue_by_line(self, line: int) -> List[LintIssue]:
        """Get all issues for a specific line."""
        return [
            issue for issue in (self.errors + self.warnings + self.info)
            if issue.line == line
        ]


# =============================================================================
# FILE BLOCK COMPONENT
# =============================================================================

class FileBlock(XMLComponent):
    """
    Individual file as XMLComponent with automatic XML rendering.

    FileBlocks are rendered as:
    <file path="src/main.py" status="⚠️ 3 Errors" tokens="450" modified="true">
        1 | import sys
        2 | def main():  # ❌ missing docstring (pylint)
        3 |     return x  # ❌ undefined name (ruff)
    </file>
    """
    type: str = "file"
    path: str = ""
    content: str = ""
    lines: int = 0
    tokens: int = 0
    modified: bool = False
    lint_results: Optional[LintResults] = None
    last_linted: Optional[datetime] = None
    previous_content: Optional[str] = None  # For side-by-side comparison

    def render(self) -> str:
        """
        Render file with error formatting based on scaffold error display mode.

        Returns formatted content with inline error markers if linting results exist.
        """
        # Get error formatter from parent scaffold if available
        formatter = self._get_error_formatter()

        # Format content with errors
        if self.lint_results and formatter:
            formatted_content = formatter.format_file_content_with_errors(
                self.content,
                self.lint_results
            )
        else:
            formatted_content = self._format_without_errors()

        # Set XML attributes
        self.attrs['path'] = self.path
        self.attrs['tokens'] = str(self.tokens)

        if self.lint_results:
            self.attrs['status'] = self._get_status_badge()

        if self.modified:
            self.attrs['modified'] = 'true'

        return formatted_content

    def _format_without_errors(self) -> str:
        """Format content without error markers (fallback)."""
        lines = self.content.splitlines()
        formatted_lines = []

        for i, line in enumerate(lines, 1):
            formatted_lines.append(f"{i:3d} | {line}")

        return '\n'.join(formatted_lines)

    def _get_status_badge(self) -> str:
        """Generate status badge for XML attribute."""
        if not self.lint_results:
            return "No Linting"

        error_count = len(self.lint_results.errors)
        warning_count = len(self.lint_results.warnings)

        if error_count > 0:
            badge = f"⚠️ {error_count} Error{'s' if error_count != 1 else ''}"
            if warning_count > 0:
                badge += f", {warning_count} Warning{'s' if warning_count != 1 else ''}"
            return badge
        elif warning_count > 0:
            return f"⚠️ {warning_count} Warning{'s' if warning_count != 1 else ''}"
        else:
            return "✅ No Issues"

    def _get_error_formatter(self):
        """Get error formatter from parent scaffold."""
        # Access through parent scaffold reference (set during FileBlock creation)
        if hasattr(self, '_scaffold') and self._scaffold:
            return self._scaffold.error_formatter

        # Fallback: no formatter available
        return None


# =============================================================================
# STATE MODEL
# =============================================================================

class FileManagerState(ScaffoldState):
    """State for FileManager scaffold with V2 change detection."""
    files: Dict[str, FileBlock] = Field(default_factory=dict)  # path -> FileBlock
    active_directory: Optional[str] = None
    working_dir: Optional[str] = None
    max_files_open: int = 10
    max_file_tokens: int = 5000
    error_display_mode: str = "both"  # inline, detailed, both, minimal, off, custom
