# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Configuration file reader tool for existing YAML configs."""

from pathlib import Path
from typing import Any
from typing import Dict
from typing import List

import yaml

from .read_files import read_files


async def read_config_files(file_paths: List[str]) -> Dict[str, Any]:
  """Read multiple YAML configuration files and extract metadata.

  Args:
    file_paths: List of absolute or relative paths to YAML configuration files

  Returns:
    Dict containing:
      - success: bool indicating if all files were processed
      - total_files: number of files requested
      - successful_reads: number of files read successfully
      - files: dict mapping file_path to file analysis:
        - success: bool for this specific file
        - file_path: absolute path to the file
        - file_size: size of file in characters
        - line_count: number of lines in file
        - content: parsed YAML content as dict (success only)
        - agent_info: extracted agent metadata (success only)
        - sub_agents: list of referenced sub-agent files (success only)
        - tools: list of tools used by the agent (success only)
        - error: error message (failure only)
        - raw_yaml: original YAML string (parsing errors only)
      - errors: list of general error messages
  """
  # Read all files using the file_manager read_files tool
  read_result = await read_files(file_paths)

  result = {
      "success": True,
      "total_files": len(file_paths),
      "successful_reads": 0,
      "files": {},
      "errors": [],
  }

  for file_path, file_info in read_result["files"].items():
    file_analysis = {
        "success": False,
        "file_path": file_path,
        "file_size": file_info.get("file_size", 0),
        "line_count": 0,
        "error": None,
    }

    # Check if file was read successfully
    if file_info.get("error"):
      file_analysis["error"] = file_info["error"]
      result["files"][file_path] = file_analysis
      result["success"] = False
      continue

    # Check if it's a YAML file
    path = Path(file_path)
    if path.suffix.lower() not in [".yaml", ".yml"]:
      file_analysis["error"] = f"File is not a YAML file: {file_path}"
      result["files"][file_path] = file_analysis
      result["success"] = False
      continue

    raw_yaml = file_info.get("content", "")
    file_analysis["line_count"] = len(raw_yaml.split("\n"))

    # Parse YAML
    try:
      content = yaml.safe_load(raw_yaml)
    except yaml.YAMLError as e:
      file_analysis["error"] = f"Invalid YAML syntax: {str(e)}"
      file_analysis["raw_yaml"] = raw_yaml
      result["files"][file_path] = file_analysis
      result["success"] = False
      continue

    if not isinstance(content, dict):
      file_analysis["error"] = "YAML content is not a valid object/dictionary"
      file_analysis["raw_yaml"] = raw_yaml
      result["files"][file_path] = file_analysis
      result["success"] = False
      continue

    # Extract agent metadata
    try:
      agent_info = _extract_agent_info(content)
      sub_agents = _extract_sub_agents(content)
      tools = _extract_tools(content)

      file_analysis.update({
          "success": True,
          "content": content,
          "agent_info": agent_info,
          "sub_agents": sub_agents,
          "tools": tools,
      })

      result["successful_reads"] += 1

    except Exception as e:
      file_analysis["error"] = f"Error extracting metadata: {str(e)}"
      result["success"] = False

    result["files"][file_path] = file_analysis

  return result


# Legacy functions removed - use read_config_files directly


def _extract_agent_info(content: Dict[str, Any]) -> Dict[str, Any]:
  """Extract basic agent information from configuration."""
  return {
      "name": content.get("name", "unknown"),
      "agent_class": content.get("agent_class", "LlmAgent"),
      "description": content.get("description", ""),
      "model": content.get("model", ""),
      "has_instruction": bool(content.get("instruction", "").strip()),
      "instruction_length": len(content.get("instruction", "")),
      "has_memory": bool(content.get("memory")),
      "has_state": bool(content.get("state")),
  }


def _extract_sub_agents(content: Dict[str, Any]) -> list:
  """Extract sub-agent references from configuration."""
  sub_agents = content.get("sub_agents", [])

  if not isinstance(sub_agents, list):
    return []

  extracted = []
  for sub_agent in sub_agents:
    if isinstance(sub_agent, dict):
      agent_ref = {
          "config_path": sub_agent.get("config_path", ""),
          "code": sub_agent.get("code", ""),
          "type": "config_path" if "config_path" in sub_agent else "code",
      }

      # Check if referenced file exists (for config_path refs)
      if agent_ref["config_path"]:
        agent_ref["file_exists"] = _check_file_exists(agent_ref["config_path"])

      extracted.append(agent_ref)
    elif isinstance(sub_agent, str):
      # Simple string reference
      extracted.append({
          "config_path": sub_agent,
          "code": "",
          "type": "config_path",
          "file_exists": _check_file_exists(sub_agent),
      })

  return extracted


def _extract_tools(content: Dict[str, Any]) -> list:
  """Extract tool information from configuration."""
  tools = content.get("tools", [])

  if not isinstance(tools, list):
    return []

  extracted = []
  for tool in tools:
    if isinstance(tool, dict):
      tool_info = {
          "name": tool.get("name", ""),
          "type": "object",
          "has_args": bool(tool.get("args")),
          "args_count": len(tool.get("args", [])),
          "raw": tool,
      }
    elif isinstance(tool, str):
      tool_info = {
          "name": tool,
          "type": "string",
          "has_args": False,
          "args_count": 0,
          "raw": tool,
      }
    else:
      continue

    extracted.append(tool_info)

  return extracted


def _check_file_exists(config_path: str) -> bool:
  """Check if a configuration file path exists."""
  try:
    if not config_path:
      return False

    path = Path(config_path)

    # If it's not absolute, check relative to current working directory
    if not path.is_absolute():
      # Try relative to current directory
      current_dir_path = Path.cwd() / config_path
      if current_dir_path.exists():
        return True

      # Try common agent directory patterns
      for potential_dir in [".", "./agents", "../agents"]:
        potential_path = Path(potential_dir) / config_path
        if potential_path.exists():
          return True

    return path.exists()

  except (OSError, ValueError):
    return False
