#!/usr/bin/env python3
"""
JavaScript syntax validation tool for MarkiTect build process.

This tool validates that all generated JavaScript in edit mode is syntactically correct,
preventing the regression that caused edit mode to fail completely.
"""

import subprocess
import tempfile
import sys
import re
from pathlib import Path
from typing import List, Tuple, Optional


class JavaScriptValidator:
    """Validates JavaScript syntax in MarkiTect templates."""

    def __init__(self):
        self.errors = []
        self.warnings = []

    def validate_document_manager_templates(self) -> bool:
        """Validate JavaScript templates in DocumentManager."""
        try:
            # Import the template generation method directly to avoid database dependency
            from markitect.document_manager import DocumentManager

            # Create a mock DocumentManager to access the template method
            class MockDatabaseManager:
                pass

            doc_manager = DocumentManager.__new__(DocumentManager)
            doc_manager.database_manager = MockDatabaseManager()

            # Test various configurations
            test_cases = [
                {
                    'title': 'Basic Edit Mode',
                    'markdown': '# Test\n\nBasic content.',
                    'edit_mode': True,
                    'theme': 'github'
                },
                {
                    'title': 'Complex Content',
                    'markdown': '''# Header 1

## Header 2

Paragraph with **bold** and *italic* text.

- List item 1
- List item 2

1. Numbered item
2. Another item

> Blockquote text

```python
code block
```

Final paragraph.''',
                    'edit_mode': True,
                    'theme': 'dark'
                },
                {
                    'title': 'Special Characters',
                    'markdown': "# Test 'quotes' and \"double quotes\"\n\nContent with $pecial ch@racters & symbols!",
                    'edit_mode': True,
                    'theme': 'github'
                }
            ]

            all_valid = True

            for test_case in test_cases:
                print(f"Validating: {test_case['title']}")

                html_content = doc_manager._generate_html_template(
                    title=test_case['title'],
                    markdown_content=test_case['markdown'],
                    edit_mode=test_case['edit_mode'],
                    editor_theme=test_case.get('theme', 'github')
                )

                is_valid, errors = self._validate_html_javascript(html_content, test_case['title'])

                if not is_valid:
                    all_valid = False
                    self.errors.extend(errors)
                else:
                    print(f"  ✅ {test_case['title']} - JavaScript syntax valid")

            return all_valid

        except Exception as e:
            self.errors.append(f"Failed to validate document manager templates: {e}")
            return False

    def _validate_html_javascript(self, html_content: str, context: str) -> Tuple[bool, List[str]]:
        """Extract and validate JavaScript from HTML content."""
        errors = []

        # Extract all JavaScript blocks
        js_blocks = re.findall(r'<script[^>]*>(.*?)</script>', html_content, re.DOTALL)

        if not js_blocks:
            errors.append(f"{context}: No JavaScript blocks found")
            return False, errors

        for i, js_content in enumerate(js_blocks):
            # Skip empty blocks or blocks with only external src
            if not js_content.strip() or 'src=' in js_content:
                continue

            is_valid, js_errors = self._validate_javascript_syntax(js_content, f"{context} block {i+1}")
            if not is_valid:
                errors.extend(js_errors)

        return len(errors) == 0, errors

    def _validate_javascript_syntax(self, js_content: str, context: str) -> Tuple[bool, List[str]]:
        """Validate JavaScript syntax using Node.js."""
        errors = []

        try:
            with tempfile.NamedTemporaryFile(mode='w', suffix='.js', delete=False) as f:
                f.write(js_content)
                temp_js_path = f.name

            # Use Node.js to check syntax
            result = subprocess.run(
                ['node', '-c', temp_js_path],
                capture_output=True,
                text=True,
                timeout=10
            )

            if result.returncode != 0:
                errors.append(f"{context}: JavaScript syntax error - {result.stderr.strip()}")

                # Add helpful debugging info
                lines = js_content.split('\n')
                for line_num, line in enumerate(lines[:20], 1):  # Show first 20 lines
                    if line.strip():
                        print(f"  Line {line_num}: {line[:100]}")  # First 100 chars

            Path(temp_js_path).unlink(missing_ok=True)

        except subprocess.TimeoutExpired:
            errors.append(f"{context}: JavaScript validation timeout")
        except FileNotFoundError:
            errors.append(f"{context}: Node.js not available for validation")
        except Exception as e:
            errors.append(f"{context}: Validation error - {e}")

        return len(errors) == 0, errors

    def check_common_issues(self) -> bool:
        """Check for common JavaScript issues that have caused problems."""
        try:
            from markitect.document_manager import DocumentManager

            # Create a mock DocumentManager to access the template method
            class MockDatabaseManager:
                pass

            doc_manager = DocumentManager.__new__(DocumentManager)
            doc_manager.database_manager = MockDatabaseManager()

            html_content = doc_manager._generate_html_template(
                title="Issue Check",
                markdown_content="# Test\n\nTest content.",
                edit_mode=True
            )

            js_match = re.search(r'<script>(.*?)</script>', html_content, re.DOTALL)
            if not js_match:
                self.errors.append("No JavaScript found for common issues check")
                return False

            js_content = js_match.group(1)
            issues_found = False

            # Check for specific issues that have caused problems
            issue_patterns = [
                (r"'\s*\n\s*'", "Broken string literal across lines"),
                (r'"\s*\n\s*"', "Broken string literal across lines"),
                (r'} else if.*{{.*}} else if.*{[^{]', "Inconsistent brace escaping"),
                (r'\$\{\{.*?\}\}', "Double-escaped template literals"),
                (r'reconstructed \+= .*\'\n', "Unescaped newline in string concatenation"),
            ]

            for pattern, description in issue_patterns:
                matches = re.findall(pattern, js_content)
                if matches:
                    self.errors.append(f"Found {description}: {matches[:3]}...")  # Show first 3 matches
                    issues_found = True

            # Check for required elements
            required_elements = [
                'MarkitectEditor',
                'updateStatus',
                'makeContentEditable',
                'DOMContentLoaded'
            ]

            for element in required_elements:
                if element not in js_content:
                    self.errors.append(f"Missing required element: {element}")
                    issues_found = True

            return not issues_found

        except Exception as e:
            self.errors.append(f"Failed to check common issues: {e}")
            return False

    def validate_all(self) -> bool:
        """Run all validation checks."""
        print("🔍 Validating JavaScript syntax in MarkiTect templates...")

        all_checks_passed = True

        # Run all validation checks
        checks = [
            ("Document Manager Templates", self.validate_document_manager_templates),
            ("Common Issues", self.check_common_issues),
        ]

        for check_name, check_func in checks:
            print(f"\n📋 Running {check_name} check...")
            try:
                if not check_func():
                    all_checks_passed = False
                    print(f"  ❌ {check_name} check failed")
                else:
                    print(f"  ✅ {check_name} check passed")
            except Exception as e:
                all_checks_passed = False
                self.errors.append(f"{check_name} check failed with exception: {e}")
                print(f"  ❌ {check_name} check failed with exception")

        return all_checks_passed

    def report_results(self) -> None:
        """Print validation results."""
        print("\n" + "="*60)
        print("JavaScript Validation Results")
        print("="*60)

        if self.errors:
            print(f"\n❌ {len(self.errors)} Error(s) Found:")
            for i, error in enumerate(self.errors, 1):
                print(f"  {i}. {error}")

        if self.warnings:
            print(f"\n⚠️  {len(self.warnings)} Warning(s):")
            for i, warning in enumerate(self.warnings, 1):
                print(f"  {i}. {warning}")

        if not self.errors and not self.warnings:
            print("\n✅ All JavaScript validation checks passed!")

        print("\n" + "="*60)


def main():
    """Main validation function."""
    validator = JavaScriptValidator()

    success = validator.validate_all()
    validator.report_results()

    return 0 if success else 1


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