import json

from smf.inspector.client import SMFInspector
from smf.inspector.printers import print_prompts, print_resources, print_section, print_tools


async def interactive_mode(inspector: SMFInspector) -> None:
    """Run interactive inspection mode."""
    await inspector.connect()

    try:
        while True:
            print("\n" + "=" * 60)
            print(" SMF Inspector - Interactive Mode")
            print("=" * 60)
            print("\nCommands:")
            print("  1. list-tools      - List all tools")
            print("  2. list-resources  - List all resources")
            print("  3. list-prompts    - List all prompts")
            print("  4. call-tool       - Call a tool")
            print("  5. read-resource   - Read a resource")
            print("  6. get-prompt      - Get a prompt")
            print("  7. info            - Show server info")
            print("  8. quit            - Exit inspector")
            print()

            command = input("Enter command: ").strip().lower()

            if command == "quit" or command == "q":
                break
            elif command == "list-tools" or command == "1":
                tools = await inspector.list_tools()
                print_tools(tools)
            elif command == "list-resources" or command == "2":
                resources = await inspector.list_resources()
                print_resources(resources)
            elif command == "list-prompts" or command == "3":
                prompts = await inspector.list_prompts()
                print_prompts(prompts)
            elif command == "call-tool" or command == "4":
                tool_name = input("Tool name: ").strip()
                
                # Get tool info to show schema
                try:
                    tools = await inspector.list_tools()
                    tool_info = next((t for t in tools if t.name == tool_name), None)
                    if tool_info:
                        print(f"\nTool: {tool_name}")
                        if tool_info.description:
                            print(f"Description: {tool_info.description}")
                        if hasattr(tool_info, "inputSchema") and tool_info.inputSchema:
                            print(f"Schema: {json.dumps(tool_info.inputSchema, indent=2)}")
                            # Try to extract parameter names
                            schema = tool_info.inputSchema
                            if isinstance(schema, dict) and "properties" in schema:
                                params = list(schema["properties"].keys())
                                if len(params) == 1:
                                    print(f"\nTip: This tool takes one parameter: '{params[0]}'")
                                    print(f"     You can enter just the value, or JSON: {{\"{params[0]}\": \"value\"}}")
                        print()
                except Exception:
                    pass  # Continue even if we can't get tool info
                
                args_str = input("Arguments (JSON, or single value if tool takes one parameter): ").strip()
                try:
                    if args_str:
                        # Try to parse as JSON first
                        try:
                            args = json.loads(args_str)
                        except json.JSONDecodeError:
                            # If JSON parsing fails, check if it's a single value
                            # and if the tool takes one parameter
                            if tool_info and hasattr(tool_info, "inputSchema"):
                                schema = tool_info.inputSchema
                                if isinstance(schema, dict) and "properties" in schema:
                                    params = list(schema["properties"].keys())
                                    if len(params) == 1:
                                        # Single parameter - use the value directly
                                        param_name = params[0]
                                        args = {param_name: args_str}
                                        print(f"Using '{param_name}' = {args_str!r}")
                                    else:
                                        raise ValueError(
                                            f"Tool requires {len(params)} parameters. "
                                            f"Please provide JSON: {json.dumps({p: 'value' for p in params}, indent=2)}"
                                        )
                                else:
                                    raise ValueError("Please provide valid JSON arguments")
                            else:
                                raise ValueError(
                                    "Invalid JSON. Please provide JSON format: "
                                    '{"param": "value"} or use --list to see tool schemas'
                                )
                    else:
                        args = {}
                    
                    result = await inspector.call_tool(tool_name, args)
                    print(f"\nResult:")
                    print(json.dumps(result, indent=2, default=str))
                except json.JSONDecodeError as e:
                    print(f"\nError parsing JSON: {e}")
                    print("Example: {\"name\": \"Alice\", \"age\": 30}")
                except ValueError as e:
                    print(f"\nError: {e}")
                except Exception as e:
                    print(f"\nError calling tool: {e}")
                    import traceback
                    traceback.print_exc()
            elif command == "read-resource" or command == "5":
                uri = input("Resource URI: ").strip()
                try:
                    result = await inspector.read_resource(uri)
                    print(f"\nResult:")
                    print(json.dumps(result, indent=2, default=str))
                except Exception as e:
                    print(f"Error: {e}")
                    import traceback
                    traceback.print_exc()
            elif command == "get-prompt" or command == "6":
                prompt_name = input("Prompt name: ").strip()
                args_str = input("Arguments (JSON, optional): ").strip()
                try:
                    args = json.loads(args_str) if args_str else {}
                    result = await inspector.get_prompt(prompt_name, args)
                    print(f"\nResult:")
                    print(json.dumps(result, indent=2, default=str))
                except Exception as e:
                    print(f"Error: {e}")
                    import traceback
                    traceback.print_exc()
            elif command == "info" or command == "7":
                tools = await inspector.list_tools()
                resources = await inspector.list_resources()
                prompts = await inspector.list_prompts()
                print_section("SERVER INFO")
                print(f"Tools: {len(tools)}")
                print(f"Resources: {len(resources)}")
                print(f"Prompts: {len(prompts)}")
            else:
                print(f"Unknown command: {command}")

    finally:
        await inspector.disconnect()


async def list_mode(inspector: SMFInspector) -> int:
    """List all components."""
    await inspector.connect()

    try:
        tools = await inspector.list_tools()
        resources = await inspector.list_resources()
        prompts = await inspector.list_prompts()

        print_tools(tools)
        print_resources(resources)
        print_prompts(prompts)

        print_section("SUMMARY")
        print(f"Total Tools: {len(tools)}")
        print(f"Total Resources: {len(resources)}")
        print(f"Total Prompts: {len(prompts)}")

    finally:
        await inspector.disconnect()
    
    return 0
