"""
Example Custom Nodes: File Processing

This file contains multiple node classes - each becomes a separate node in Plumber.
Demonstrates: file I/O, JSON parsing, text transformations.

HOW TO USE:
1. Copy this file to: ~/plumber/custom_nodes/
2. The agent will auto-detect it within 2 seconds
3. Three nodes appear in Plumber's TabMenu

AVAILABLE CLASSES (no imports needed):
- Node, Property, Input, Output, ExecutionContext

YOU CAN IMPORT STANDARD LIBRARIES:
- os, json, pathlib, etc. work normally
"""

import json
from pathlib import Path


# ═══════════════════════════════════════════════════════════════════════════════
# NODE 1: File Reader
# ═══════════════════════════════════════════════════════════════════════════════

class FileReaderNode(Node):
    """Read content from a text file."""

    _category = "File I/O"
    _icon = "FileText"
    _description = "Read content from a text file"
    _color = "#3b82f6"  # Blue

    # Properties
    file_path: str = Property(
        default="",
        label="File Path",
        tooltip="Path to the file to read",
        file_filter="*.txt;*.json;*.csv"  # Shows file picker in UI
    )

    encoding: str = Property(
        default="utf-8",
        choices=["utf-8", "ascii", "latin-1"],  # Dropdown menu
        label="Encoding"
    )

    # Outputs
    content: str = Output(type=str, label="Content")
    line_count: int = Output(type=int, label="Line Count")
    success: bool = Output(type=bool, label="Success")

    def execute(self, context: ExecutionContext) -> dict:
        context.report_progress(0.0, "Reading file...")

        if not self.file_path:
            context.log_error("No file path specified")
            return {"content": "", "line_count": 0, "success": False}

        file_path = Path(self.file_path)

        if not file_path.exists():
            context.log_error(f"File not found: {file_path}")
            return {"content": "", "line_count": 0, "success": False}

        try:
            content = file_path.read_text(encoding=self.encoding)
            lines = content.split('\n')

            context.log_info(f"Read {len(lines)} lines from {file_path.name}")
            context.report_progress(1.0, "Done!")
            return {"content": content, "line_count": len(lines), "success": True}

        except Exception as e:
            context.log_error(f"Error reading file: {e}")
            return {"content": "", "line_count": 0, "success": False}


# ═══════════════════════════════════════════════════════════════════════════════
# NODE 2: JSON Parser
# ═══════════════════════════════════════════════════════════════════════════════

class JsonParserNode(Node):
    """Parse JSON string to dictionary."""

    _category = "Data"
    _icon = "Braces"
    _description = "Parse JSON string into a dictionary"
    _color = "#f59e0b"  # Amber

    # Inputs
    json_string: str = Input(
        type=str,
        required=True,
        label="JSON String"
    )

    # Outputs
    data: dict = Output(type=dict, label="Parsed Data")
    keys: list = Output(type=list, label="Keys")
    success: bool = Output(type=bool, label="Success")

    def execute(self, context: ExecutionContext) -> dict:
        context.report_progress(0.0, "Parsing JSON...")

        json_input = self.get_input("json_string")

        if not json_input:
            context.log_error("No JSON input provided")
            return {"data": {}, "keys": [], "success": False}

        try:
            data = json.loads(json_input)
            keys = list(data.keys()) if isinstance(data, dict) else []

            context.log_info(f"Parsed JSON with {len(keys)} keys")
            context.report_progress(1.0, "Done!")
            return {"data": data, "keys": keys, "success": True}

        except json.JSONDecodeError as e:
            context.log_error(f"Invalid JSON: {e}")
            return {"data": {}, "keys": [], "success": False}


# ═══════════════════════════════════════════════════════════════════════════════
# NODE 3: Text Transform
# ═══════════════════════════════════════════════════════════════════════════════

class TextTransformNode(Node):
    """Transform text with various operations."""

    _category = "Text"
    _icon = "Type"
    _description = "Apply transformations to text"
    _color = "#8b5cf6"  # Violet

    # Properties
    operation: str = Property(
        default="uppercase",
        choices=["uppercase", "lowercase", "title", "reverse", "strip"],
        label="Operation"
    )

    # Inputs
    text: str = Input(
        type=str,
        required=True,
        label="Input Text"
    )

    # Outputs
    result: str = Output(type=str, label="Result")
    char_count: int = Output(type=int, label="Character Count")

    def execute(self, context: ExecutionContext) -> dict:
        context.report_progress(0.0, f"Applying {self.operation}...")

        text = self.get_input("text") or ""

        operations = {
            "uppercase": str.upper,
            "lowercase": str.lower,
            "title": str.title,
            "reverse": lambda s: s[::-1],
            "strip": str.strip,
        }

        result = operations.get(self.operation, lambda s: s)(text)

        context.log_info(f"Transformed {len(text)} -> {len(result)} characters")
        context.report_progress(1.0, "Done!")
        return {"result": result, "char_count": len(result)}
