#!/usr/bin/env python3
"""
Git Progress Query - Query git notes for team progress tracking

Enables lead AIs to query git log for task completion and progress tracking.
Combines task metadata from git notes with commit history.

Phase 2 Implementation: Unified audit trail via git notes
"""

import json
import subprocess
import logging
from typing import List, Dict, Optional, Any
from datetime import datetime

logger = logging.getLogger(__name__)


class GitProgressQuery:
    """
    Query git notes for team progress tracking
    
    Lead AI can query git to see what agents accomplished, when, and why.
    Combines task metadata with commit history for unified timeline.
    """
    
    def __init__(self):
        """Initialize git query interface"""
        self.git_available = self._check_git_available()
    
    def _check_git_available(self) -> bool:
        """Check if git is available"""
        try:
            result = subprocess.run(
                ['git', 'rev-parse', '--git-dir'],
                capture_output=True,
                timeout=2,
                cwd='.'
            )
            return result.returncode == 0
        except (subprocess.TimeoutExpired, FileNotFoundError):
            return False
    
    def get_goal_timeline(
        self,
        goal_id: str,
        max_commits: int = 100
    ) -> Dict[str, Any]:
        """
        Get commit timeline for goal with task metadata
        
        Args:
            goal_id: Goal UUID to query
            max_commits: Maximum commits to retrieve
            
        Returns:
            Timeline dict with commits and task metadata
        """
        if not self.git_available:
            return {
                'goal_id': goal_id,
                'error': 'Git not available',
                'commits': []
            }
        
        try:
            # Get commits with notes from goal-specific ref
            note_ref = f"empirica/tasks/{goal_id}"
            
            result = subprocess.run(
                ['git', 'log', f'--max-count={max_commits}', 
                 '--format=%H|%at|%s', f'--notes={note_ref}'],
                capture_output=True,
                timeout=10,
                cwd='.',
                text=True
            )
            
            if result.returncode != 0:
                return {
                    'goal_id': goal_id,
                    'error': f'Git log failed: {result.stderr}',
                    'commits': []
                }
            
            # Parse commits
            commits = []
            for line in result.stdout.strip().split('\n'):
                if not line or line.startswith('Notes'):
                    continue
                
                parts = line.split('|', 2)
                if len(parts) < 3:
                    continue
                
                commit_hash, timestamp, message = parts
                
                # Try to get task note for this commit
                task_note = self._get_task_note(commit_hash, note_ref)
                
                commit_data = {
                    'hash': commit_hash[:7],
                    'full_hash': commit_hash,
                    'timestamp': int(timestamp),
                    'datetime': datetime.fromtimestamp(int(timestamp)).isoformat(),
                    'message': message,
                    'task': task_note
                }
                
                commits.append(commit_data)
            
            # Get completed subtask IDs
            completed_subtasks = [
                c['task']['subtask_id'] 
                for c in commits 
                if c['task'] is not None
            ]
            
            return {
                'goal_id': goal_id,
                'commits': commits,
                'total_commits': len(commits),
                'completed_subtasks': completed_subtasks,
                'completion_count': len(completed_subtasks)
            }
            
        except Exception as e:
            logger.error(f"Error querying goal timeline: {e}")
            return {
                'goal_id': goal_id,
                'error': str(e),
                'commits': []
            }
    
    def _get_task_note(
        self,
        commit_hash: str,
        note_ref: str
    ) -> Optional[Dict[str, Any]]:
        """
        Get task note for a specific commit
        
        Args:
            commit_hash: Commit hash
            note_ref: Git notes reference
            
        Returns:
            Task metadata dict or None
        """
        try:
            result = subprocess.run(
                ['git', 'notes', '--ref', note_ref, 'show', commit_hash],
                capture_output=True,
                timeout=2,
                cwd='.',
                text=True
            )
            
            if result.returncode != 0:
                return None
            
            # Parse JSON note
            note_data = json.loads(result.stdout)
            return note_data
            
        except (subprocess.CalledProcessError, json.JSONDecodeError):
            return None
        except Exception as e:
            logger.debug(f"Error getting task note: {e}")
            return None
    
    def get_team_progress(
        self,
        goal_ids: List[str]
    ) -> Dict[str, Any]:
        """
        Multi-goal progress for team coordination
        
        Lead AI can see progress across multiple agents/goals
        
        Args:
            goal_ids: List of goal UUIDs
            
        Returns:
            Team progress summary
        """
        if not self.git_available:
            return {
                'error': 'Git not available',
                'goals': []
            }
        
        team_data = {
            'goals': [],
            'total_completed_tasks': 0,
            'total_commits': 0
        }
        
        for goal_id in goal_ids:
            goal_timeline = self.get_goal_timeline(goal_id)
            
            team_data['goals'].append({
                'goal_id': goal_id,
                'completed_tasks': goal_timeline.get('completion_count', 0),
                'total_commits': goal_timeline.get('total_commits', 0),
                'last_commit': goal_timeline['commits'][0] if goal_timeline.get('commits') else None
            })
            
            team_data['total_completed_tasks'] += goal_timeline.get('completion_count', 0)
            team_data['total_commits'] += goal_timeline.get('total_commits', 0)
        
        return team_data
    
    def get_unified_timeline(
        self,
        session_id: str,
        goal_id: str
    ) -> Dict[str, Any]:
        """
        Combine task metadata with epistemic state
        
        Shows complete agent journey: goals → actions → learning
        
        Args:
            session_id: Session UUID
            goal_id: Goal UUID
            
        Returns:
            Unified timeline with tasks + epistemic checkpoints
        """
        if not self.git_available:
            return {
                'error': 'Git not available',
                'timeline': []
            }
        
        try:
            # Get task timeline
            task_timeline = self.get_goal_timeline(goal_id)
            
            # Get epistemic checkpoints from session notes
            epistemic_ref = f"empirica/session/{session_id}"
            
            result = subprocess.run(
                ['git', 'log', '--max-count=100',
                 '--format=%H|%at', f'--notes={epistemic_ref}'],
                capture_output=True,
                timeout=10,
                cwd='.',
                text=True
            )
            
            # Build unified timeline
            timeline = []
            
            for commit_data in task_timeline.get('commits', []):
                entry = {
                    'type': 'commit',
                    'timestamp': commit_data['timestamp'],
                    'datetime': commit_data['datetime'],
                    'commit_hash': commit_data['hash'],
                    'message': commit_data['message']
                }
                
                # Add task metadata if present
                if commit_data.get('task'):
                    entry['task'] = {
                        'subtask_id': commit_data['task']['subtask_id'],
                        'description': commit_data['task']['description'],
                        'epistemic_importance': commit_data['task']['epistemic_importance']
                    }
                
                # Try to get epistemic checkpoint for this commit
                epistemic_note = self._get_task_note(
                    commit_data['full_hash'],
                    epistemic_ref
                )
                
                if epistemic_note:
                    entry['epistemic_state'] = {
                        'know': epistemic_note.get('vectors', {}).get('know'),
                        'uncertainty': epistemic_note.get('vectors', {}).get('uncertainty'),
                        'phase': epistemic_note.get('phase')
                    }
                
                timeline.append(entry)
            
            # Sort by timestamp descending
            timeline.sort(key=lambda x: x['timestamp'], reverse=True)
            
            return {
                'session_id': session_id,
                'goal_id': goal_id,
                'timeline': timeline,
                'total_events': len(timeline)
            }
            
        except Exception as e:
            logger.error(f"Error building unified timeline: {e}")
            return {
                'error': str(e),
                'timeline': []
            }
    
    def get_recent_activity(
        self,
        hours: int = 24
    ) -> Dict[str, Any]:
        """
        Get recent activity across all goals
        
        Useful for lead AI to see what's happening now
        
        Args:
            hours: Hours to look back
            
        Returns:
            Recent activity summary
        """
        if not self.git_available:
            return {
                'error': 'Git not available',
                'activity': []
            }
        
        try:
            # Get recent commits
            result = subprocess.run(
                ['git', 'log', f'--since={hours} hours ago',
                 '--format=%H|%at|%s'],
                capture_output=True,
                timeout=5,
                cwd='.',
                text=True
            )
            
            if result.returncode != 0:
                return {
                    'error': 'Git log failed',
                    'activity': []
                }
            
            activity = []
            
            for line in result.stdout.strip().split('\n'):
                if not line:
                    continue
                
                parts = line.split('|', 2)
                if len(parts) < 3:
                    continue
                
                commit_hash, timestamp, message = parts
                
                # Check for task notes in any goal namespace
                # (We'd need to iterate through known goals, but for now just report commits)
                activity.append({
                    'commit_hash': commit_hash[:7],
                    'timestamp': int(timestamp),
                    'datetime': datetime.fromtimestamp(int(timestamp)).isoformat(),
                    'message': message
                })
            
            return {
                'hours': hours,
                'activity': activity,
                'commit_count': len(activity)
            }
            
        except Exception as e:
            logger.error(f"Error getting recent activity: {e}")
            return {
                'error': str(e),
                'activity': []
            }
