"""
DSS Project Tools for MCP

Base tools that Claude can use to interact with DSS projects.
All tools are project-scoped and context-aware.

Tools include:
- Project Management (create, list, get, update, delete)
- Figma Integration (setup credentials, discover files, add files)
- Token Management (sync, extract, validate, detect drift)
- Component Analysis (discover, analyze, find quick wins)
- Status & Info (project status, system health)
"""

import uuid
from typing import Dict, Any, List, Optional
from datetime import datetime
from mcp import types

from ..context.project_context import get_context_manager
from ..security import CredentialVault
from ..audit import AuditLog, AuditEventType
from storage.json_store import Projects, Components, Tokens, ActivityLog  # JSON storage
from ..handler import get_mcp_handler, MCPContext


# Tool definitions (metadata for Claude)
PROJECT_TOOLS = [
    types.Tool(
        name="dss_get_project_summary",
        description="Get comprehensive project summary including components, tokens, health, and stats",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID to query"
                },
                "include_components": {
                    "type": "boolean",
                    "description": "Include full component list (default: false)",
                    "default": False
                }
            },
            "required": ["project_id"]
        }
    ),
    types.Tool(
        name="dss_list_components",
        description="List all components in a project with their properties",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                },
                "filter_name": {
                    "type": "string",
                    "description": "Optional: Filter by component name (partial match)"
                },
                "code_generated_only": {
                    "type": "boolean",
                    "description": "Optional: Only show components with generated code",
                    "default": False
                }
            },
            "required": ["project_id"]
        }
    ),
    types.Tool(
        name="dss_get_component",
        description="Get detailed information about a specific component",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                },
                "component_name": {
                    "type": "string",
                    "description": "Component name (exact match)"
                }
            },
            "required": ["project_id", "component_name"]
        }
    ),
    types.Tool(
        name="dss_get_design_tokens",
        description="Get all design tokens (colors, typography, spacing, etc.) for a project",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                },
                "token_category": {
                    "type": "string",
                    "description": "Optional: Filter by token category (colors, typography, spacing, etc.)",
                    "enum": ["colors", "typography", "spacing", "shadows", "borders", "all"]
                }
            },
            "required": ["project_id"]
        }
    ),
    types.Tool(
        name="dss_get_project_health",
        description="Get project health score, grade, and list of issues",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                }
            },
            "required": ["project_id"]
        }
    ),
    types.Tool(
        name="dss_list_styles",
        description="List design styles (text, fill, effect, grid) from Figma",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                },
                "style_type": {
                    "type": "string",
                    "description": "Optional: Filter by style type",
                    "enum": ["TEXT", "FILL", "EFFECT", "GRID", "all"]
                }
            },
            "required": ["project_id"]
        }
    ),
    types.Tool(
        name="dss_get_discovery_data",
        description="Get project discovery/scan data (file counts, technologies detected, etc.)",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                }
            },
            "required": ["project_id"]
        }
    ),
    # === Project Management Tools ===
    types.Tool(
        name="dss_create_project",
        description="Create a new design system project",
        inputSchema={
            "type": "object",
            "properties": {
                "name": {
                    "type": "string",
                    "description": "Project name"
                },
                "description": {
                    "type": "string",
                    "description": "Project description"
                },
                "root_path": {
                    "type": "string",
                    "description": "Root directory path for the project. Can be a git URL or a local folder path."
                }
            },
            "required": ["name", "root_path"]
        }
    ),
    types.Tool(
        name="dss_list_projects",
        description="List all design system projects",
        inputSchema={
            "type": "object",
            "properties": {
                "filter_status": {
                    "type": "string",
                    "description": "Optional: Filter by project status (active, archived)",
                    "enum": ["active", "archived", "all"]
                }
            }
        }
    ),
    types.Tool(
        name="dss_get_project",
        description="Get detailed information about a specific project",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                }
            },
            "required": ["project_id"]
        }
    ),
    types.Tool(
        name="dss_update_project",
        description="Update project settings and metadata",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID to update"
                },
                "updates": {
                    "type": "object",
                    "description": "Fields to update (name, description, etc.)"
                }
            },
            "required": ["project_id", "updates"]
        }
    ),
    types.Tool(
        name="dss_delete_project",
        description="Delete a design system project and all its data",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID to delete"
                },
                "confirm": {
                    "type": "boolean",
                    "description": "Confirmation to delete (must be true)"
                }
            },
            "required": ["project_id", "confirm"]
        }
    ),
    # === Figma Integration Tools ===
    types.Tool(
        name="dss_setup_figma_credentials",
        description="Setup Figma API credentials for a project",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                },
                "api_token": {
                    "type": "string",
                    "description": "Figma API token"
                }
            },
            "required": ["project_id", "api_token"]
        }
    ),
    types.Tool(
        name="dss_discover_figma_files",
        description="Discover Figma files accessible with current credentials",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                }
            },
            "required": ["project_id"]
        }
    ),
    types.Tool(
        name="dss_add_figma_file",
        description="Add a Figma file to a project for syncing",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                },
                "file_key": {
                    "type": "string",
                    "description": "Figma file key"
                },
                "file_name": {
                    "type": "string",
                    "description": "Display name for the file"
                }
            },
            "required": ["project_id", "file_key", "file_name"]
        }
    ),
    types.Tool(
        name="dss_list_figma_files",
        description="List all Figma files linked to a project",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                }
            },
            "required": ["project_id"]
        }
    ),
    # === Token Management Tools ===
    types.Tool(
        name="dss_sync_tokens",
        description="Synchronize design tokens from Figma to project",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                },
                "output_format": {
                    "type": "string",
                    "description": "Output format for tokens (css, json, tailwind)",
                    "enum": ["css", "json", "tailwind", "figma-tokens"]
                }
            },
            "required": ["project_id"]
        }
    ),
    types.Tool(
        name="dss_extract_tokens",
        description="Extract design tokens from a Figma file",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                },
                "file_key": {
                    "type": "string",
                    "description": "Figma file key"
                }
            },
            "required": ["project_id", "file_key"]
        }
    ),
    types.Tool(
        name="dss_validate_tokens",
        description="Validate design tokens for consistency and completeness",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                }
            },
            "required": ["project_id"]
        }
    ),
    types.Tool(
        name="dss_detect_token_drift",
        description="Detect inconsistencies between Figma and project tokens",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                }
            },
            "required": ["project_id"]
        }
    ),
    # === Component Analysis Tools ===
    types.Tool(
        name="dss_discover_components",
        description="Discover components in project codebase",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                },
                "path": {
                    "type": "string",
                    "description": "Optional: Specific path to scan"
                }
            },
            "required": ["project_id"]
        }
    ),
    types.Tool(
        name="dss_analyze_components",
        description="Analyze components for design system alignment and quality",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                }
            },
            "required": ["project_id"]
        }
    ),
    types.Tool(
        name="dss_get_quick_wins",
        description="Identify quick wins for improving design system consistency",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                },
                "path": {
                    "type": "string",
                    "description": "Optional: Specific path to analyze"
                }
            },
            "required": ["project_id"]
        }
    ),
    # === Status & Info Tools ===
    types.Tool(
        name="dss_get_project_status",
        description="Get current project status and progress",
        inputSchema={
            "type": "object",
            "properties": {
                "project_id": {
                    "type": "string",
                    "description": "Project ID"
                }
            },
            "required": ["project_id"]
        }
    ),
    types.Tool(
        name="dss_get_system_health",
        description="Get overall system health and statistics",
        inputSchema={
            "type": "object",
            "properties": {}
        }
    )
]


# Tool implementations
class ProjectTools:
    """Project tool implementations"""

    def __init__(self, user_id: Optional[int] = None):
        self.context_manager = get_context_manager()
        self.user_id = user_id
        self.projects_db = Projects()

    async def execute_tool(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
        """Execute a tool by name"""
        handlers = {
            # Project Management
            "dss_create_project": self.create_project,
            "dss_list_projects": self.list_projects,
            "dss_get_project": self.get_project,
            # Read-only tools
            "dss_get_project_summary": self.get_project_summary,
            "dss_list_components": self.list_components,
            "dss_get_component": self.get_component,
            "dss_get_design_tokens": self.get_design_tokens,
            "dss_get_project_health": self.get_project_health,
            "dss_list_styles": self.list_styles,
            "dss_get_discovery_.dat": self.get_discovery_data
        }

        handler = handlers.get(tool_name)
        if not handler:
            return {"error": f"Unknown or not implemented tool: {tool_name}"}

        try:
            result = await handler(**arguments)
            return result
        except Exception as e:
            return {"error": str(e)}

    async def create_project(self, name: str, root_path: str, description: str = "") -> Dict[str, Any]:
        """Create a new project and trigger initial analysis."""
        project_id = str(uuid.uuid4())
        
        # The `create` method in json_store handles the creation of the manifest
        self.projects_db.create(
            id=project_id,
            name=name,
            description=description
        )
        
        # We may still want to update the root_path if it's not part of the manifest
        self.projects_db.update(project_id, root_path=root_path)


        # Trigger the analysis as a background task
        # We don't want to block the creation call
        mcp_handler = get_mcp_handler()
        
        # Create a context for the tool call
        # The user_id might be important for permissions later
        mcp_context = MCPContext(project_id=project_id, user_id=self.user_id)

        # It's better to run this in the background and not wait for the result here
        asyncio.create_task(
            mcp_handler.execute_tool(
                tool_name="analyze_project",
                arguments={"project_path": root_path},
                context=mcp_context
            )
        )

        return {
            "status": "success",
            "message": "Project created successfully. Analysis has been started in the background.",
            "project_id": project_id
        }

    async def list_projects(self, filter_status: Optional[str] = None) -> Dict[str, Any]:
        """List all projects."""
        all_projects = self.projects_db.list(status=filter_status)
        return {"projects": all_projects}

    async def get_project(self, project_id: str) -> Dict[str, Any]:
        """Get a single project by its ID."""
        project = self.projects_db.get(project_id)
        if not project:
            return {"error": f"Project with ID '{project_id}' not found."}
        return {"project": project}

    async def get_project_summary(
        self,
        project_id: str,
        include_components: bool = False
    ) -> Dict[str, Any]:
        """Get comprehensive project summary"""
        context = await self.context_manager.get_context(project_id, self.user_id)
        if not context:
            return {"error": f"Project not found: {project_id}"}

        summary = {
            "project_id": context.project_id,
            "name": context.name,
            "description": context.description,
            "component_count": context.component_count,
            "health": context.health,
            "stats": context.stats,
            "config": context.config,
            "integrations_enabled": list(context.integrations.keys()),
            "loaded_at": context.loaded_at.isoformat()
        }

        if include_components:
            summary["components"] = context.components

        return summary

    async def list_components(
        self,
        project_id: str,
        filter_name: Optional[str] = None,
        code_generated_only: bool = False
    ) -> Dict[str, Any]:
        """List components with optional filtering"""
        context = await self.context_manager.get_context(project_id, self.user_id)
        if not context:
            return {"error": f"Project not found: {project_id}"}

        components = context.components

        # Apply filters
        if filter_name:
            components = [
                c for c in components
                if filter_name.lower() in c['name'].lower()
            ]

        if code_generated_only:
            components = [c for c in components if c.get('code_generated')]

        return {
            "project_id": project_id,
            "total_count": len(components),
            "components": components
        }

    async def get_component(
        self,
        project_id: str,
        component_name: str
    ) -> Dict[str, Any]:
        """Get detailed component information"""
        context = await self.context_manager.get_context(project_id, self.user_id)
        if not context:
            return {"error": f"Project not found: {project_id}"}

        # Find component by name
        component = next(
            (c for c in context.components if c['name'] == component_name),
            None
        )

        if not component:
            return {"error": f"Component not found: {component_name}"}

        return {
            "project_id": project_id,
            "component": component
        }

    async def get_design_tokens(
        self,
        project_id: str,
        token_category: Optional[str] = None
    ) -> Dict[str, Any]:
        """Get design tokens, optionally filtered by category"""
        context = await self.context_manager.get_context(project_id, self.user_id)
        if not context:
            return {"error": f"Project not found: {project_id}"}

        tokens = context.tokens

        if token_category and token_category != "all":
            # Filter by category
            if token_category in tokens:
                tokens = {token_category: tokens[token_category]}
            else:
                tokens = {}

        return {
            "project_id": project_id,
            "tokens": tokens,
            "categories": list(tokens.keys())
        }

    async def get_project_health(self, project_id: str) -> Dict[str, Any]:
        """Get project health information"""
        context = await self.context_manager.get_context(project_id, self.user_id)
        if not context:
            return {"error": f"Project not found: {project_id}"}

        return {
            "project_id": project_id,
            "health": context.health
        }

    async def list_styles(
        self,
        project_id: str,
        style_type: Optional[str] = None
    ) -> Dict[str, Any]:
        """List design styles with optional type filter"""
        context = await self.context_manager.get_context(project_id, self.user_id)
        if not context:
            return {"error": f"Project not found: {project_id}"}

        styles = context.styles

        if style_type and style_type != "all":
            styles = [s for s in styles if s['type'] == style_type]

        return {
            "project_id": project_id,
            "total_count": len(styles),
            "styles": styles
        }

    async def get_discovery_data(self, project_id: str) -> Dict[str, Any]:
        """Get project discovery/scan data"""
        context = await self.context_manager.get_context(project_id, self.user_id)
        if not context:
            return {"error": f"Project not found: {project_id}"}

        return {
            "project_id": project_id,
            "discovery": context.discovery
        }
