from __future__ import annotations

from fastapi import FastAPI
from fastapi.testclient import TestClient

from src.api.v1.iwooos import router
from src.services.iwooos_wazuh_manager_registry_reviewer_validation import (
    load_latest_iwooos_wazuh_manager_registry_reviewer_validation,
    validate_iwooos_wazuh_manager_registry_acceptance_evidence,
    validate_iwooos_wazuh_manager_registry_owner_export,
)


EXPECTED_ALIASES = [
    "managed_core_node_a",
    "managed_core_node_b",
    "managed_dev_node_a",
    "managed_dev_node_b",
    "managed_control_node_a",
    "managed_control_node_b",
]


def _client() -> TestClient:
    app = FastAPI()
    app.include_router(router)
    return TestClient(app)


def _valid_owner_export() -> dict:
    return {
        "owner_role": "資安負責人",
        "team": "IwoooS",
        "decision": "accept_readonly_registry_export_for_reviewer_validation",
        "decision_reason": "Wazuh manager registry 已脫敏，供 reviewer 驗證主機覆蓋與 Dashboard API 修復狀態。",
        "affected_scope": "iwooos_wazuh_expected_scope_aliases",
        "collection_method": "owner_export_redacted_summary",
        "agent_total": 6,
        "agent_active": 2,
        "agent_disconnected": 3,
        "agent_never_connected": 1,
        "last_seen_window_start": "2026-06-27T15:00:00+08:00",
        "last_seen_window_end": "2026-06-27T16:00:00+08:00",
        "registry_collected_at": "2026-06-27T16:05:00+08:00",
        "registry_export_scope_aliases": EXPECTED_ALIASES,
        "per_host_registry_matrix": [
            {
                "node_alias": alias,
                "scope_role": "managed_scope",
                "registry_presence": "present",
                "agent_status_bucket": "active" if index < 2 else "disconnected",
                "last_seen_state": "within_owner_window" if index < 2 else "outside_owner_window",
                "manager_group_ref": f"group-ref-{index}",
                "agent_id_redacted_ref": f"agent-redacted-ref-{index}",
                "gap_reason": "none" if index < 2 else "owner_followup_required",
                "redacted_evidence_ref": f"evidence-ref-{index}",
            }
            for index, alias in enumerate(EXPECTED_ALIASES)
        ],
        "registry_gap_reason_by_alias": {
            alias: "none" if index < 2 else "owner_followup_required"
            for index, alias in enumerate(EXPECTED_ALIASES)
        },
        "registry_export_summary_ref": "evidence-ref-registry-summary",
        "manager_health_ref": "evidence-ref-manager-health",
        "dashboard_api_status_ref": "evidence-ref-dashboard-api",
        "dashboard_api_connection_check_status": "ok",
        "dashboard_api_version_check_status": "ok",
        "dashboard_index_pattern_statuses": ["alerts_ok", "monitoring_ok", "statistics_ok"],
        "dashboard_api_degradation_root_cause": "stored_api_connection_repaired_by_owner",
        "dashboard_api_repair_postcheck_ref": "evidence-ref-dashboard-postcheck",
        "redacted_evidence_refs": [
            "evidence-ref-registry-summary",
            "evidence-ref-dashboard-postcheck",
        ],
        "followup_owner": "IwoooS reviewer",
        "rollback_owner": "IwoooS runtime owner",
        "postcheck_plan": "post_enable_iwooos_readback_no_raw_payload",
    }


def _valid_acceptance_evidence() -> dict:
    return {
        "acceptance_reviewer_role": "IwoooS reviewer",
        "acceptance_decision": "accept_manager_registry_evidence_for_review",
        "acceptance_decision_reason": "脫敏 manager registry evidence 與六個公開別名 scope parity 一致，可進 commit review。",
        "accepted_scope_aliases": EXPECTED_ALIASES,
        "accepted_agent_total": 6,
        "accepted_agent_active": 2,
        "accepted_agent_disconnected": 3,
        "accepted_agent_never_connected": 1,
        "manager_registry_acceptance_evidence_refs": [
            "evidence-ref-registry-summary",
            "evidence-ref-scope-parity",
            "evidence-ref-post-enable-readback",
        ],
        "post_enable_readback_ref": "evidence-ref-post-enable-readback",
        "product_scope_parity_ref": "evidence-ref-scope-parity",
        "reviewed_at": "2026-06-27T22:10:00+08:00",
        "followup_owner": "IwoooS reviewer",
        "rollback_owner": "IwoooS runtime owner",
        "post_acceptance_verifier_plan": "commit_readback_without_runtime_action",
    }


def test_iwooos_wazuh_manager_registry_reviewer_validation_contract_has_passed_redacted_export() -> None:
    payload = load_latest_iwooos_wazuh_manager_registry_reviewer_validation()

    assert payload["schema_version"] == "iwooos_wazuh_manager_registry_reviewer_validation_readback_v1"
    assert payload["source_schema_version"] == "wazuh_manager_registry_reviewer_validation_v1"
    assert payload["status"] == "manager_registry_accepted_readback_committed_no_runtime_no_secret_collection"
    assert payload["mode"] == "committed_manager_registry_accepted_readback_no_runtime_no_secret_collection"
    assert payload["summary"]["expected_scope_alias_count"] == 6
    assert payload["summary"]["required_owner_field_count"] == 28
    assert payload["summary"]["per_host_required_field_count"] == 9
    assert payload["summary"]["reviewer_validation_check_count"] == 11
    assert payload["summary"]["outcome_lane_count"] == 17
    assert payload["summary"]["evidence_slot_count"] == 6
    assert payload["summary"]["forbidden_payload_count"] == 27
    assert payload["summary"]["owner_registry_export_received_count"] == 1
    assert payload["summary"]["owner_registry_export_accepted_count"] == 1
    assert payload["summary"]["reviewer_validation_ready_count"] == 1
    assert payload["summary"]["reviewer_validation_passed_count"] == 1
    assert payload["summary"]["post_enable_readback_passed_count"] == 1
    assert payload["summary"]["reviewer_validation_quarantined_count"] == 0
    assert payload["summary"]["manager_registry_accepted_count"] == 6
    assert payload["summary"]["manager_registry_acceptance_intake_endpoint_available_count"] == 1
    assert payload["summary"]["manager_registry_acceptance_evidence_received_count"] == 1
    assert payload["summary"]["manager_registry_acceptance_evidence_review_ready_count"] == 1
    assert payload["summary"]["runtime_gate_count"] == 0


def test_iwooos_wazuh_manager_registry_reviewer_validation_evidence_slots_are_accepted_only_for_posture() -> None:
    payload = load_latest_iwooos_wazuh_manager_registry_reviewer_validation()

    assert [item["slot_id"] for item in payload["evidence_slots"]] == [
        "manager_registry_agent_counts",
        "per_host_agent_scope_matrix",
        "dashboard_api_rbac_tls_repair_readback",
        "readonly_credential_metadata_without_secret",
        "owner_response_and_rollback_owner",
        "post_enable_iwooos_readback",
    ]
    assert all(item["received"] is True for item in payload["evidence_slots"])
    assert all(item["accepted"] is True for item in payload["evidence_slots"])
    assert all(item["quarantined"] is False for item in payload["evidence_slots"])
    assert all(item["next_gate"] == "manager_registry_acceptance_evidence_review" for item in payload["evidence_slots"])
    assert "managed_core_node_a" in payload["expected_scope_aliases"]
    assert "manager_registry_agent_counts" in [item["slot_id"] for item in payload["evidence_slots"]]


def test_iwooos_wazuh_manager_registry_reviewer_validation_api_is_public_safe() -> None:
    response = _client().get("/api/v1/iwooos/wazuh-manager-registry-reviewer-validation")

    assert response.status_code == 200
    data = response.json()
    assert data["schema_version"] == "iwooos_wazuh_manager_registry_reviewer_validation_readback_v1"
    assert data["summary"]["owner_registry_export_received_count"] == 1
    assert data["summary"]["owner_registry_export_accepted_count"] == 1
    assert data["summary"]["reviewer_validation_passed_count"] == 1
    assert data["summary"]["post_enable_readback_passed_count"] == 1
    assert data["summary"]["manager_registry_accepted_count"] == 6
    assert data["summary"]["manager_registry_acceptance_intake_endpoint_available_count"] == 1
    assert data["summary"]["manager_registry_acceptance_evidence_received_count"] == 1
    assert data["summary"]["manager_registry_acceptance_evidence_review_ready_count"] == 1
    assert data["summary"]["runtime_gate_count"] == 0
    assert len(data["reviewer_validation_checks"]) == 11
    assert len(data["evidence_slots"]) == 6
    assert any(
        marker == "wazuh_manager_registry_reviewer_validation_owner_registry_export_received_count=1"
        for marker in data["boundary_markers"]
    )
    assert any(
        marker == "wazuh_manager_registry_reviewer_validation_owner_registry_export_accepted_count=1"
        for marker in data["boundary_markers"]
    )
    assert any(
        marker == "wazuh_manager_registry_reviewer_validation_passed_count=1"
        for marker in data["boundary_markers"]
    )
    assert any(
        marker == "wazuh_manager_registry_reviewer_validation_post_enable_readback_passed_count=1"
        for marker in data["boundary_markers"]
    )
    assert any(
        marker == "wazuh_manager_registry_reviewer_validation_manager_registry_accepted_count=6"
        for marker in data["boundary_markers"]
    )
    assert any(
        marker == "wazuh_manager_registry_acceptance_validation_api_available=true"
        for marker in data["boundary_markers"]
    )
    assert any(
        marker == "wazuh_manager_registry_acceptance_evidence_received_count=1"
        for marker in data["boundary_markers"]
    )
    assert any(
        marker == "wazuh_manager_registry_acceptance_evidence_review_ready_count=1"
        for marker in data["boundary_markers"]
    )
    assert any(
        marker == "wazuh_manager_registry_reviewer_validation_runtime_gate_count=0"
        for marker in data["boundary_markers"]
    )
    assert any(rule.startswith("reviewer validation passed") for rule in data["no_false_green_rules"])
    assert data["boundaries"]["runtime_execution_authorized"] is False
    assert data["boundaries"]["wazuh_active_response_authorized"] is False
    assert data["boundaries"]["host_write_authorized"] is False
    assert data["boundaries"]["not_authorization"] is True
    assert "192.168.0." not in response.text
    assert "工作視窗" not in response.text
    assert "批准！繼續" not in response.text
    assert "source_thread_id" not in response.text
    assert "owenhytsai/" not in response.text
    assert "WAZUH_API_PASSWORD" not in response.text


def test_iwooos_wazuh_manager_registry_owner_export_validation_accepts_redacted_payload() -> None:
    payload = validate_iwooos_wazuh_manager_registry_owner_export(_valid_owner_export())

    assert payload["schema_version"] == "iwooos_wazuh_manager_registry_owner_export_validation_result_v1"
    assert payload["status"] == "accepted_for_readonly_posture_only"
    assert payload["accepted_for_readonly_posture_only"] is True
    assert payload["reviewer_validation_passed"] is True
    assert payload["summary"]["owner_registry_export_received_count"] == 1
    assert payload["summary"]["owner_registry_export_accepted_count"] == 1
    assert payload["summary"]["manager_registry_accepted_count"] == 0
    assert payload["summary"]["runtime_gate_count"] == 0
    assert payload["boundaries"]["payload_persisted"] is False
    assert payload["boundaries"]["runtime_execution_authorized"] is False
    assert payload["boundaries"]["manager_registry_accepted_updated"] is False
    assert all(slot["received"] is True for slot in payload["evidence_slots"])
    assert all(slot["accepted"] is True for slot in payload["evidence_slots"])


def test_iwooos_wazuh_manager_registry_owner_export_validation_api_does_not_persist_payload_or_open_runtime() -> None:
    client = _client()
    response = client.post(
        "/api/v1/iwooos/wazuh-manager-registry-reviewer-validation/validate-owner-export",
        json=_valid_owner_export(),
    )

    assert response.status_code == 200
    result = response.json()
    assert result["status"] == "accepted_for_readonly_posture_only"
    assert result["summary"]["owner_registry_export_accepted_count"] == 1
    assert result["summary"]["manager_registry_accepted_count"] == 0
    assert result["summary"]["runtime_gate_count"] == 0

    readback = client.get("/api/v1/iwooos/wazuh-manager-registry-reviewer-validation").json()
    assert readback["summary"]["owner_registry_export_received_count"] == 1
    assert readback["summary"]["owner_registry_export_accepted_count"] == 1
    assert readback["summary"]["reviewer_validation_passed_count"] == 1
    assert readback["summary"]["post_enable_readback_passed_count"] == 1
    assert readback["summary"]["manager_registry_accepted_count"] == 6
    assert readback["summary"]["runtime_gate_count"] == 0


def test_iwooos_wazuh_manager_registry_owner_export_validation_requests_missing_fields() -> None:
    candidate = _valid_owner_export()
    candidate.pop("decision_reason")

    payload = validate_iwooos_wazuh_manager_registry_owner_export(candidate)

    assert payload["status"] == "request_missing_fields"
    assert payload["accepted_for_readonly_posture_only"] is False
    assert payload["summary"]["owner_registry_export_received_count"] == 1
    assert payload["summary"]["owner_registry_export_accepted_count"] == 0
    assert any("decision_reason" in finding["field_paths"] for finding in payload["validation_findings"])


def test_iwooos_wazuh_manager_registry_owner_export_validation_quarantines_sensitive_payload() -> None:
    candidate = _valid_owner_export()
    candidate["manager_health_ref"] = "health evidence mentioned 10.250.250.250 by mistake"

    payload = validate_iwooos_wazuh_manager_registry_owner_export(candidate)

    assert payload["status"] == "quarantine_sensitive_payload"
    assert payload["quarantined"] is True
    assert payload["summary"]["reviewer_validation_quarantined_count"] == 1
    assert payload["summary"]["owner_registry_export_accepted_count"] == 0
    assert "10.250.250.250" not in str(payload)
    assert any(finding["check_id"] == "RV-07" for finding in payload["validation_findings"])


def test_iwooos_wazuh_manager_registry_owner_export_validation_rejects_runtime_action_request() -> None:
    candidate = _valid_owner_export()
    candidate["requested_actions"] = ["wazuh_active_response"]

    payload = validate_iwooos_wazuh_manager_registry_owner_export(candidate)

    assert payload["status"] == "reject_runtime_action_request"
    assert payload["runtime_action_rejected"] is True
    assert payload["summary"]["owner_registry_export_accepted_count"] == 0
    assert payload["summary"]["runtime_gate_count"] == 0
    assert any(finding["check_id"] == "RV-09" for finding in payload["validation_findings"])


def test_iwooos_wazuh_manager_registry_acceptance_evidence_validation_accepts_redacted_packet_for_review_only() -> None:
    payload = validate_iwooos_wazuh_manager_registry_acceptance_evidence(_valid_acceptance_evidence())

    assert payload["schema_version"] == "iwooos_wazuh_manager_registry_acceptance_evidence_validation_result_v1"
    assert payload["status"] == "accepted_for_manager_registry_acceptance_review_only"
    assert payload["mode"] == "no_persist_acceptance_evidence_review_no_runtime_no_secret_collection"
    assert payload["accepted_for_manager_registry_acceptance_review_only"] is True
    assert payload["summary"]["manager_registry_acceptance_evidence_received_count"] == 1
    assert payload["summary"]["manager_registry_acceptance_evidence_review_ready_count"] == 1
    assert payload["summary"]["manager_registry_accepted_count"] == 0
    assert payload["summary"]["runtime_gate_count"] == 0
    assert payload["boundaries"]["payload_persisted"] is False
    assert payload["boundaries"]["manager_registry_accepted_updated"] is False
    assert payload["boundaries"]["runtime_execution_authorized"] is False
    assert payload["next_gate"] == "commit_manager_registry_accepted_readback_evidence"


def test_iwooos_wazuh_manager_registry_acceptance_evidence_api_does_not_persist_or_open_runtime() -> None:
    client = _client()
    response = client.post(
        "/api/v1/iwooos/wazuh-manager-registry-reviewer-validation/validate-manager-registry-acceptance",
        json=_valid_acceptance_evidence(),
    )

    assert response.status_code == 200
    result = response.json()
    assert result["status"] == "accepted_for_manager_registry_acceptance_review_only"
    assert result["summary"]["manager_registry_acceptance_evidence_review_ready_count"] == 1
    assert result["summary"]["manager_registry_accepted_count"] == 0
    assert result["summary"]["runtime_gate_count"] == 0

    readback = client.get("/api/v1/iwooos/wazuh-manager-registry-reviewer-validation").json()
    assert readback["summary"]["manager_registry_acceptance_evidence_received_count"] == 1
    assert readback["summary"]["manager_registry_acceptance_evidence_review_ready_count"] == 1
    assert readback["summary"]["manager_registry_accepted_count"] == 6
    assert readback["summary"]["runtime_gate_count"] == 0


def test_iwooos_wazuh_manager_registry_acceptance_evidence_validation_requests_missing_fields() -> None:
    candidate = _valid_acceptance_evidence()
    candidate.pop("product_scope_parity_ref")

    payload = validate_iwooos_wazuh_manager_registry_acceptance_evidence(candidate)

    assert payload["status"] == "request_manager_registry_acceptance_evidence_supplement"
    assert payload["accepted_for_manager_registry_acceptance_review_only"] is False
    assert payload["summary"]["manager_registry_acceptance_evidence_supplement_required_count"] == 1
    assert payload["summary"]["manager_registry_accepted_count"] == 0
    assert any("product_scope_parity_ref" in finding["field_paths"] for finding in payload["validation_findings"])


def test_iwooos_wazuh_manager_registry_acceptance_evidence_validation_quarantines_sensitive_payload() -> None:
    candidate = _valid_acceptance_evidence()
    candidate["post_enable_readback_ref"] = "post enable accidentally included 10.250.250.250"

    payload = validate_iwooos_wazuh_manager_registry_acceptance_evidence(candidate)

    assert payload["status"] == "quarantine_sensitive_payload"
    assert payload["quarantined"] is True
    assert payload["summary"]["manager_registry_acceptance_evidence_quarantined_count"] == 1
    assert payload["summary"]["manager_registry_accepted_count"] == 0
    assert "10.250.250.250" not in str(payload)
    assert any(finding["check_id"] == "MRA-04" for finding in payload["validation_findings"])


def test_iwooos_wazuh_manager_registry_acceptance_evidence_validation_rejects_runtime_action_request() -> None:
    candidate = _valid_acceptance_evidence()
    candidate["requested_actions"] = ["wazuh_active_response"]

    payload = validate_iwooos_wazuh_manager_registry_acceptance_evidence(candidate)

    assert payload["status"] == "reject_runtime_action_request"
    assert payload["runtime_action_rejected"] is True
    assert payload["summary"]["manager_registry_acceptance_runtime_action_rejected_count"] == 1
    assert payload["summary"]["manager_registry_accepted_count"] == 0
    assert payload["summary"]["runtime_gate_count"] == 0
    assert any(finding["check_id"] == "MRA-05" for finding in payload["validation_findings"])
