#!/usr/bin/env python3
"""
EXPORT Executor
Company: eXonware.com
Author: eXonware Backend Team
Email: connect@exonware.com
Version: 0.9.0.6
"""

from typing import Any, Optional
from ..base import AUniversalOperationExecutor
from ....contracts import QueryAction, ExecutionContext, ExecutionResult
from ....defs import OperationType
from ..utils import extract_items, extract_field_value


class ExportExecutor(AUniversalOperationExecutor):
    """EXPORT - Serialize data to target format."""
    OPERATION_NAME = "EXPORT"
    OPERATION_TYPE = OperationType.DATA_OPS
    SUPPORTED_NODE_TYPES = []

    def _do_execute(self, action: QueryAction, context: ExecutionContext) -> ExecutionResult:
        params = action.params
        result_data = self._execute_export(context.node, params, context)
        return ExecutionResult(
            success=True,
            data=result_data,
            action_type=self.OPERATION_NAME,
            metadata={"operation": self.OPERATION_NAME},
        )

    def _execute_export(self, node: Any, params: dict, context: ExecutionContext) -> dict:
        import csv
        import xml.etree.ElementTree as ET

        from exonware.xwsystem.io.serialization.formats.text import json as xw_json

        target = params.get("target")
        format_name = str(params.get("format", "json")).lower()
        options = params.get("options", {})
        items = extract_items(node)

        if not target:
            return {"items": items, "count": len(items), "error": "target is required"}

        try:
            if format_name == "json":
                with open(target, "w", encoding=options.get("encoding", "utf-8")) as handle:
                    xw_json.dump(items, handle, indent=options.get("indent", 2), ensure_ascii=False)
            elif format_name == "csv":
                fieldnames = options.get("fieldnames")
                if not fieldnames:
                    first = items[0] if items and isinstance(items[0], dict) else {}
                    fieldnames = list(first.keys())
                with open(target, "w", encoding=options.get("encoding", "utf-8"), newline="") as handle:
                    writer = csv.DictWriter(handle, fieldnames=fieldnames)
                    writer.writeheader()
                    for item in items:
                        writer.writerow(item if isinstance(item, dict) else {"value": item})
            elif format_name == "xml":
                root_name = options.get("root_name", "rows")
                row_name = options.get("row_name", "row")
                root = ET.Element(root_name)
                for item in items:
                    row = ET.SubElement(root, row_name)
                    if isinstance(item, dict):
                        for key, value in item.items():
                            cell = ET.SubElement(row, str(key))
                            cell.text = "" if value is None else str(value)
                    else:
                        cell = ET.SubElement(row, "value")
                        cell.text = str(item)
                ET.ElementTree(root).write(target, encoding=options.get("encoding", "utf-8"), xml_declaration=True)
            else:
                return {"items": items, "count": len(items), "error": f"Unsupported format: {format_name}"}
        except Exception as exc:
            return {"items": items, "count": len(items), "error": str(exc), "target": target, "format": format_name}

        return {
            "items": items,
            "count": len(items),
            "target": target,
            "format": format_name,
            "status": "exported",
        }
