#!/usr/bin/env python3
"""
Digital Karma Score Calculator v6.1
Calculates and updates Digital Karma Score based on federation signals
Usage: python ai/calculate_karma.py
"""

import os
import json
import datetime
from pathlib import Path

ROOT = Path(__file__).parent.parent
NOW = datetime.datetime.utcnow().replace(microsecond=0).isoformat() + "Z"

def load_json(path):
    """Load JSON file"""
    with open(path, 'r', encoding='utf-8') as f:
        return json.load(f)

def save_json(path, data):
    """Save JSON file with pretty formatting"""
    with open(path, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=2)
    print(f"✅ Saved: {path}")

def check_ai_endpoints():
    """Check presence and validity of AI endpoints"""
    required = ['manifest.json', 'health.json', 'catalog.json', 'karma.json']
    ai_dir = ROOT / 'ai'
    
    present = 0
    valid = 0
    
    for endpoint in required:
        path = ai_dir / endpoint
        if path.exists():
            present += 1
            try:
                load_json(path)
                valid += 1
            except:
                pass
    
    # Score: 0.25 per required endpoint present and valid
    score = valid / len(required)
    
    # Bonus for optional endpoints
    optional = ['llm.json', 'diagnostics.json', 'sitemap.json', 'federation.json']
    optional_count = sum(1 for e in optional if (ai_dir / e).exists())
    bonus = min(optional_count * 0.05, 0.25)
    
    return min(score + bonus, 1.0)

def check_schema_coverage():
    """Check Schema.org coverage"""
    # Simplified: Check for entity files
    entities_dir = ROOT / 'entities'
    
    if not entities_dir.exists():
        return 0.0
    
    entity_count = len(list(entities_dir.glob('*.jsonld')))
    
    # Basic scoring: 0.25 per entity file (up to 4)
    score = min(entity_count * 0.25, 1.0)
    
    return score

def check_content_freshness():
    """Check content freshness based on timestamps"""
    try:
        health = load_json(ROOT / 'ai' / 'health.json')
        last_rebuild = health.get('lastRebuild', '')
        
        if not last_rebuild:
            return 0.5
        
        # Parse timestamp
        rebuild_date = datetime.datetime.fromisoformat(last_rebuild.replace('Z', '+00:00'))
        now = datetime.datetime.now(datetime.timezone.utc)
        days_old = (now - rebuild_date).days
        
        # Scoring based on age
        if days_old <= 7:
            return 1.0
        elif days_old <= 30:
            return 0.90
        elif days_old <= 90:
            return 0.75
        elif days_old <= 180:
            return 0.50
        elif days_old <= 365:
            return 0.25
        else:
            return 0.0
    except:
        return 0.5

def check_federation_presence():
    """Check federation integration"""
    try:
        manifest = load_json(ROOT / 'ai' / 'manifest.json')
        
        # Check federation version
        if manifest.get('federation_version') != '6.1':
            return 0.4
        
        # Check related sites
        related = manifest.get('related_sites', [])
        related_count = len(related)
        
        # Scoring based on connections
        if related_count >= 5:
            return 1.0
        elif related_count >= 3:
            return 0.80
        elif related_count >= 1:
            return 0.60
        else:
            return 0.20
    except:
        return 0.0

def check_dataset_quality():
    """Check dataset presence and quality"""
    try:
        catalog = load_json(ROOT / 'ai' / 'catalog.json')
        datasets = catalog.get('dataset', [])
        dataset_count = len(datasets)
        
        # Verify datasets actually exist
        valid_count = 0
        for ds in datasets:
            url = ds.get('url', '')
            if url.startswith('/'):
                path = ROOT / url.lstrip('/')
                if path.exists():
                    valid_count += 1
        
        # Scoring based on valid dataset count
        if valid_count >= 5:
            return 1.0
        elif valid_count >= 3:
            return 0.80
        elif valid_count >= 1:
            return 0.60
        else:
            return 0.20
    except:
        return 0.0

def check_external_links():
    """Estimate external link quality (simplified)"""
    # This would require external API calls in production
    # For now, return a default score
    return 0.75

def check_technical_quality():
    """Check technical quality indicators"""
    score = 0.0
    
    # Check for HTTPS in manifest
    try:
        manifest = load_json(ROOT / 'ai' / 'manifest.json')
        if manifest.get('url', '').startswith('https://'):
            score += 0.3
    except:
        pass
    
    # Check for robots.txt
    if (ROOT / 'robots.txt').exists():
        score += 0.2
    
    # Check for llm.txt
    if (ROOT / 'llm.txt').exists():
        score += 0.2
    
    # Check for sitemap
    if (ROOT / 'sitemap.xml').exists():
        score += 0.15
    
    # Check health status
    try:
        health = load_json(ROOT / 'ai' / 'health.json')
        if health.get('status') == 'ok':
            score += 0.15
    except:
        pass
    
    return min(score, 1.0)

def calculate_digital_karma_score():
    """Calculate overall Digital Karma Score"""
    
    print("\n🔍 Calculating Digital Karma Score v6.1\n")
    print("=" * 50)
    
    # Define weights (must sum to 1.0)
    weights = {
        'schema_coverage': 0.20,
        'content_freshness': 0.15,
        'ai_endpoints': 0.25,
        'federation_presence': 0.15,
        'external_links': 0.10,
        'technical_quality': 0.10,
        'dataset_quality': 0.05
    }
    
    # Calculate signals
    signals = {
        'schema_coverage': check_schema_coverage(),
        'content_freshness': check_content_freshness(),
        'ai_endpoints': check_ai_endpoints(),
        'federation_presence': check_federation_presence(),
        'external_links': check_external_links(),
        'technical_quality': check_technical_quality(),
        'dataset_quality': check_dataset_quality()
    }
    
    # Print signal breakdown
    print("\n📊 Signal Breakdown:\n")
    for signal, value in signals.items():
        weight = weights[signal]
        contribution = value * weight
        print(f"  {signal:25s} {value:.2f} × {weight:.2f} = {contribution:.4f}")
    
    # Calculate total score
    total_score = sum(signals[k] * weights[k] for k in signals)
    total_score = min(max(total_score, 0.0), 1.0)  # Clamp to [0.0, 1.0]
    
    print(f"\n{'=' * 50}")
    print(f"\n✨ Digital Karma Score: {total_score:.2f}\n")
    
    # Determine badges
    badges = [
        {
            "name": "Karma Certified",
            "level": "✅",
            "threshold": 0.70,
            "earned": total_score >= 0.70
        },
        {
            "name": "Karma Pro",
            "level": "⭐",
            "threshold": 0.85,
            "earned": total_score >= 0.85
        },
        {
            "name": "Karma Elite",
            "level": "🏆",
            "threshold": 0.95,
            "earned": total_score >= 0.95
        }
    ]
    
    earned_badges = [b for b in badges if b['earned']]
    if earned_badges:
        print("🏅 Badges Earned:")
        for badge in earned_badges:
            print(f"  {badge['level']} {badge['name']}")
    
    return {
        'score': total_score,
        'signals': signals,
        'badges': badges
    }

def update_karma_json(karma_data):
    """Update karma.json with new score"""
    
    karma_path = ROOT / 'ai' / 'karma.json'
    
    try:
        karma = load_json(karma_path)
    except:
        karma = {}
    
    # Update with new data
    karma.update({
        'site': 'https://www.aiwebsitesystems.com',
        'digital_karma_score': round(karma_data['score'], 2),
        'updated_utc': NOW,
        'federation_version': '6.1',
        'signals': {k: round(v, 2) for k, v in karma_data['signals'].items()},
        'badges': karma_data['badges'],
        'health_status': 'ok'
    })
    
    # Add metrics if present
    try:
        health = load_json(ROOT / 'ai' / 'health.json')
        karma['metrics'] = health.get('metrics', {})
        karma['metrics']['last_content_update'] = NOW
    except:
        pass
    
    save_json(karma_path, karma)
    
    return karma

if __name__ == '__main__':
    print("\n" + "=" * 50)
    print("  Digital Karma Score Calculator v6.1")
    print("=" * 50)
    
    # Calculate score
    karma_data = calculate_digital_karma_score()
    
    # Update karma.json
    print(f"\n📝 Updating karma.json...\n")
    update_karma_json(karma_data)
    
    print("\n✅ Digital Karma Score updated successfully!\n")
