"""Tests for godotiq_file_context tool."""

from __future__ import annotations

from godotiq.session import GodotIQSession
from godotiq.tools.memory import _build_file_context


class TestFileContextGdScript:
    def test_context_gd_file(self, session: GodotIQSession) -> None:
        """Basic .gd file returns expected structure."""
        result = _build_file_context(session, "res://scripts/autoloads/economy_manager.gd")
        assert result["type"] == "gdscript"
        assert result["class_name"] == "EconomyManagerClass"
        assert result["extends"] == "Node"
        assert "public_api" in result

    def test_context_gd_autoload(self, session: GodotIQSession) -> None:
        """Autoload script is correctly identified."""
        result = _build_file_context(session, "res://scripts/autoloads/economy_manager.gd")
        assert result["is_autoload"] is True

    def test_context_gd_non_autoload(self, session: GodotIQSession) -> None:
        """Non-autoload script is correctly identified."""
        result = _build_file_context(session, "res://scripts/entities/worker.gd")
        assert result["is_autoload"] is False

    def test_context_gd_dependencies(self, session: GodotIQSession) -> None:
        """Dependencies are correctly listed."""
        result = _build_file_context(session, "res://scripts/autoloads/progression_manager.gd")
        assert "depends_on" in result
        assert "GameManager" in result["depends_on"]["autoloads"]
        assert "EconomyManager" in result["depends_on"]["autoloads"]

    def test_context_gd_signals(self, session: GodotIQSession) -> None:
        """Signals are listed."""
        result = _build_file_context(session, "res://scripts/autoloads/economy_manager.gd")
        assert "cash_changed" in result["signals_defined"]
        assert "cash_changed" in result["signals_emitted"]

    def test_context_gd_public_api(self, session: GodotIQSession) -> None:
        """Public API lists non-private functions."""
        result = _build_file_context(session, "res://scripts/autoloads/economy_manager.gd")
        func_names = [f["name"] for f in result["public_api"]["functions"]]
        assert "add_cash" in func_names
        assert "spend_cash" in func_names
        # Private functions should not appear
        assert "_ready" not in func_names

    def test_context_gd_safety(self, session: GodotIQSession) -> None:
        """Safety fields are populated correctly."""
        result = _build_file_context(session, "res://scripts/autoloads/economy_manager.gd")
        assert "safety" in result
        assert isinstance(result["safety"]["is_instance_valid_count"], int)
        assert result["safety"]["has_serialize"] is True

    def test_context_gd_depended_by(self, session: GodotIQSession) -> None:
        """Autoload depended_by lists scripts that reference it."""
        # GameManager is referenced by progression_manager.gd
        result = _build_file_context(session, "res://scripts/entities/printer.gd")
        # printer.gd is registered as GameManager autoload
        assert result["is_autoload"] is True
        # progression_manager references GameManager
        assert "res://scripts/autoloads/progression_manager.gd" in result["depended_by"]


class TestFileContextTscnScene:
    def test_context_tscn_file(self, session: GodotIQSession) -> None:
        """Basic .tscn file returns expected structure."""
        result = _build_file_context(session, "res://scenes/equipment/fdm_printer.tscn")
        assert result["type"] == "scene"
        assert result["root_type"] == "Node3D"
        assert result["total_nodes"] >= 4

    def test_context_tscn_scripts(self, session: GodotIQSession) -> None:
        """Scene lists attached scripts."""
        result = _build_file_context(session, "res://scenes/equipment/fdm_printer.tscn")
        assert "res://scripts/entities/printer.gd" in result["scripts_used"]

    def test_context_tscn_instances(self, session: GodotIQSession) -> None:
        """Scene lists instanced sub-scenes."""
        result = _build_file_context(session, "res://scenes/main.tscn")
        assert "res://scenes/equipment/fdm_printer.tscn" in result["instances"]

    def test_context_tscn_groups(self, session: GodotIQSession) -> None:
        """Scene lists groups used by nodes."""
        result = _build_file_context(session, "res://scenes/equipment/fdm_printer.tscn")
        assert "interactable" in result["groups_used"]

    def test_context_tscn_instanced_by(self, session: GodotIQSession) -> None:
        """Scene lists scenes that instance it."""
        result = _build_file_context(session, "res://scenes/equipment/fdm_printer.tscn")
        assert "res://scenes/main.tscn" in result["instanced_by"]


class TestFileContextPathHandling:
    def test_context_res_path(self, session: GodotIQSession) -> None:
        """Accepts res:// paths."""
        result = _build_file_context(session, "res://scripts/autoloads/economy_manager.gd")
        assert "error" not in result

    def test_context_relative_path(self, session: GodotIQSession) -> None:
        """Accepts relative paths from project root."""
        result = _build_file_context(session, "scripts/autoloads/economy_manager.gd")
        assert "error" not in result
        assert result["file"].startswith("res://")

    def test_context_missing_file(self, session: GodotIQSession) -> None:
        """Returns error dict for missing files."""
        result = _build_file_context(session, "res://nonexistent.gd")
        assert "error" in result
