#!/usr/bin/env python3
"""
OurDigital Skills Installation Validator

Checks that all components are properly installed and configured.

Usage:
    python validate_install.py
    python validate_install.py --verbose
    python validate_install.py --fix  # Attempt to fix issues
"""

import os
import sys
import json
import argparse
from pathlib import Path
from typing import List, Tuple, Dict

# Colors for terminal output
class Colors:
    GREEN = '\033[92m'
    YELLOW = '\033[93m'
    RED = '\033[91m'
    CYAN = '\033[96m'
    BOLD = '\033[1m'
    END = '\033[0m'

def ok(msg: str) -> None:
    print(f"{Colors.GREEN}[✓]{Colors.END} {msg}")

def warn(msg: str) -> None:
    print(f"{Colors.YELLOW}[!]{Colors.END} {msg}")

def fail(msg: str) -> None:
    print(f"{Colors.RED}[✗]{Colors.END} {msg}")

def info(msg: str) -> None:
    print(f"{Colors.CYAN}[i]{Colors.END} {msg}")


class InstallationValidator:
    def __init__(self, verbose: bool = False):
        self.verbose = verbose
        self.home = Path.home()
        self.script_dir = Path(__file__).parent.parent
        self.skills_dir = self.script_dir.parent

        self.env_file = self.home / ".env.ourdigital"
        self.config_dir = self.home / ".ourdigital"
        self.venv_dir = self.skills_dir / ".venv-ourdigital"

        self.results: List[Tuple[str, bool, str]] = []

    def check(self, name: str, condition: bool, fix_hint: str = "") -> bool:
        """Record a check result."""
        self.results.append((name, condition, fix_hint))
        return condition

    def validate_directories(self) -> int:
        """Check required directories exist."""
        info("Checking directories...")
        passed = 0

        checks = [
            ("Config directory", self.config_dir.exists(),
             f"mkdir -p {self.config_dir}"),
            ("Credentials directory", (self.config_dir / "credentials").exists(),
             f"mkdir -p {self.config_dir}/credentials"),
            ("Logs directory", (self.config_dir / "logs").exists(),
             f"mkdir -p {self.config_dir}/logs"),
        ]

        for name, condition, fix in checks:
            if self.check(name, condition, fix):
                ok(name)
                passed += 1
            else:
                fail(name)
                if self.verbose:
                    print(f"    Fix: {fix}")

        return passed

    def validate_files(self) -> int:
        """Check required files exist."""
        info("Checking files...")
        passed = 0

        checks = [
            ("Environment file (.env.ourdigital)", self.env_file.exists(),
             "cp _ourdigital-shared/.env.ourdigital.template ~/.env.ourdigital"),
            ("Config file (config.yaml)", (self.config_dir / "config.yaml").exists(),
             "cp _ourdigital-shared/config/ourdigital.yaml ~/.ourdigital/config.yaml"),
        ]

        for name, condition, fix in checks:
            if self.check(name, condition, fix):
                ok(name)
                passed += 1
            else:
                fail(name)
                if self.verbose:
                    print(f"    Fix: {fix}")

        return passed

    def validate_env_variables(self) -> int:
        """Check environment variables are set."""
        info("Checking environment variables...")
        passed = 0

        required_vars = [
            "NOTION_API_TOKEN",
            "GHOST_BLOG_ADMIN_KEY",
            "GHOST_JOURNAL_ADMIN_KEY",
        ]

        optional_vars = [
            "FIGMA_ACCESS_TOKEN",
            "N8N_API_KEY",
        ]

        if self.env_file.exists():
            env_content = self.env_file.read_text()

            for var in required_vars:
                has_value = f"{var}=" in env_content and \
                           f"{var}=<" not in env_content and \
                           f"{var}=$" not in env_content
                if self.check(f"Required: {var}", has_value, f"Set {var} in {self.env_file}"):
                    ok(f"{var}")
                    passed += 1
                else:
                    fail(f"{var} (required)")

            for var in optional_vars:
                has_value = f"{var}=" in env_content and \
                           f"{var}=<" not in env_content
                if has_value:
                    ok(f"{var} (optional)")
                    passed += 1
                else:
                    warn(f"{var} (optional, not set)")
        else:
            fail("Environment file not found")

        return passed

    def validate_python_env(self) -> int:
        """Check Python virtual environment."""
        info("Checking Python environment...")
        passed = 0

        if self.check("Virtual environment", self.venv_dir.exists(),
                     f"python3 -m venv {self.venv_dir}"):
            ok("Virtual environment exists")
            passed += 1

            # Check for key packages
            pip_path = self.venv_dir / "bin" / "pip"
            if pip_path.exists():
                ok("pip available")
                passed += 1
        else:
            fail("Virtual environment not found")

        return passed

    def validate_skills(self) -> int:
        """Check skills are properly structured."""
        info("Checking skills...")
        passed = 0

        expected_skills = [
            "01-ourdigital-brand-guide",
            "02-ourdigital-blog",
            "03-ourdigital-journal",
            "04-ourdigital-research",
            "05-ourdigital-document",
            "06-ourdigital-designer",
            "07-ourdigital-ad-manager",
            "08-ourdigital-trainer",
            "09-ourdigital-backoffice",
            "10-ourdigital-skill-creator",
        ]

        for skill in expected_skills:
            skill_dir = self.skills_dir / skill
            has_desktop = (skill_dir / "desktop" / "SKILL.md").exists()
            has_code = (skill_dir / "code" / "SKILL.md").exists()

            if has_desktop and has_code:
                ok(f"{skill}")
                passed += 1
            elif has_desktop or has_code:
                warn(f"{skill} (incomplete)")
            else:
                fail(f"{skill} (missing)")

        return passed

    def validate_permissions(self) -> int:
        """Check file permissions are secure."""
        info("Checking permissions...")
        passed = 0

        if self.env_file.exists():
            mode = oct(self.env_file.stat().st_mode)[-3:]
            if mode in ('600', '400'):
                ok(f".env.ourdigital permissions ({mode})")
                passed += 1
            else:
                warn(f".env.ourdigital permissions ({mode}, should be 600)")

        creds_dir = self.config_dir / "credentials"
        if creds_dir.exists():
            mode = oct(creds_dir.stat().st_mode)[-3:]
            if mode in ('700', '500'):
                ok(f"credentials/ permissions ({mode})")
                passed += 1
            else:
                warn(f"credentials/ permissions ({mode}, should be 700)")

        return passed

    def run(self) -> Dict[str, int]:
        """Run all validation checks."""
        print(f"\n{Colors.CYAN}{Colors.BOLD}OurDigital Skills Installation Validator{Colors.END}\n")

        results = {
            "directories": self.validate_directories(),
            "files": self.validate_files(),
            "env_variables": self.validate_env_variables(),
            "python_env": self.validate_python_env(),
            "skills": self.validate_skills(),
            "permissions": self.validate_permissions(),
        }

        # Summary
        total_passed = sum(results.values())
        total_checks = len(self.results)

        print(f"\n{Colors.CYAN}{'='*50}{Colors.END}")
        print(f"{Colors.BOLD}Summary:{Colors.END} {total_passed}/{total_checks} checks passed")

        if total_passed == total_checks:
            print(f"{Colors.GREEN}All checks passed! Installation is complete.{Colors.END}")
        else:
            failed = [r for r in self.results if not r[1]]
            print(f"{Colors.YELLOW}Some checks failed. Review above for details.{Colors.END}")

            if self.verbose:
                print(f"\n{Colors.BOLD}Failed checks:{Colors.END}")
                for name, _, fix in failed:
                    print(f"  - {name}")
                    if fix:
                        print(f"    Fix: {fix}")

        return results


def main():
    parser = argparse.ArgumentParser(description="Validate OurDigital Skills installation")
    parser.add_argument("--verbose", "-v", action="store_true",
                       help="Show detailed output with fix suggestions")
    parser.add_argument("--json", action="store_true",
                       help="Output results as JSON")
    args = parser.parse_args()

    validator = InstallationValidator(verbose=args.verbose)
    results = validator.run()

    if args.json:
        print(json.dumps(results, indent=2))

    # Exit with error if any checks failed
    total_passed = sum(results.values())
    total_checks = len(validator.results)
    sys.exit(0 if total_passed == total_checks else 1)


if __name__ == "__main__":
    main()
