"""Tests for ND0203: unexpected parameters on zero-property nodes."""

import json
from pathlib import Path

import pytest

from fixtures import workflows_dir
from valn8n_lib.rules import get_rules
from valn8n_lib.rules.nd_0203 import check_unexpected_params
from valn8n_lib.validator import validate_workflow

BROKENZIE_DIR = workflows_dir() / "test_brokenzie619"


class TestNoOpWithParams:
    """noOp nodes with parameters should emit ND0203."""

    def test_noop_with_params_emits_per_key(self, tmp_path: Path) -> None:
        workflow = {
            "nodes": [
                {
                    "parameters": {"text": "hello", "options": {}},
                    "id": "1",
                    "name": "BadNoOp",
                    "type": "n8n-nodes-base.noOp",
                    "typeVersion": 1,
                    "position": [0, 0],
                }
            ]
        }
        path = tmp_path / "noop.json"
        path.write_text(json.dumps(workflow))
        diags = check_unexpected_params(workflow, path)
        assert len(diags) == 2
        assert all(d.code.code == "ND0203" for d in diags)
        keys = {d.message.split('"')[1] for d in diags}
        assert keys == {"text", "options"}


class TestNoOpEmpty:
    """noOp nodes without parameters should not emit ND0203."""

    def test_noop_empty_params(self, tmp_path: Path) -> None:
        workflow = {
            "nodes": [
                {
                    "parameters": {},
                    "id": "1",
                    "name": "GoodNoOp",
                    "type": "n8n-nodes-base.noOp",
                    "typeVersion": 1,
                    "position": [0, 0],
                }
            ]
        }
        path = tmp_path / "noop_empty.json"
        path.write_text(json.dumps(workflow))
        diags = check_unexpected_params(workflow, path)
        assert len(diags) == 0

    def test_noop_missing_params(self, tmp_path: Path) -> None:
        workflow = {
            "nodes": [
                {
                    "id": "1",
                    "name": "NoParamsKey",
                    "type": "n8n-nodes-base.noOp",
                    "typeVersion": 1,
                    "position": [0, 0],
                }
            ]
        }
        path = tmp_path / "noop_missing.json"
        path.write_text(json.dumps(workflow))
        diags = check_unexpected_params(workflow, path)
        assert len(diags) == 0


class TestIncompleteCatalogSkipped:
    """Nodes with incomplete catalog entries should be skipped."""

    def test_http_request_skipped(self, tmp_path: Path) -> None:
        workflow = {
            "nodes": [
                {
                    "parameters": {"url": "https://example.com", "method": "GET"},
                    "id": "1",
                    "name": "HTTP",
                    "type": "n8n-nodes-base.httpRequest",
                    "typeVersion": 4,
                    "position": [0, 0],
                }
            ]
        }
        path = tmp_path / "http.json"
        path.write_text(json.dumps(workflow))
        diags = check_unexpected_params(workflow, path)
        assert len(diags) == 0


class TestRegularNodeSkipped:
    """Nodes with defined properties should not trigger ND0203."""

    def test_if_node_not_flagged(self, tmp_path: Path) -> None:
        workflow = {
            "nodes": [
                {
                    "parameters": {"conditions": {"options": {"caseSensitive": True}}},
                    "id": "1",
                    "name": "IfNode",
                    "type": "n8n-nodes-base.if",
                    "typeVersion": 2,
                    "position": [0, 0],
                }
            ]
        }
        path = tmp_path / "if_node.json"
        path.write_text(json.dumps(workflow))
        diags = check_unexpected_params(workflow, path)
        assert len(diags) == 0


class TestUnknownNodeSkipped:
    """Community/unknown nodes not in catalog should be skipped."""

    def test_community_node_skipped(self, tmp_path: Path) -> None:
        workflow = {
            "nodes": [
                {
                    "parameters": {"foo": "bar"},
                    "id": "1",
                    "name": "CommunityNode",
                    "type": "n8n-nodes-community.customThing",
                    "typeVersion": 1,
                    "position": [0, 0],
                }
            ]
        }
        path = tmp_path / "community.json"
        path.write_text(json.dumps(workflow))
        diags = check_unexpected_params(workflow, path)
        assert len(diags) == 0


class TestBrokenzieFixtures:
    """Integration tests with real fixture files."""

    def test_corrupted_workflow_19_diagnostics(self) -> None:
        path = BROKENZIE_DIR / "1521_Whatsapp_Stickynote_Automation_Webhook.json"
        if not path.exists():
            pytest.skip("fixture not available")
        diagnostics = validate_workflow(path, rules=get_rules())
        nd0009 = [d for d in diagnostics if d.code.code == "ND0203"]
        assert len(nd0009) == 19

    def test_clean_workflow_no_nd0009(self) -> None:
        path = (
            BROKENZIE_DIR
            / "3859-ai-customer-support-assistant-whatsapp-ready-works-for-any-business.json"
        )
        if not path.exists():
            pytest.skip("fixture not available")
        diagnostics = validate_workflow(path, rules=get_rules())
        nd0009 = [d for d in diagnostics if d.code.code == "ND0203"]
        assert len(nd0009) == 0
