import unittest
from deploy_support_workflows import (
    CONFIRMATION_WORKFLOW_NAME, TOOL_SPECS, build_tool_workflow,
    patch_agent_workflow,
)


class WorkflowBuilderTests(unittest.TestCase):
    def test_all_approved_tools_exist(self):
        self.assertEqual(set(TOOL_SPECS), {
            "search_support_slots", "hold_support_slot", "attach_support_receipt",
            "cancel_support_booking", "reschedule_support_booking",
        })

    def test_tool_uses_server_token_expression(self):
        wf = build_tool_workflow("search_support_slots", "https://db.kingsandqueens.com.ar")
        request = next(node for node in wf["nodes"] if node["type"] == "n8n-nodes-base.httpRequest")
        rendered = str(request["parameters"])
        self.assertIn("KQ_TOOL_TOKEN", rendered)
        self.assertNotIn("edd_secret", rendered)

    def test_confirmation_is_webhook_not_ai_tool(self):
        self.assertEqual(CONFIRMATION_WORKFLOW_NAME, "kq-support-confirmation")


class PatchAgentTests(unittest.TestCase):
    """Patching the live agent must be additive, idempotent, and lossless."""

    def _agent(self):
        return {
            "name": "kq-chatwoot-agent",
            "active": True,
            "nodes": [
                {"id": "s7", "name": "Sam - AI Agent",
                 "type": "@n8n/n8n-nodes-langchain.agent",
                 "parameters": {"options": {"systemMessage": "BASE PROMPT"}}},
                {"id": "s10", "name": "qualify_student",
                 "type": "@n8n/n8n-nodes-langchain.toolWorkflow", "parameters": {}},
                {"id": "s11", "name": "escalate_to_ale",
                 "type": "@n8n/n8n-nodes-langchain.toolWorkflow", "parameters": {}},
                {"id": "web", "name": "Chatwoot Webhook",
                 "type": "n8n-nodes-base.webhook", "parameters": {"path": "kq-chatwoot"}},
            ],
            "connections": {
                "qualify_student": {"ai_tool": [[{"node": "Sam - AI Agent", "type": "ai_tool", "index": 0}]]},
                "escalate_to_ale": {"ai_tool": [[{"node": "Sam - AI Agent", "type": "ai_tool", "index": 1}]]},
            },
        }

    def test_patch_is_additive_and_indexes_continue(self):
        tool_ids = {name: f"id_{name}" for name in TOOL_SPECS}
        patched = patch_agent_workflow(self._agent(), tool_ids)
        names = [n["name"] for n in patched["nodes"]]
        # Existing nodes preserved.
        for keep in ("Sam - AI Agent", "qualify_student", "escalate_to_ale", "Chatwoot Webhook"):
            self.assertIn(keep, names)
        # All five support tools added.
        for tool in TOOL_SPECS:
            self.assertIn(tool, names)
        # ai_tool indices continue from the existing max (1) without renumbering.
        indices = sorted(
            patched["connections"][t]["ai_tool"][0][0]["index"] for t in TOOL_SPECS
        )
        self.assertEqual(indices, [2, 3, 4, 5, 6])
        self.assertEqual(patched["connections"]["qualify_student"]["ai_tool"][0][0]["index"], 0)
        # Prompt block appended once with markers.
        prompt = next(n for n in patched["nodes"] if n["name"] == "Sam - AI Agent")["parameters"]["options"]["systemMessage"]
        self.assertEqual(prompt.count("## KQ_SUPPORT_START"), 1)
        self.assertIn("BASE PROMPT", prompt)
        self.assertTrue(patched["active"])

    def test_patch_is_idempotent(self):
        tool_ids = {name: f"id_{name}" for name in TOOL_SPECS}
        once = patch_agent_workflow(self._agent(), tool_ids)
        twice = patch_agent_workflow(once, tool_ids)
        names = [n["name"] for n in twice["nodes"]]
        for tool in TOOL_SPECS:
            self.assertEqual(names.count(tool), 1)
        prompt = next(n for n in twice["nodes"] if n["name"] == "Sam - AI Agent")["parameters"]["options"]["systemMessage"]
        self.assertEqual(prompt.count("## KQ_SUPPORT_START"), 1)


if __name__ == "__main__":
    unittest.main()
