"""
Project Scorecard Tool - Generate comprehensive project health overview.

[HINT: Project scorecard. Returns overall score, component scores (security, testing,
docs, alignment, clarity, parallelizable, dogfooding, uniqueness), task metrics, production readiness.]
"""

import json
import re
from pathlib import Path
from datetime import datetime
from typing import Any

from ..utils import find_project_root

# Optional: Multi-source wisdom system (extraction-ready subpackage)
try:
    from .wisdom import (
        get_wisdom,
        format_text as format_wisdom_text,
        load_config as load_wisdom_config,
        list_sources as list_available_sources,
    )
    WISDOM_AVAILABLE = True
except ImportError:
    WISDOM_AVAILABLE = False
    get_wisdom = lambda x, **kwargs: None
    format_wisdom_text = lambda x: ""
    load_wisdom_config = lambda: {"disabled": True}
    list_available_sources = lambda: []


def generate_project_scorecard(
    output_format: str = "text",
    include_recommendations: bool = True,
    output_path: str | None = None
) -> dict[str, Any]:
    """
    Generate comprehensive project health scorecard.
    
    [HINT: Project scorecard. Returns overall score, component scores (security, testing,
    docs, alignment, clarity, parallelizable), task metrics, production readiness.]
    
    Args:
        output_format: Output format - "text", "json", or "markdown"
        include_recommendations: Include improvement recommendations
        output_path: Optional path to save report
        
    Returns:
        Dictionary with scorecard data and formatted output
    """
    project_root = find_project_root()
    
    scores = {}
    metrics = {}
    details = {}
    
    # ═══════════════════════════════════════════════════════════════
    # 1. CODEBASE METRICS
    # ═══════════════════════════════════════════════════════════════
    py_files = list(project_root.rglob('*.py'))
    py_files = [f for f in py_files if 'venv' not in str(f) and '.build-env' not in str(f) 
                and '__pycache__' not in str(f)]
    
    total_py_lines = 0
    for f in py_files:
        try:
            total_py_lines += len(f.read_text().splitlines())
        except:
            pass
    
    # Count tools and prompts
    tools_dir = project_root / 'project_management_automation' / 'tools'
    tools_count = len([f for f in tools_dir.glob('*.py') if not f.name.startswith('__')]) if tools_dir.exists() else 0
    
    try:
        import sys
        sys.path.insert(0, str(project_root))
        from prompts import PROMPTS
        prompts_count = len(PROMPTS)
    except:
        prompts_count = 0
    
    metrics['codebase'] = {
        'python_files': len(py_files),
        'python_lines': total_py_lines,
        'mcp_tools': tools_count,
        'mcp_prompts': prompts_count,
    }
    scores['codebase'] = 80  # Base score for having a structured codebase
    
    # ═══════════════════════════════════════════════════════════════
    # 2. TESTING
    # ═══════════════════════════════════════════════════════════════
    test_dir = project_root / 'tests'
    test_files = list(test_dir.rglob('test_*.py')) if test_dir.exists() else []
    test_lines = sum(len(f.read_text().splitlines()) for f in test_files if f.exists())
    
    test_ratio = (test_lines / total_py_lines * 100) if total_py_lines > 0 else 0
    scores['testing'] = min(100, test_ratio * 3)  # 33% ratio = 100%
    
    metrics['testing'] = {
        'test_files': len(test_files),
        'test_lines': test_lines,
        'test_ratio': round(test_ratio, 1),
    }
    
    # ═══════════════════════════════════════════════════════════════
    # 3. DOCUMENTATION
    # ═══════════════════════════════════════════════════════════════
    docs_dir = project_root / 'docs'
    md_files = list(project_root.rglob('*.md'))
    md_files = [f for f in md_files if 'venv' not in str(f)]
    
    doc_lines = sum(len(f.read_text().splitlines()) for f in md_files if f.exists())
    doc_ratio = (doc_lines / total_py_lines * 100) if total_py_lines > 0 else 0
    
    key_docs = ['README.md', 'INSTALL.md', 'docs/SECURITY.md', 'docs/WORKFLOW.md']
    existing_docs = sum(1 for d in key_docs if (project_root / d).exists())
    
    scores['documentation'] = min(100, doc_ratio + (existing_docs / len(key_docs) * 50))
    
    metrics['documentation'] = {
        'doc_files': len(md_files),
        'doc_lines': doc_lines,
        'doc_ratio': round(doc_ratio, 1),
        'key_docs': f"{existing_docs}/{len(key_docs)}",
    }
    
    # ═══════════════════════════════════════════════════════════════
    # 4. TASK MANAGEMENT
    # ═══════════════════════════════════════════════════════════════
    todo2_file = project_root / '.todo2' / 'state.todo2.json'
    if todo2_file.exists():
        with open(todo2_file) as f:
            data = json.load(f)
        todos = data.get('todos', [])
        
        pending = [t for t in todos if t.get('status') in ['pending', 'in_progress']]
        completed = [t for t in todos if t.get('status') == 'completed']
        
        completion_rate = len(completed) / len(todos) * 100 if todos else 0
        scores['completion'] = completion_rate
        
        remaining_hours = sum(t.get('estimatedHours', 0) for t in pending)
        
        metrics['tasks'] = {
            'total': len(todos),
            'pending': len(pending),
            'completed': len(completed),
            'completion_rate': round(completion_rate, 1),
            'remaining_hours': remaining_hours,
        }
        
        # ═══════════════════════════════════════════════════════════
        # 5. ALIGNMENT ANALYSIS
        # ═══════════════════════════════════════════════════════════
        mcp_keywords = {
            'mcp', 'fastmcp', 'tool', 'tools', 'prompt', 'prompts', 'resource',
            'server', 'client', 'automation', 'automate', 'security', 'secure',
            'validation', 'validate', 'test', 'testing', 'tests', 'coverage',
            'integration', 'documentation', 'docs', 'workflow', 'ci', 'cd',
            'health', 'analysis', 'task', 'tasks', 'todo', 'sprint',
            'boundary', 'rate', 'limiting', 'access', 'control', 'auth',
            'exarp', 'hook', 'hooks', 'trigger', 'config', 'deploy',
        }
        
        alignment_scores = []
        well_aligned = 0
        moderately_aligned = 0
        for task in pending:
            content = task.get('content', '').lower()
            details_text = (task.get('details', '') or task.get('long_description', '') or '').lower()
            tags = ' '.join(task.get('tags', [])).lower()
            full_text = f"{content} {details_text} {tags}"
            
            words = set(re.findall(r'\b[a-z_]{3,}\b', full_text))
            matches = len(words & mcp_keywords)
            
            # Score based on matches (generous scoring)
            if matches >= 5:
                score = 100
                well_aligned += 1
            elif matches >= 3:
                score = 75
                moderately_aligned += 1
            elif matches >= 2:
                score = 50
                moderately_aligned += 1
            elif matches >= 1:
                score = 30
            else:
                score = 10
            alignment_scores.append(score)
        
        avg_alignment = sum(alignment_scores) / len(alignment_scores) if alignment_scores else 0
        scores['alignment'] = avg_alignment
        
        metrics['alignment'] = {
            'well_aligned': well_aligned,
            'moderately_aligned': moderately_aligned,
            'total_pending': len(pending),
            'avg_score': round(avg_alignment, 1),
        }
        
        # ═══════════════════════════════════════════════════════════
        # 6. CLARITY & PARALLELIZABILITY
        # ═══════════════════════════════════════════════════════════
        action_verbs = ['add', 'implement', 'create', 'fix', 'update', 'remove', 
                       'refactor', 'migrate', 'integrate', 'test', 'document', 'extend']
        
        has_estimate = sum(1 for t in pending if t.get('estimatedHours', 0) > 0)
        has_tags = sum(1 for t in pending if t.get('tags'))
        small_enough = sum(1 for t in pending if 0 < t.get('estimatedHours', 0) <= 4)
        clear_name = sum(1 for t in pending if any(
            t.get('content', '').lower().startswith(v) for v in action_verbs))
        no_deps = sum(1 for t in pending if not t.get('dependsOn') and not t.get('dependencies'))
        
        total_pending = len(pending) or 1
        clarity_score = (has_estimate + has_tags + small_enough + clear_name + no_deps) / (5 * total_pending) * 100
        scores['clarity'] = clarity_score
        
        parallelizable = sum(1 for t in pending if 
            t.get('estimatedHours', 0) <= 4 and 
            not t.get('dependsOn') and 
            not t.get('dependencies'))
        parallel_score = parallelizable / total_pending * 100 if total_pending else 0
        scores['parallelizable'] = parallel_score
        
        metrics['clarity'] = {
            'has_estimate': has_estimate,
            'has_tags': has_tags,
            'small_enough': small_enough,
            'clear_name': clear_name,
            'no_dependencies': no_deps,
            'clarity_score': round(clarity_score, 1),
        }
        
        metrics['parallelizable'] = {
            'ready': parallelizable,
            'total': total_pending,
            'score': round(parallel_score, 1),
        }
    else:
        scores['completion'] = 0
        scores['alignment'] = 0
        scores['clarity'] = 0
        scores['parallelizable'] = 0
        metrics['tasks'] = {'total': 0, 'pending': 0, 'completed': 0}
    
    # ═══════════════════════════════════════════════════════════════
    # 7. SECURITY
    # ═══════════════════════════════════════════════════════════════
    security_checks = {
        'security_docs': (project_root / 'docs' / 'SECURITY.md').exists(),
        'ci_cd_workflow': (project_root / '.github' / 'workflows' / 'ci.yml').exists(),
        'gitignore': (project_root / '.gitignore').exists(),
        'no_hardcoded_secrets': True,
        'input_validation': False,
        'path_boundaries': False,
        'rate_limiting': False,
        'access_control': False,
    }
    
    passed = sum(1 for v in security_checks.values() if v)
    scores['security'] = passed / len(security_checks) * 100
    
    # Count pending security tasks
    security_tasks = [t for t in todos if 'security' in t.get('tags', []) and t.get('status') == 'pending'] if todo2_file.exists() else []
    
    metrics['security'] = {
        'checks_passed': passed,
        'checks_total': len(security_checks),
        'pending_tasks': len(security_tasks),
        'details': security_checks,
    }
    
    # ═══════════════════════════════════════════════════════════════
    # 8. CI/CD
    # ═══════════════════════════════════════════════════════════════
    ci_checks = {
        'github_actions': (project_root / '.github' / 'workflows' / 'ci.yml').exists(),
        'linting': (project_root / 'pyproject.toml').exists(),
        'type_checking': (project_root / 'pyproject.toml').exists(),
        'unit_tests': (project_root / 'tests').exists(),
        'pre_commit': (project_root / '.pre-commit-config.yaml').exists(),
        'dependency_lock': (project_root / 'requirements.txt').exists(),
    }
    
    scores['ci_cd'] = sum(1 for v in ci_checks.values() if v) / len(ci_checks) * 100
    metrics['ci_cd'] = ci_checks
    
    # ═══════════════════════════════════════════════════════════════
    # 9. DOGFOODING SCORE (Does Exarp use its own tools?)
    # ═══════════════════════════════════════════════════════════════
    dogfooding_checks = {
        # Git hooks using exarp
        'pre_commit_hook': (project_root / '.git' / 'hooks' / 'pre-commit').exists() and 
            'exarp' in ((project_root / '.git' / 'hooks' / 'pre-commit').read_text().lower() 
            if (project_root / '.git' / 'hooks' / 'pre-commit').exists() else ''),
        'pre_push_hook': (project_root / '.git' / 'hooks' / 'pre-push').exists() and
            'exarp' in ((project_root / '.git' / 'hooks' / 'pre-push').read_text().lower()
            if (project_root / '.git' / 'hooks' / 'pre-push').exists() else ''),
        'post_commit_hook': (project_root / '.git' / 'hooks' / 'post-commit').exists(),
        'post_merge_hook': (project_root / '.git' / 'hooks' / 'post-merge').exists(),
        # Pre-commit config
        'pre_commit_config': (project_root / '.pre-commit-config.yaml').exists() and
            'exarp' in ((project_root / '.pre-commit-config.yaml').read_text().lower()
            if (project_root / '.pre-commit-config.yaml').exists() else ''),
        # CI/CD using exarp
        'ci_self_check': (project_root / '.github' / 'workflows' / 'ci.yml').exists() and
            'exarp' in ((project_root / '.github' / 'workflows' / 'ci.yml').read_text().lower()
            if (project_root / '.github' / 'workflows' / 'ci.yml').exists() else ''),
        # Cron automation
        'daily_cron': (project_root / 'scripts' / 'cron' / 'run_daily_exarp.sh').exists(),
        'weekly_cron': (project_root / 'scripts' / 'cron' / 'run_weekly_exarp.sh').exists(),
        # Project goals for alignment
        'project_goals': (project_root / 'PROJECT_GOALS.md').exists(),
        # Pattern triggers
        'pattern_triggers': (project_root / '.cursor' / 'automa_patterns.json').exists(),
    }
    
    dogfooding_passed = sum(1 for v in dogfooding_checks.values() if v)
    scores['dogfooding'] = dogfooding_passed / len(dogfooding_checks) * 100
    
    metrics['dogfooding'] = {
        'checks_passed': dogfooding_passed,
        'checks_total': len(dogfooding_checks),
        'details': dogfooding_checks,
        'description': 'How much Exarp uses its own tools for self-maintenance',
    }
    
    # ═══════════════════════════════════════════════════════════════
    # 10. UNIQUENESS SCORE (Are we reinventing the wheel?)
    # ═══════════════════════════════════════════════════════════════
    
    # Check for common patterns that could use existing libraries
    wheel_reinventions = []
    justified_customs = []
    
    # Analyze source files for potential reinventions
    tools_dir = project_root / 'project_management_automation' / 'tools'
    
    # Known patterns that might be reinventions
    reinvention_patterns = {
        'http_client': {
            'patterns': ['requests.', 'urllib', 'http.client', 'aiohttp'],
            'alternatives': ['httpx', 'requests'],
            'check_file': True,
        },
        'json_parsing': {
            'patterns': ['json.loads', 'json.dumps'],
            'alternatives': ['orjson', 'ujson'],
            'check_file': False,  # json is standard, not a reinvention
        },
        'cli_parsing': {
            'patterns': ['argparse', 'sys.argv'],
            'alternatives': ['click', 'typer'],
            'check_file': True,
        },
        'task_management': {
            'patterns': ['todo', 'task', 'subtask'],
            'alternatives': ['GitHub Issues', 'Linear', 'Jira API'],
            'justification': 'MCP-native, offline-first, zero dependencies',
            'check_file': False,  # This IS our core feature
        },
        'file_watching': {
            'patterns': ['watchdog', 'inotify', 'fswatch'],
            'alternatives': ['watchdog', 'watchfiles'],
            'check_file': True,
        },
        'git_operations': {
            'patterns': ['subprocess.*git', 'git.Repo', 'pygit2'],
            'alternatives': ['GitPython', 'pygit2'],
            'justification': 'Minimal subprocess calls, no heavy deps',
            'check_file': False,
        },
        'markdown_parsing': {
            'patterns': ['markdown', 'mistune', 're.findall.*\\['],
            'alternatives': ['markdown-it-py', 'mistune'],
            'check_file': True,
        },
        'yaml_parsing': {
            'patterns': ['yaml.load', 'yaml.safe_load'],
            'alternatives': ['ruamel.yaml', 'PyYAML'],
            'check_file': False,  # yaml is standard for configs
        },
        'test_framework': {
            'patterns': ['unittest', 'pytest'],
            'alternatives': ['pytest'],
            'check_file': False,  # using standard tools
        },
        'duplicate_detection': {
            'patterns': ['levenshtein', 'fuzzy', 'difflib'],
            'alternatives': ['rapidfuzz', 'python-Levenshtein'],
            'justification': 'Simple set-based matching sufficient for task names',
            'check_file': False,
        },
        'cron_scheduling': {
            'patterns': ['cron', 'schedule', 'apscheduler'],
            'alternatives': ['APScheduler', 'schedule'],
            'justification': 'Using system cron, no Python scheduler needed',
            'check_file': False,
        },
    }
    
    # Check requirements.txt for dependencies we DO use
    req_file = project_root / 'requirements.txt'
    dependencies = set()
    if req_file.exists():
        for line in req_file.read_text().splitlines():
            if line.strip() and not line.startswith('#'):
                dep = line.split('==')[0].split('>=')[0].split('[')[0].strip().lower()
                dependencies.add(dep)
    
    # Check pyproject.toml for more deps
    pyproject = project_root / 'pyproject.toml'
    if pyproject.exists():
        content = pyproject.read_text()
        # Simple extraction of dependencies
        for match in re.findall(r'"([a-zA-Z0-9_-]+)', content):
            dependencies.add(match.lower())
    
    # Check for a DESIGN_DECISIONS.md or similar
    design_docs = [
        project_root / 'docs' / 'DESIGN_DECISIONS.md',
        project_root / 'docs' / 'ARCHITECTURE.md',
        project_root / 'docs' / 'WHY_CUSTOM.md',
        project_root / 'DESIGN.md',
    ]
    has_design_docs = any(d.exists() for d in design_docs)
    
    # Score components
    uniqueness_analysis = {
        'core_features': {
            'task_management': {
                'custom': True,
                'justified': True,
                'reason': 'MCP-native task management is our core value proposition',
            },
            'mcp_tools': {
                'custom': True,
                'justified': True, 
                'reason': 'Custom MCP tools are the product itself',
            },
            'project_scorecard': {
                'custom': True,
                'justified': True,
                'reason': 'Project-specific metrics not available elsewhere',
            },
            'alignment_analysis': {
                'custom': True,
                'justified': True,
                'reason': 'Custom goal-task alignment for this project type',
            },
        },
        'infrastructure': {
            'git_hooks': {
                'custom': True,
                'justified': True,
                'reason': 'Simple shell scripts, no framework needed',
            },
            'cron_scripts': {
                'custom': True,
                'justified': True,
                'reason': 'Using system cron, lightweight approach',
            },
            'file_patterns': {
                'custom': True,
                'justified': True,
                'reason': 'Simple JSON config, no complex framework',
            },
        },
        'potential_improvements': [],
    }
    
    # Check if we're using heavy frameworks where simpler would work
    using_fastmcp = 'fastmcp' in dependencies or 'mcp' in dependencies
    using_pydantic = 'pydantic' in dependencies
    
    # FastMCP is justified - it's the standard for MCP servers
    if using_fastmcp:
        uniqueness_analysis['infrastructure']['mcp_framework'] = {
            'custom': False,
            'justified': True,
            'reason': 'FastMCP is the standard MCP server framework',
        }
    
    # Count justified vs potentially unjustified
    total_decisions = 0
    justified_count = 0
    
    for category in ['core_features', 'infrastructure']:
        for name, info in uniqueness_analysis.get(category, {}).items():
            total_decisions += 1
            if info.get('justified'):
                justified_count += 1
    
    # Check for design documentation
    if has_design_docs:
        justified_count += 1
        total_decisions += 1
        uniqueness_analysis['documentation'] = {
            'design_decisions_documented': True,
            'reason': 'Design decisions are documented',
        }
    else:
        total_decisions += 1
        uniqueness_analysis['potential_improvements'].append({
            'item': 'Design Documentation',
            'suggestion': 'Create docs/DESIGN_DECISIONS.md to document why custom implementations were chosen',
            'priority': 'low',
        })
    
    # Calculate uniqueness score
    # Higher score = better justified custom code OR using existing solutions
    uniqueness_score = (justified_count / total_decisions * 100) if total_decisions > 0 else 50
    
    # Bonus for minimal dependencies (less dependency hell)
    dep_count = len(dependencies)
    if dep_count <= 5:
        uniqueness_score = min(100, uniqueness_score + 10)
        uniqueness_analysis['dependency_approach'] = {
            'count': dep_count,
            'rating': 'minimal',
            'reason': 'Minimal dependencies reduces dependency hell',
        }
    elif dep_count <= 15:
        uniqueness_analysis['dependency_approach'] = {
            'count': dep_count,
            'rating': 'moderate',
            'reason': 'Reasonable dependency count',
        }
    else:
        uniqueness_score = max(0, uniqueness_score - 10)
        uniqueness_analysis['dependency_approach'] = {
            'count': dep_count,
            'rating': 'heavy',
            'reason': 'Consider reducing dependencies',
        }
    
    scores['uniqueness'] = uniqueness_score
    
    metrics['uniqueness'] = {
        'score': round(uniqueness_score, 1),
        'justified_decisions': justified_count,
        'total_decisions': total_decisions,
        'dependency_count': dep_count,
        'has_design_docs': has_design_docs,
        'analysis': uniqueness_analysis,
        'description': 'Are we reinventing wheels? If so, is it justified?',
    }
    
    # ═══════════════════════════════════════════════════════════════
    # CALCULATE OVERALL SCORE
    # ═══════════════════════════════════════════════════════════════
    weights = {
        'documentation': 0.07,
        'ci_cd': 0.07,
        'codebase': 0.07,
        'clarity': 0.07,
        'parallelizable': 0.07,
        'alignment': 0.07,
        'security': 0.20,
        'testing': 0.10,
        'completion': 0.05,
        'dogfooding': 0.13,  # Eating our own dog food
        'uniqueness': 0.10,  # Not reinventing wheels (or justified if we are)
    }
    
    overall_score = sum(scores.get(k, 0) * weights.get(k, 0) for k in weights)
    
    # Determine production readiness
    production_ready = scores.get('security', 0) >= 80 and scores.get('testing', 0) >= 50
    blockers = []
    if scores.get('security', 0) < 80:
        blockers.append("Security controls incomplete")
    if scores.get('testing', 0) < 50:
        blockers.append("Test coverage too low")
    
    # ═══════════════════════════════════════════════════════════════
    # BUILD RESULT
    # ═══════════════════════════════════════════════════════════════
    result = {
        'generated_at': datetime.now().isoformat(),
        'overall_score': round(overall_score, 1),
        'production_ready': production_ready,
        'blockers': blockers,
        'scores': {k: round(v, 1) for k, v in scores.items()},
        'weights': weights,
        'metrics': metrics,
    }
    
    # Add recommendations if requested
    if include_recommendations:
        recommendations = []
        
        if scores.get('security', 0) < 80:
            recommendations.append({
                'priority': 'critical',
                'area': 'Security',
                'action': 'Implement path boundary enforcement, rate limiting, and access control',
                'impact': '+25% to security score',
            })
        
        if scores.get('testing', 0) < 50:
            recommendations.append({
                'priority': 'high',
                'area': 'Testing',
                'action': 'Fix failing tests and increase coverage to 30%',
                'impact': '+15% to testing score',
            })
        
        if scores.get('completion', 0) < 25:
            recommendations.append({
                'priority': 'medium',
                'area': 'Tasks',
                'action': 'Complete pending tasks to show progress',
                'impact': '+5% to overall score',
            })
        
        if scores.get('dogfooding', 0) < 70:
            missing = [k for k, v in metrics.get('dogfooding', {}).get('details', {}).items() if not v]
            recommendations.append({
                'priority': 'medium',
                'area': 'Dogfooding',
                'action': f'Enable more self-maintenance: {", ".join(missing[:3])}{"..." if len(missing) > 3 else ""}',
                'impact': '+13% to dogfooding score',
            })
        
        if scores.get('uniqueness', 0) < 80:
            improvements = metrics.get('uniqueness', {}).get('analysis', {}).get('potential_improvements', [])
            if improvements:
                recommendations.append({
                    'priority': 'low',
                    'area': 'Uniqueness',
                    'action': improvements[0].get('suggestion', 'Document design decisions'),
                    'impact': '+10% to uniqueness score',
                })
        
        result['recommendations'] = recommendations
    
    # ═══════════════════════════════════════════════════════════════
    # FORMAT OUTPUT
    # ═══════════════════════════════════════════════════════════════
    if output_format == "json":
        formatted_output = json.dumps(result, indent=2)
    elif output_format == "markdown":
        formatted_output = _format_markdown(result)
    else:
        formatted_output = _format_text(result)
    
    result['formatted_output'] = formatted_output
    
    # Save to file if requested
    if output_path:
        output_file = Path(output_path)
        output_file.parent.mkdir(parents=True, exist_ok=True)
        output_file.write_text(formatted_output)
        result['output_file'] = str(output_file)
    
    return result


def _format_text(data: dict) -> str:
    """Format scorecard as plain text."""
    lines = []
    lines.append("=" * 70)
    lines.append("  📊 EXARP PROJECT SCORE CARD")
    lines.append(f"  Generated: {data['generated_at'][:16].replace('T', ' ')}")
    lines.append("=" * 70)
    
    # Overall score
    overall = data['overall_score']
    status = "🟢" if overall >= 70 else "🟡" if overall >= 50 else "🔴"
    lines.append(f"\n  OVERALL SCORE: {overall}% {status}")
    lines.append(f"  Production Ready: {'YES ✅' if data['production_ready'] else 'NO ❌'}")
    
    if data.get('blockers'):
        lines.append(f"  Blockers: {', '.join(data['blockers'])}")
    
    # Component scores
    lines.append("\n  Component Scores:")
    for name, score in sorted(data['scores'].items(), key=lambda x: -x[1]):
        bar_len = int(score / 5)
        bar = "█" * bar_len + "░" * (20 - bar_len)
        status = "🟢" if score >= 70 else "🟡" if score >= 50 else "🔴"
        weight = int(data['weights'].get(name, 0) * 100)
        lines.append(f"    {name:<14} [{bar}] {score:>5.1f}% {status} (×{weight}%)")
    
    # Key metrics
    lines.append("\n  Key Metrics:")
    if 'tasks' in data['metrics']:
        t = data['metrics']['tasks']
        lines.append(f"    Tasks: {t.get('pending', 0)} pending, {t.get('completed', 0)} completed")
        lines.append(f"    Remaining work: {t.get('remaining_hours', 0)}h")
    
    if 'parallelizable' in data['metrics']:
        p = data['metrics']['parallelizable']
        lines.append(f"    Parallelizable: {p.get('ready', 0)} tasks ({p.get('score', 0)}%)")
    
    if 'dogfooding' in data['metrics']:
        d = data['metrics']['dogfooding']
        lines.append(f"    Dogfooding: {d.get('checks_passed', 0)}/{d.get('checks_total', 0)} self-checks")
    
    if 'uniqueness' in data['metrics']:
        u = data['metrics']['uniqueness']
        deps = u.get('dependency_count', 0)
        justified = u.get('justified_decisions', 0)
        total = u.get('total_decisions', 0)
        lines.append(f"    Uniqueness: {justified}/{total} decisions justified, {deps} deps")
    
    # Recommendations
    if data.get('recommendations'):
        lines.append("\n  Recommendations:")
        for rec in data['recommendations']:
            icon = {'critical': '🔴', 'high': '🟠', 'medium': '🟡'}.get(rec['priority'], '•')
            lines.append(f"    {icon} [{rec['area']}] {rec['action']}")
    
    lines.append("\n" + "=" * 70)
    
    # Add daily wisdom if available and enabled
    if WISDOM_AVAILABLE:
        wisdom_config = load_wisdom_config()
        if not wisdom_config.get("disabled"):
            # Check for first run
            project_root = find_project_root()
            marker_file = project_root / '.exarp_wisdom_seen'
            if not marker_file.exists():
                try:
                    from datetime import datetime
                    marker_file.write_text(f"First seen: {datetime.now().isoformat()}\n")
                    lines.append(_first_run_wisdom_prompt())
                except:
                    pass
            
            wisdom = get_wisdom(data['overall_score'])
            if wisdom:
                lines.append(format_wisdom_text(wisdom))
    
    return "\n".join(lines)


def _format_markdown(data: dict) -> str:
    """Format scorecard as markdown."""
    lines = []
    lines.append("# 📊 Exarp Project Score Card")
    lines.append(f"\n*Generated: {data['generated_at'][:16].replace('T', ' ')}*")
    
    # Overall score
    overall = data['overall_score']
    status = "🟢" if overall >= 70 else "🟡" if overall >= 50 else "🔴"
    lines.append(f"\n## Overall Score: **{overall}%** {status}")
    lines.append(f"\n**Production Ready:** {'✅ Yes' if data['production_ready'] else '❌ No'}")
    
    if data.get('blockers'):
        lines.append(f"\n**Blockers:** {', '.join(data['blockers'])}")
    
    # Component scores table
    lines.append("\n## Component Scores\n")
    lines.append("| Component | Score | Status | Weight |")
    lines.append("|-----------|-------|--------|--------|")
    for name, score in sorted(data['scores'].items(), key=lambda x: -x[1]):
        status = "🟢" if score >= 70 else "🟡" if score >= 50 else "🔴"
        weight = int(data['weights'].get(name, 0) * 100)
        lines.append(f"| {name.title()} | {score:.1f}% | {status} | {weight}% |")
    
    # Key metrics
    lines.append("\n## Key Metrics\n")
    if 'tasks' in data['metrics']:
        t = data['metrics']['tasks']
        lines.append(f"- **Tasks:** {t.get('pending', 0)} pending, {t.get('completed', 0)} completed")
        lines.append(f"- **Remaining work:** {t.get('remaining_hours', 0)}h")
    
    if 'parallelizable' in data['metrics']:
        p = data['metrics']['parallelizable']
        lines.append(f"- **Parallelizable:** {p.get('ready', 0)} tasks ({p.get('score', 0)}%)")
    
    if 'dogfooding' in data['metrics']:
        d = data['metrics']['dogfooding']
        lines.append(f"- **Dogfooding:** {d.get('checks_passed', 0)}/{d.get('checks_total', 0)} self-checks ({data['scores'].get('dogfooding', 0):.0f}%)")
    
    if 'uniqueness' in data['metrics']:
        u = data['metrics']['uniqueness']
        deps = u.get('dependency_count', 0)
        justified = u.get('justified_decisions', 0)
        total = u.get('total_decisions', 0)
        lines.append(f"- **Uniqueness:** {justified}/{total} decisions justified, {deps} dependencies ({data['scores'].get('uniqueness', 0):.0f}%)")
    
    # Recommendations
    if data.get('recommendations'):
        lines.append("\n## Recommendations\n")
        for rec in data['recommendations']:
            icon = {'critical': '🔴', 'high': '🟠', 'medium': '🟡'}.get(rec['priority'], '•')
            lines.append(f"- {icon} **{rec['area']}:** {rec['action']} ({rec['impact']})")
    
    # Add daily wisdom if available and enabled
    if WISDOM_AVAILABLE:
        wisdom_config = load_wisdom_config()
        if not wisdom_config.get("disabled"):
            wisdom = get_wisdom(data['overall_score'])
            if wisdom:
                lines.append(_format_wisdom_markdown(wisdom))
    
    return "\n".join(lines)


def _first_run_wisdom_prompt() -> str:
    """First-run message introducing the wisdom feature."""
    sources = list_available_sources() if WISDOM_AVAILABLE else []
    source_list = ", ".join([s['id'] for s in sources[:5]]) + "..." if len(sources) > 5 else ", ".join([s['id'] for s in sources])
    
    return f"""
┌──────────────────────────────────────────────────────────────────────┐
│  ✨ NEW FEATURE: Daily Wisdom from Public Domain Texts               │
├──────────────────────────────────────────────────────────────────────┤
│  Exarp now includes inspirational quotes matched to your project's   │
│  health status. Multiple wisdom sources are available:               │
│                                                                      │
│  📚 Sources: {source_list:<52} │
│                                                                      │
│  Change source: export EXARP_WISDOM_SOURCE=<source>                  │
│  Example:       EXARP_WISDOM_SOURCE=bofh  (tech humor)               │
│                 EXARP_WISDOM_SOURCE=stoic (resilience)               │
│                 EXARP_WISDOM_SOURCE=tao   (balance)                  │
│                                                                      │
│  To disable: export EXARP_DISABLE_WISDOM=1                           │
│              or create .exarp_no_wisdom file in project root         │
└──────────────────────────────────────────────────────────────────────┘
"""


def _format_wisdom_markdown(wisdom: dict) -> str:
    """Format wisdom as Markdown."""
    if wisdom is None:
        return ""
    
    return f"""
---

### {wisdom.get('wisdom_icon', '📜')} {wisdom.get('wisdom_source', 'Daily Wisdom')}

**Project Status:** {wisdom.get('aeon_level', 'Unknown')}

> *"{wisdom.get('quote', '')}"*
> 
> — {wisdom.get('source', '')}

💡 **{wisdom.get('encouragement', '')}**

<details>
<summary>ℹ️ About this quote</summary>

- **Health Score:** {wisdom.get('health_score', 0):.1f}%
- **Change source:** `EXARP_WISDOM_SOURCE=bofh|tao|stoic|bible|murphy|...`
- **Disable:** `export EXARP_DISABLE_WISDOM=1` or create `.exarp_no_wisdom` file.

</details>

---
"""

