#!/usr/bin/env python3
"""
Home Assistant YAML Configuration Validator

This script validates Home Assistant YAML configuration files for syntax errors
and common issues.

Usage:
    # Validate a single file
    python3 validate_yaml.py configuration.yaml

    # Validate automation configuration
    python3 validate_yaml.py automations.yaml --type automation

    # Validate with verbose output
    python3 validate_yaml.py configuration.yaml --verbose
"""

import argparse
import sys
import yaml
from pathlib import Path
from typing import Any, Dict, List, Optional


class HomeAssistantYAMLValidator:
    """Validator for Home Assistant YAML files."""

    # Common required fields for different config types
    AUTOMATION_REQUIRED = ['trigger']
    AUTOMATION_OPTIONAL = ['alias', 'id', 'description', 'condition', 'action', 'mode', 'variables']

    def __init__(self, verbose: bool = False):
        self.verbose = verbose
        self.errors: List[str] = []
        self.warnings: List[str] = []

    def validate_file(self, filepath: Path) -> bool:
        """Validate a YAML file."""
        self.errors = []
        self.warnings = []

        if not filepath.exists():
            self.errors.append(f"File not found: {filepath}")
            return False

        try:
            with open(filepath, 'r', encoding='utf-8') as f:
                content = f.read()

            # Check for tabs (Home Assistant doesn't allow tabs)
            if '\t' in content:
                self.errors.append("File contains tab characters. Use spaces for indentation.")
                return False

            # Parse YAML
            data = yaml.safe_load(content)

            if self.verbose:
                print(f"✓ YAML syntax is valid")

            return True

        except yaml.YAMLError as e:
            self.errors.append(f"YAML syntax error: {str(e)}")
            return False
        except Exception as e:
            self.errors.append(f"Error reading file: {str(e)}")
            return False

    def validate_automation(self, filepath: Path) -> bool:
        """Validate an automation configuration file."""
        if not self.validate_file(filepath):
            return False

        try:
            with open(filepath, 'r', encoding='utf-8') as f:
                data = yaml.safe_load(f)

            if not isinstance(data, list):
                # Single automation wrapped in automation: key
                if isinstance(data, dict):
                    if 'automation' in data:
                        automations = data['automation']
                        if not isinstance(automations, list):
                            automations = [automations]
                    else:
                        automations = [data]
                else:
                    self.errors.append("Automation file must contain a list or dict")
                    return False
            else:
                automations = data

            # Validate each automation
            for i, automation in enumerate(automations):
                if not isinstance(automation, dict):
                    self.errors.append(f"Automation {i+1} is not a dictionary")
                    continue

                # Check required fields
                if 'trigger' not in automation:
                    self.errors.append(f"Automation {i+1}: Missing required field 'trigger'")

                # Check for common issues
                if 'alias' not in automation:
                    self.warnings.append(f"Automation {i+1}: No 'alias' field (recommended for readability)")

                if 'id' not in automation:
                    self.warnings.append(f"Automation {i+1}: No 'id' field (required for UI editor)")

                # Validate trigger structure
                if 'trigger' in automation:
                    triggers = automation['trigger']
                    if not isinstance(triggers, list):
                        triggers = [triggers]

                    for j, trigger in enumerate(triggers):
                        if not isinstance(trigger, dict):
                            self.errors.append(f"Automation {i+1}, Trigger {j+1}: Must be a dictionary")
                            continue
                        if 'trigger' not in trigger and 'platform' not in trigger:
                            self.errors.append(f"Automation {i+1}, Trigger {j+1}: Missing 'trigger' or 'platform' field")

                # Validate action structure if present
                if 'action' in automation:
                    actions = automation['action']
                    if not isinstance(actions, list):
                        actions = [actions]

                    for j, action in enumerate(actions):
                        if not isinstance(action, dict):
                            self.errors.append(f"Automation {i+1}, Action {j+1}: Must be a dictionary")

            if self.verbose and not self.errors:
                print(f"✓ Validated {len(automations)} automation(s)")

            return len(self.errors) == 0

        except Exception as e:
            self.errors.append(f"Error validating automation: {str(e)}")
            return False

    def print_results(self):
        """Print validation results."""
        if self.errors:
            print("\n❌ Errors found:")
            for error in self.errors:
                print(f"  • {error}")

        if self.warnings:
            print("\n⚠️  Warnings:")
            for warning in self.warnings:
                print(f"  • {warning}")

        if not self.errors and not self.warnings:
            print("✅ Validation passed with no errors or warnings")
        elif not self.errors:
            print("\n✅ Validation passed (with warnings)")


def main():
    parser = argparse.ArgumentParser(description='Validate Home Assistant YAML files')
    parser.add_argument('file', help='YAML file to validate')
    parser.add_argument('--type', choices=['automation', 'general'],
                       default='general', help='Type of configuration to validate')
    parser.add_argument('--verbose', '-v', action='store_true',
                       help='Verbose output')

    args = parser.parse_args()

    filepath = Path(args.file)
    validator = HomeAssistantYAMLValidator(verbose=args.verbose)

    if args.type == 'automation':
        success = validator.validate_automation(filepath)
    else:
        success = validator.validate_file(filepath)

    validator.print_results()

    sys.exit(0 if success else 1)


if __name__ == '__main__':
    main()
