import logging
import json
from typing import Optional, List, Dict, Any
from src.services.project_service import project_manager
from src.models.schemas import ProjectData

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

logger = logging.getLogger(__name__)

def list_projects() -> ToolResponse:
    """ 列表 all projects in the system.
    Returns a summary of projects including ID, name, and type.
    """
    try:
        projects = project_manager.list_projects()
        # Simplify output for LLM
        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.
    """
    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()
        # Simplify large objects if necessary, or just dump all
        # 转换ing datetime objects to string for JSON serialization
        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 project.
    
    Args:
        name: The name of the project.
        description: A brief description of the project.
        type: The type of project. Defaults to 'video'.
    """
    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)}")])


import asyncio
import uuid

# script_service = ScriptService()

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 includes creating the project, extracting assets (characters, scenes), splitting chapters, and saving everything.
    
    Args:
        name: Project name.
        novel_text: The full text of the novel or script.
        description: Project description.
        type: Project type (default: video).
        style: Visual style (e.g., "anime", "realistic", "cinematic").
    """
    from src.services.script import script_service
    
    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
        )
        
        # Use dict directly to preserve all fields and avoid Pydantic attribute access issues
        analysis_result = analysis_result_dict
        
        # 3. Construct Assets List
        assets_list = []
        
        for char in analysis_result.get("characters", []):
            assets_list.append({
                "id": str(uuid.uuid4()),
                "type": "character",
                "name": char.get("name"),
                "desc": char.get("desc") or char.get("description"),
                "content": char # Store full details
            })
            
        for scene in analysis_result.get("scenes", []):
            assets_list.append({
                "id": str(uuid.uuid4()),
                "type": "scene",
                "name": scene.get("name"),
                "desc": scene.get("desc") or scene.get("description"),
                "content": scene
            })
            
        for prop in analysis_result.get("props", []):
            assets_list.append({
                "id": str(uuid.uuid4()),
                "type": "prop",
                "name": prop.get("name"),
                "desc": prop.get("desc") or prop.get("description"),
                "content": prop
            })
            
        # 4. Construct Episodes (Chapters)
        episodes_list = []
        for chapter in analysis_result.get("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 and Episodes
        # Let's try to update assets first
        project_manager.update_project(project_id, {"assets": assets_list})
        
        # For episodes, we might need to add them one by one or if update_project supports it.
        # Safe bet: generate episodes and add them.
        
        from src.models.schemas import Episode
        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}). 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.
    
    Args:
        novel_text: The text to analyze.
    """
    from src.services.script import script_service
    try:
        # Use parallel extraction from script_service
        # We can reuse extract_characters, extract_scenes directly
        # Or use analyze_novel for full package.
        # Let's use individual methods for lighter weight tool
        
        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.
    
    Args:
        novel_text: The full novel text.
    """
    from src.services.script.utils import split_chapters
    try:
        chapters = 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)}")])
