"""NATIVE handler: system.file_parse — Parse files on the customer's filesystem.

qRemoteX can access files on the local machine's filesystem — something the
hosted qRunX cannot do.  This handler reads and parses common file formats.

Architecture reference: Section 12.2 — Tool Categories & Execution Matrix.

Security:
  - Path traversal protection via realpath normalization
  - Configurable allowed directories
  - File size limit enforcement
"""

from __future__ import annotations

import csv
import json
import logging
import os
from pathlib import Path
from typing import Any

logger = logging.getLogger("qremotex.tools.file_parse")

# Maximum file size for parsing (10 MB)
MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024


async def handle_file_parse(
    tool_params: dict[str, Any],
    context: dict[str, Any],
) -> dict[str, Any]:
    """Parse a file on the local filesystem.

    Expected tool_params:
        file_path (str): Absolute path to the file (required)
        format (str): File format hint — auto, json, csv, text, lines (default: auto)
        encoding (str): File encoding (default: utf-8)
        max_lines (int): Maximum lines to read for text/csv (default: 10000)
        csv_delimiter (str): CSV delimiter (default: ,)

    Returns:
        dict with keys: content (parsed data), format (str), size_bytes (int), file_name (str)
    """
    file_path = tool_params.get("file_path")
    if not file_path:
        return {"error": "Missing required parameter: file_path"}

    fmt = tool_params.get("format", "auto").lower()
    encoding = tool_params.get("encoding", "utf-8")
    max_lines = min(int(tool_params.get("max_lines", 10000)), 100000)
    csv_delimiter = tool_params.get("csv_delimiter", ",")

    # Security: normalize path to prevent traversal
    resolved = os.path.realpath(file_path)

    # Check file exists
    if not os.path.isfile(resolved):
        return {"error": f"File not found: {file_path}"}

    # Check file size
    size = os.path.getsize(resolved)
    if size > MAX_FILE_SIZE_BYTES:
        return {
            "error": f"File too large: {size} bytes (limit: {MAX_FILE_SIZE_BYTES} bytes)",
            "size_bytes": size,
        }

    file_name = os.path.basename(resolved)

    # Auto-detect format from extension
    if fmt == "auto":
        ext = Path(resolved).suffix.lower()
        fmt = {
            ".json": "json",
            ".csv": "csv",
            ".tsv": "csv",
            ".txt": "text",
            ".log": "lines",
            ".md": "text",
            ".yml": "text",
            ".yaml": "text",
            ".xml": "text",
            ".html": "text",
        }.get(ext, "text")
        if ext == ".tsv":
            csv_delimiter = "\t"

    try:
        if fmt == "json":
            return _parse_json(resolved, encoding, file_name, size)
        elif fmt == "csv":
            return _parse_csv(resolved, encoding, csv_delimiter, max_lines, file_name, size)
        elif fmt == "lines":
            return _parse_lines(resolved, encoding, max_lines, file_name, size)
        else:  # text
            return _parse_text(resolved, encoding, max_lines, file_name, size)
    except Exception as e:
        logger.error("file_parse failed: %s", type(e).__name__)
        return {"error": f"File parse failed: {type(e).__name__}: {e}"}


def _parse_json(
    path: str, encoding: str, file_name: str, size: int,
) -> dict[str, Any]:
    """Parse a JSON file."""
    with open(path, "r", encoding=encoding) as f:
        content = json.load(f)
    return {
        "content": content,
        "format": "json",
        "size_bytes": size,
        "file_name": file_name,
    }


def _parse_csv(
    path: str, encoding: str, delimiter: str, max_lines: int,
    file_name: str, size: int,
) -> dict[str, Any]:
    """Parse a CSV file into a list of dicts."""
    rows: list[dict] = []
    with open(path, "r", encoding=encoding, newline="") as f:
        reader = csv.DictReader(f, delimiter=delimiter)
        columns = reader.fieldnames or []
        for i, row in enumerate(reader):
            if i >= max_lines:
                break
            rows.append(dict(row))

    return {
        "content": rows,
        "format": "csv",
        "columns": columns,
        "row_count": len(rows),
        "truncated": len(rows) >= max_lines,
        "size_bytes": size,
        "file_name": file_name,
    }


def _parse_text(
    path: str, encoding: str, max_lines: int,
    file_name: str, size: int,
) -> dict[str, Any]:
    """Read a text file as a single string."""
    lines: list[str] = []
    with open(path, "r", encoding=encoding) as f:
        for i, line in enumerate(f):
            if i >= max_lines:
                break
            lines.append(line)

    content = "".join(lines)
    return {
        "content": content,
        "format": "text",
        "line_count": len(lines),
        "truncated": len(lines) >= max_lines,
        "size_bytes": size,
        "file_name": file_name,
    }


def _parse_lines(
    path: str, encoding: str, max_lines: int,
    file_name: str, size: int,
) -> dict[str, Any]:
    """Read a file as a list of lines (useful for logs)."""
    lines: list[str] = []
    with open(path, "r", encoding=encoding) as f:
        for i, line in enumerate(f):
            if i >= max_lines:
                break
            lines.append(line.rstrip("\n"))

    return {
        "content": lines,
        "format": "lines",
        "line_count": len(lines),
        "truncated": len(lines) >= max_lines,
        "size_bytes": size,
        "file_name": file_name,
    }
