"""
Service to capture and sync Claude Code's TodoWrite operations with the database.
"""

import json
import sqlite3
from datetime import datetime
from pathlib import Path
from typing import List, Dict, Any, Optional
import asyncio
from dataclasses import dataclass

from ..core.todo_models import TodoItem, TodoList, TodoSession, TodoStatus, TodoPriority
from .todo_service import TodoService
from .goal_parser import GoalParser


@dataclass
class ClaudeTodo:
    """Represents a todo from Claude's TodoWrite tool."""
    content: str
    status: str
    activeForm: str
    
    def to_todo_item(self, created_by: str = "claude") -> TodoItem:
        """Convert to TodoItem model."""
        status_map = {
            "pending": TodoStatus.PENDING,
            "in_progress": TodoStatus.IN_PROGRESS,
            "completed": TodoStatus.COMPLETED
        }
        
        return TodoItem(
            content=self.content,
            status=status_map.get(self.status, TodoStatus.PENDING),
            created_by=created_by,
            metadata={
                "active_form": self.activeForm,
                "source": "claude_todowrite"
            }
        )


class ClaudeTodoSync:
    """Sync Claude's todos with the database and master goals."""
    
    def __init__(self, storage_dir: str = ".cuti"):
        self.storage_dir = Path(storage_dir).expanduser()
        self.todo_service = TodoService(storage_dir)
        self.goal_parser = GoalParser(self.storage_dir / "GOAL.md")
        self.current_session = None
        self._init_session()
    
    def _init_session(self):
        """Initialize or get current session."""
        # Try to get active session
        sessions = self.todo_service.get_active_sessions()
        if sessions:
            self.current_session = sessions[0]
        else:
            # Create new session
            self.current_session = self._create_session()
    
    def _create_session(self) -> TodoSession:
        """Create a new work session."""
        # Get or create master list
        master_list = self.todo_service.get_master_list()
        if not master_list:
            master_list = self.goal_parser.parse_goal_file()
            master_list = self.goal_parser.sync_with_database(
                self.todo_service, master_list
            )
        
        # Create session
        session = TodoSession(
            name=f"Session {datetime.now().strftime('%Y-%m-%d %H:%M')}",
            master_list=master_list,
            metadata={"created_by": "claude_sync"}
        )
        
        self.todo_service.save_session(session)
        return session
    
    def capture_todo_write(self, todos: List[Dict[str, Any]], 
                          agent_name: Optional[str] = None) -> TodoList:
        """
        Capture TodoWrite operation from Claude.
        
        Args:
            todos: List of todo dictionaries from Claude
            agent_name: Name of the Claude agent if applicable
            
        Returns:
            TodoList created from the captured todos
        """
        # Create a new sub-list for these todos
        sub_list = TodoList(
            name=f"Claude Tasks - {datetime.now().strftime('%H:%M')}",
            description="Tasks generated by Claude",
            created_by=agent_name or "claude",
            parent_list_id=self.current_session.master_list.id if self.current_session.master_list else None,
            session_id=self.current_session.id
        )
        
        # Convert and add todos
        for todo_data in todos:
            claude_todo = ClaudeTodo(
                content=todo_data.get('content', ''),
                status=todo_data.get('status', 'pending'),
                activeForm=todo_data.get('activeForm', '')
            )
            
            todo_item = claude_todo.to_todo_item(created_by=agent_name or "claude")
            
            # Try to link to master goal
            todo_item = self._link_to_master_goal(todo_item)
            
            # Assign to agent if specified
            if agent_name:
                todo_item.assigned_to = agent_name
            
            sub_list.add_todo(todo_item)
        
        # Save to database
        self.todo_service.save_list(sub_list)
        
        # Add to current session
        if self.current_session:
            self.current_session.add_sub_list(sub_list)
            self.todo_service.save_session(self.current_session)
        
        return sub_list
    
    def _link_to_master_goal(self, todo: TodoItem) -> TodoItem:
        """Attempt to link a todo to a master goal based on content similarity."""
        if not self.current_session or not self.current_session.master_list:
            return todo
        
        master_todos = self.current_session.master_list.todos
        best_match = None
        best_score = 0
        
        # Simple keyword matching for now
        todo_words = set(todo.content.lower().split())
        
        for master_todo in master_todos:
            master_words = set(master_todo.content.lower().split())
            # Calculate Jaccard similarity
            intersection = todo_words & master_words
            union = todo_words | master_words
            
            if union:
                score = len(intersection) / len(union)
                if score > best_score and score > 0.2:  # Minimum threshold
                    best_score = score
                    best_match = master_todo
        
        if best_match:
            todo.metadata['linked_goal_id'] = best_match.id
            todo.metadata['goal_alignment_score'] = best_score
            todo.metadata['goal_content'] = best_match.content
        
        return todo
    
    def update_todo_status(self, todo_id: str, new_status: str) -> bool:
        """Update the status of a todo."""
        status_map = {
            "pending": TodoStatus.PENDING,
            "in_progress": TodoStatus.IN_PROGRESS,
            "completed": TodoStatus.COMPLETED,
            "blocked": TodoStatus.BLOCKED
        }
        
        status_enum = status_map.get(new_status)
        if not status_enum:
            return False
        
        # Find and update todo
        for sub_list in self.current_session.sub_lists:
            todo = sub_list.get_todo(todo_id)
            if todo:
                todo.status = status_enum
                if status_enum == TodoStatus.COMPLETED:
                    todo.completed_at = datetime.now()
                    # Check if this completes a master goal
                    self._check_master_goal_completion(todo)
                
                self.todo_service.save_list(sub_list)
                return True
        
        return False
    
    def _check_master_goal_completion(self, completed_todo: TodoItem):
        """Check if completing this todo completes a master goal."""
        linked_goal_id = completed_todo.metadata.get('linked_goal_id')
        if not linked_goal_id or not self.current_session.master_list:
            return
        
        master_todo = self.current_session.master_list.get_todo(linked_goal_id)
        if not master_todo:
            return
        
        # Check if all linked todos are complete
        all_linked_complete = True
        for sub_list in self.current_session.sub_lists:
            for todo in sub_list.todos:
                if (todo.metadata.get('linked_goal_id') == linked_goal_id and 
                    todo.status != TodoStatus.COMPLETED):
                    all_linked_complete = False
                    break
        
        if all_linked_complete:
            master_todo.mark_completed()
            self.todo_service.save_list(self.current_session.master_list)
            # Optionally update GOAL.md
            self.goal_parser.write_goal_file(self.current_session.master_list)
    
    def get_current_todos(self) -> Dict[str, Any]:
        """Get current todos for Claude to see."""
        if not self.current_session:
            return {"master_todos": [], "sub_todos": [], "stats": {}}
        
        result = {
            "master_todos": [],
            "sub_todos": [],
            "stats": self.current_session.get_overall_progress()
        }
        
        # Add master todos
        if self.current_session.master_list:
            for todo in self.current_session.master_list.todos:
                if todo.status != TodoStatus.COMPLETED:
                    result["master_todos"].append(todo.to_dict())
        
        # Add current sub-todos
        for sub_list in self.current_session.sub_lists:
            for todo in sub_list.todos:
                if todo.status != TodoStatus.COMPLETED:
                    result["sub_todos"].append(todo.to_dict())
        
        return result
    
    def suggest_next_todo(self) -> Optional[TodoItem]:
        """Suggest the next todo for Claude to work on."""
        if not self.current_session:
            return None
        
        # Priority order: in_progress > high priority pending > regular pending
        candidates = []
        
        for sub_list in self.current_session.sub_lists:
            for todo in sub_list.todos:
                if todo.status == TodoStatus.IN_PROGRESS:
                    return todo  # Continue in-progress work
                elif todo.status == TodoStatus.PENDING:
                    candidates.append(todo)
        
        # Sort by priority
        candidates.sort(key=lambda t: t.priority.value, reverse=True)
        
        return candidates[0] if candidates else None