"""
Project Tools Module
Provides project management tools for AgentScope agents.
Refactored from tools_api.py for use with ProjectAgent.
""" 
import logging
import json
import asyncio
import uuid
from typing import Optional, List, Dict, Any

from agentscope.tool import ToolResponse
from agentscope.message import TextBlock

from src.services.project_service import project_manager

logger = logging.getLogger(__name__)


def list_projects() -> ToolResponse:
    """ List all projects in the system.
    
    Returns:
        ToolResponse containing a summary of all projects including:
        - id: Project unique identifier
        - name: Project name
        - type: Project type
        - created_at: Creation timestamp
        - episodes_count: Number of episodes/chapters
    """
    try:
        projects = project_manager.list_projects()
        summary = []
        for p in projects:
            summary.append({
                "id": p.id,
                "name": p.name,
                "type": p.type,
                "created_at": str(p.created_at),
                "episodes_count": len(p.episodes) if p.episodes else 0
            })
        return ToolResponse(content=[TextBlock(
            type="text", 
            text=json.dumps(summary, indent=2, ensure_ascii=False)
        )])
    except Exception as e:
        logger.error(f"Tool list_projects error: {e}")
        return ToolResponse(content=[TextBlock(
            type="text", 
            text=f"Error listing projects: {str(e)}"
        )])


def get_project(project_id: str) -> ToolResponse:
    """ 获取 detailed information about a specific project.
    
    Args:
        project_id: The unique identifier of the project to retrieve.
    
    Returns:
        ToolResponse containing full project details including assets,
        episodes, settings, and metadata.
    """
    try:
        project = project_manager.get_project(project_id)
        if not project:
            return ToolResponse(content=[TextBlock(
                type="text", 
                text=f"Project with ID {project_id} not found."
            )])
        
        # 转换 to dict and handle datetime
        data = project.model_dump()
        
        def default_serializer(obj):
            if hasattr(obj, 'isoformat'):
                return obj.isoformat()
            return str(obj)

        return ToolResponse(content=[TextBlock(
            type="text", 
            text=json.dumps(data, indent=2, default=default_serializer, ensure_ascii=False)
        )])
    except Exception as e:
        logger.error(f"Tool get_project error: {e}")
        return ToolResponse(content=[TextBlock(
            type="text", 
            text=f"Error getting project: {str(e)}"
        )])


def create_project(
    name: str, 
    description: str = "", 
    type: str = "video"
) -> ToolResponse:
    """ 创建 a new empty project.
    
    Args:
        name: The name of the project.
        description: A brief description of the project (optional).
        type: The type of project. Defaults to 'video'.
    
    Returns:
        ToolResponse with the new project ID on success.
    """
    try:
        project = project_manager.create_project(
            name=name,
            description=description,
            type=type
        )
        return ToolResponse(content=[TextBlock(
            type="text", 
            text=f"Project created successfully. ID: {project.id}"
        )])
    except Exception as e:
        logger.error(f"Tool create_project error: {e}")
        return ToolResponse(content=[TextBlock(
            type="text", 
            text=f"Error creating project: {str(e)}"
        )])


async def create_project_from_novel(
    name: str, 
    novel_text: str, 
    description: str = "", 
    type: str = "video", 
    style: str = "anime"
) -> ToolResponse:
    """ 创建 a complete project from novel text.
    
    This is a comprehensive tool that:
    1. Creates a new project
    2. Extracts assets (characters, scenes, props) from the text
    3. Splits the text into chapters/episodes
    4. Saves everything to the project
    
    Args:
        name: Project name.
        novel_text: The full text of the novel or script to analyze.
        description: Project description (optional).
        type: Project type. Defaults to 'video'.
        style: Visual style for the project. Options: 'anime', 'realistic', 
               'cinematic', 'cartoon'. Defaults to 'anime'.
    
    Returns:
        ToolResponse with project ID and summary of extracted content.
    """
    from src.services.script import script_service
    from src.models.schemas import Episode
    
    try:
        # 1. Create Project
        project = project_manager.create_project(
            name=name,
            description=description,
            type=type
        )
        project_id = project.id
        
        # 2. Analyze Novel (Extract Assets & Split Chapters)
        # Using new pipeline
        analysis_result_dict = await script_service.run_full_initialization(
            novel_text=novel_text,
            project_id=project_id,
            style_id=style,
            title=name
        )
        
        from src.models.schemas import ScriptResponse
        valid_keys = ScriptResponse.model_fields.keys()
        filtered_data = {k: v for k, v in analysis_result_dict.items() if k in valid_keys}
        analysis_result = ScriptResponse(**filtered_data)
        
        # 3. Construct Assets List
        assets_list = []
        
        for char in analysis_result.characters:
            assets_list.append({
                "id": str(uuid.uuid4()),
                "type": "character",
                "name": char.get("name"),
                "desc": char.get("desc"),
                "content": char
            })
            
        for scene in analysis_result.scenes:
            assets_list.append({
                "id": str(uuid.uuid4()),
                "type": "scene",
                "name": scene.get("name"),
                "desc": scene.get("desc"),
                "content": scene
            })
            
        for prop in analysis_result.props:
            assets_list.append({
                "id": str(uuid.uuid4()),
                "type": "prop",
                "name": prop.get("name"),
                "desc": prop.get("desc"),
                "content": prop
            })
            
        # 4. Construct Episodes (Chapters)
        episodes_list = []
        for chapter in analysis_result.chapters:
            episodes_list.append({
                "title": chapter.get("title"),
                "desc": f"Word count: {chapter.get('word_count')}",
                "content": chapter.get("content"),
                "status": "draft"
            })
            
        # 5. Update Project with Assets
        project_manager.update_project(project_id, {"assets": assets_list})
        
        # 6. Add Episodes
        created_episodes = []
        for idx, ep_data in enumerate(episodes_list):
            new_ep = Episode(
                id=str(uuid.uuid4()),
                title=ep_data["title"],
                order=idx + 1,
                desc=ep_data["desc"],
                content=ep_data["content"],
                status="draft"
            )
            project_manager.add_episode(project_id, new_ep)
            created_episodes.append(new_ep.id)
            
        return ToolResponse(content=[TextBlock(
            type="text", 
            text=f"Project '{name}' created successfully (ID: {project_id}). "
                 f"Extracted {len(assets_list)} assets and {len(created_episodes)} chapters."
        )])

    except Exception as e:
        logger.error(f"Tool create_project_from_novel error: {e}")
        return ToolResponse(content=[TextBlock(
            type="text", 
            text=f"Error creating project from novel: {str(e)}"
        )])


async def extract_assets(novel_text: str) -> ToolResponse:
    """ 提取 characters, scenes, and props from a novel text segment.
    
    This is a lighter-weight tool compared to create_project_from_novel,
    useful when you only need to analyze text without creating a project.
    
    Args:
        novel_text: The text to analyze for asset extraction.
    
    Returns:
        ToolResponse with JSON containing:
        - characters: List of character descriptions
        - scenes: List of scene descriptions  
        - props: List of prop/item descriptions
    """
    from src.services.script import ScriptService
    script_service = ScriptService()
    
    try:
        # Use parallel extraction for efficiency
        chars_task = script_service.extract_characters(novel_text)
        scenes_task = script_service.extract_scenes(novel_text)
        props_task = script_service.extract_props(novel_text)
        
        chars, scenes, props = await asyncio.gather(chars_task, scenes_task, props_task)
        
        result = {
            "characters": chars.get("characters", []),
            "scenes": scenes.get("scenes", []),
            "props": props.get("props", [])
        }
        
        return ToolResponse(content=[TextBlock(
            type="text", 
            text=json.dumps(result, indent=2, ensure_ascii=False)
        )])
    except Exception as e:
        logger.error(f"Tool extract_assets error: {e}")
        return ToolResponse(content=[TextBlock(
            type="text", 
            text=f"Error extracting assets: {str(e)}"
        )])


def split_text_into_chapters(novel_text: str) -> ToolResponse:
    """
    Split a long novel text into chapters based on headings and structure.
    
    Args:
        novel_text: The full novel text to split.
    
    Returns:
        ToolResponse with JSON containing list of chapters, each with:
        - title: Chapter title
        - word_count: Number of words in the chapter
    """
    from src.services.script import ScriptService
    script_service = ScriptService()
    
    try:
        chapters = script_service.split_chapters(novel_text)
        summary = [
            {"title": c["title"], "word_count": c["word_count"]} 
            for c in chapters
        ]
        return ToolResponse(content=[TextBlock(
            type="text", 
            text=json.dumps(summary, indent=2, ensure_ascii=False)
        )])
    except Exception as e:
        logger.error(f"Tool split_text_into_chapters error: {e}")
        return ToolResponse(content=[TextBlock(
            type="text", 
            text=f"Error splitting chapters: {str(e)}"
        )])
