#!/usr/bin/env python3
"""
Post-Tool Validation Hook for sf-lwc plugin.

This hook runs AFTER Write or Edit tool completes and provides SLDS 2
validation feedback for LWC files (*.html, *.css, *.js).

Integrates:
1. Custom 140-point SLDS 2 scoring (7 categories)
2. Official SLDS Linter (if available via npm)

Hook Input (stdin): JSON with tool_input and tool_response
Hook Output (stdout): JSON with optional output message

This hook is ADVISORY - it provides feedback but does not block operations.
"""

import sys
import os
import json
from pathlib import Path

# Add script directory to path for imports
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, SCRIPT_DIR)

# Find shared modules
PLUGIN_ROOT = os.path.dirname(os.path.dirname(SCRIPT_DIR))  # sf-lwc/
SKILLS_ROOT = os.path.dirname(PLUGIN_ROOT)  # skills root
SHARED_DIR = os.path.join(SKILLS_ROOT, "shared")
sys.path.insert(0, SHARED_DIR)

# Supported LWC file extensions
LWC_EXTENSIONS = {".html", ".css", ".js"}


def is_lwc_file(file_path: str) -> bool:
    """
    Check if file is an LWC component file.

    We validate .html (templates), .css (styles), and .js (controllers).
    """
    ext = Path(file_path).suffix.lower()
    return ext in LWC_EXTENSIONS


def validate_lwc_file(file_path: str) -> dict:
    """
    Run comprehensive SLDS 2 validation on an LWC file.

    Args:
        file_path: Path to .html, .css, or .js file

    Returns:
        dict with validation results and output message
    """
    output_parts = []
    file_name = os.path.basename(file_path)
    ext = Path(file_path).suffix.lower()

    try:
        # ═══════════════════════════════════════════════════════════════════
        # PHASE 1: Custom 140-point SLDS 2 validation
        # ═══════════════════════════════════════════════════════════════════
        from validate_slds import SLDSValidator

        validator = SLDSValidator(file_path)
        results = validator.validate()

        score = results.get("score", 0)
        max_score = results.get("max_score", 140)
        issues = results.get("issues", [])
        scores = results.get("scores", {})

        # ═══════════════════════════════════════════════════════════════════
        # PHASE 1.5: LWC Template Anti-Pattern Validation (for HTML files)
        # ═══════════════════════════════════════════════════════════════════
        if ext == ".html":
            try:
                from template_validator import LWCTemplateValidator

                template_validator = LWCTemplateValidator(file_path)
                template_results = template_validator.validate()
                template_issues = template_results.get("issues", [])

                # Add template issues to main issues list
                for tpl_issue in template_issues:
                    issues.append(
                        {
                            "severity": tpl_issue.get("severity", "WARNING"),
                            "category": "template_" + tpl_issue.get("category", "pattern"),
                            "message": tpl_issue.get("message", ""),
                            "line": tpl_issue.get("line", 0),
                            "fix": tpl_issue.get("fix", ""),
                            "source": "template-validator",
                        }
                    )

                    # Deduct from score for critical template issues
                    if tpl_issue.get("severity") == "CRITICAL":
                        scores["component_structure"] = max(0, scores["component_structure"] - 3)
            except ImportError:
                pass  # Template validator not available
            except Exception:
                pass  # Don't fail validation on template check errors

        # ═══════════════════════════════════════════════════════════════════
        # PHASE 2: Official SLDS Linter (if available)
        # ═══════════════════════════════════════════════════════════════════
        linter_available = False
        linter_violations = []

        try:
            from slds_linter_wrapper import SLDSLinterWrapper

            linter = SLDSLinterWrapper()
            if linter.is_available() and ext in {".html", ".css"}:
                linter_available = True
                linter_result = linter.lint_file(file_path)

                if linter_result.get("success"):
                    linter_violations = linter_result.get("violations", [])

                    # Merge linter violations with issues
                    for v in linter_violations:
                        issues.append(
                            {
                                "severity": v.get("severity", "WARNING"),
                                "category": "slds_linter",
                                "message": f"[{v.get('rule', 'slds')}] {v.get('message', '')}",
                                "line": v.get("line", 0),
                                "source": "slds-linter",
                            }
                        )
        except ImportError:
            pass
        except Exception:
            pass

        # ═══════════════════════════════════════════════════════════════════
        # PHASE 3: Calculate rating
        # ═══════════════════════════════════════════════════════════════════
        pct = (score / max_score * 100) if max_score > 0 else 0
        if pct >= 90:
            rating_stars = 5
            rating = "Production-ready SLDS 2"
        elif pct >= 80:
            rating_stars = 4
            rating = "Good"
        elif pct >= 70:
            rating_stars = 3
            rating = "Functional"
        elif pct >= 60:
            rating_stars = 2
            rating = "Needs work"
        else:
            rating_stars = 1
            rating = "Critical issues"

        stars = "⭐" * rating_stars + "☆" * (5 - rating_stars)

        # ═══════════════════════════════════════════════════════════════════
        # PHASE 4: Format output
        # ═══════════════════════════════════════════════════════════════════
        output_parts.append("")
        output_parts.append(f"🎨 SLDS 2 Validation: {file_name}")
        output_parts.append("═" * 60)
        output_parts.append(f"📊 Score: {score}/{max_score} {stars} {rating}")

        # Category breakdown
        if scores:
            output_parts.append("")
            output_parts.append("📋 Category Breakdown:")
            for cat, cat_score in scores.items():
                max_cat = validator.max_scores.get(cat, 0)
                if max_cat > 0:
                    icon = (
                        "✅"
                        if cat_score == max_cat
                        else ("⚠️" if cat_score >= max_cat * 0.7 else "❌")
                    )
                    diff = f" (-{max_cat - cat_score})" if cat_score < max_cat else ""
                    display_name = cat.replace("_", " ").title()
                    output_parts.append(f"   {icon} {display_name}: {cat_score}/{max_cat}{diff}")

        # SLDS Linter status
        output_parts.append("")
        if linter_available:
            output_parts.append("🔧 SLDS Linter: Active")
        else:
            output_parts.append("💡 SLDS Linter: Not installed")
            output_parts.append("   Install: npm i -g @salesforce-ux/slds-linter")

        # Issues list
        if issues:
            output_parts.append("")
            output_parts.append(f"⚠️ Issues Found ({len(issues)}):")

            # Sort by severity
            severity_order = {
                "CRITICAL": 0,
                "HIGH": 1,
                "MODERATE": 2,
                "WARNING": 3,
                "LOW": 4,
                "INFO": 5,
            }
            issues.sort(key=lambda x: severity_order.get(x.get("severity", "INFO"), 5))

            # Display up to 10 issues
            for issue in issues[:10]:
                sev = issue.get("severity", "INFO")
                icon = {
                    "CRITICAL": "🔴",
                    "HIGH": "🟠",
                    "MODERATE": "🟡",
                    "WARNING": "🟡",
                    "LOW": "🔵",
                    "INFO": "⚪",
                }.get(sev, "⚪")
                line_info = f"L{issue.get('line', '?')}" if issue.get("line") else ""
                message = issue.get("message", "")[:60]
                output_parts.append(f"   {icon} {line_info} {message}")

                if issue.get("fix"):
                    fix = issue["fix"][:55] + "..." if len(issue["fix"]) > 55 else issue["fix"]
                    output_parts.append(f"      💡 Fix: {fix}")

            if len(issues) > 10:
                output_parts.append(f"   ... and {len(issues) - 10} more issues")
        else:
            output_parts.append("")
            output_parts.append("✅ No SLDS issues found!")

        output_parts.append("═" * 60)

        return {"continue": True, "output": "\n".join(output_parts)}

    except ImportError as e:
        return {"continue": True, "output": f"⚠️ SLDS validator not available: {e}"}
    except Exception as e:
        return {"continue": True, "output": f"⚠️ SLDS validation error: {e}"}


def main():
    """
    Main hook entry point.

    Reads hook input from stdin, validates LWC files.
    """
    try:
        # Read hook input from stdin
        hook_input = json.load(sys.stdin)

        # Extract file path from tool input
        tool_input = hook_input.get("tool_input", {})
        file_path = tool_input.get("file_path", "")

        # Check if operation was successful
        tool_response = hook_input.get("tool_response", {})
        if not tool_response.get("success", True):
            print(json.dumps({"continue": True}))
            return 0

        # Only validate LWC files
        result = {"continue": True}

        if is_lwc_file(file_path):
            result = validate_lwc_file(file_path)

        print(json.dumps(result))
        return 0

    except json.JSONDecodeError:
        print(json.dumps({"continue": True}))
        return 0
    except Exception as e:
        print(json.dumps({"continue": True, "output": f"⚠️ Hook error: {e}"}))
        return 0


if __name__ == "__main__":
    sys.exit(main())
