"""Tests for PingPulseHook."""

import pytest
from unittest.mock import Mock, patch, MagicMock
import requests

from pingpulse_airflow.hooks.pingpulse import PingPulseHook


class TestPingPulseHook:
    """Tests for PingPulseHook class."""

    def test_init_with_defaults(self):
        """Test hook initialization with default values."""
        hook = PingPulseHook()
        assert hook.pingpulse_conn_id == "pingpulse_default"
        assert hook._api_key is None
        assert hook._base_url is None

    def test_init_with_direct_values(self):
        """Test hook initialization with direct API key and URL."""
        hook = PingPulseHook(
            api_key="ppk_test_123",
            base_url="https://custom.pingpulse.com",
        )
        assert hook.api_key == "ppk_test_123"
        assert hook.base_url == "https://custom.pingpulse.com"

    def test_base_url_strips_trailing_slash(self):
        """Test that base_url strips trailing slash."""
        hook = PingPulseHook(base_url="https://example.com/")
        assert hook.base_url == "https://example.com"

    def test_get_conn_returns_session(self):
        """Test that get_conn returns a requests Session."""
        hook = PingPulseHook(api_key="test")
        session = hook.get_conn()
        assert isinstance(session, requests.Session)
        assert session.headers["Content-Type"] == "application/json"

    def test_get_conn_reuses_session(self):
        """Test that get_conn returns the same session on subsequent calls."""
        hook = PingPulseHook(api_key="test")
        session1 = hook.get_conn()
        session2 = hook.get_conn()
        assert session1 is session2

    @patch("pingpulse_airflow.hooks.pingpulse.PingPulseHook.get_conn")
    def test_send_ping_dynamic_workflow(self, mock_get_conn):
        """Test sending ping to dynamic workflow."""
        mock_session = MagicMock()
        mock_response = MagicMock()
        mock_response.json.return_value = {"status": "success"}
        mock_session.post.return_value = mock_response
        mock_get_conn.return_value = mock_session

        hook = PingPulseHook(
            api_key="ppk_test_123",
            base_url="https://app.pingpulse.com",
        )
        result = hook.send_ping(
            workflow_id="dwf123abc",
            stage_path="1",
            payload={"test": "data"},
            start=True,
            workflow_type="dynamic",
        )

        mock_session.post.assert_called_once()
        call_args = mock_session.post.call_args
        assert "/dhk/dwf123abc" in call_args[0][0]
        assert call_args[1]["params"]["stagePath"] == "1"
        assert call_args[1]["params"]["start"] == "yes"
        assert call_args[1]["json"] == {"test": "data"}
        assert result == {"status": "success"}

    @patch("pingpulse_airflow.hooks.pingpulse.PingPulseHook.get_conn")
    def test_send_ping_static_workflow(self, mock_get_conn):
        """Test sending ping to static workflow."""
        mock_session = MagicMock()
        mock_response = MagicMock()
        mock_response.json.return_value = {"status": "success"}
        mock_session.post.return_value = mock_response
        mock_get_conn.return_value = mock_session

        hook = PingPulseHook(
            api_key="ppk_test_123",
            base_url="https://app.pingpulse.com",
        )
        hook.send_ping(
            workflow_id="swf456def",
            stage_path="2",
            workflow_type="static",
            final=True,
        )

        call_args = mock_session.post.call_args
        assert "/shk/swf456def" in call_args[0][0]
        assert call_args[1]["params"]["final"] == "yes"

    @patch("pingpulse_airflow.hooks.pingpulse.PingPulseHook.get_conn")
    def test_send_heartbeat(self, mock_get_conn):
        """Test sending heartbeat ping."""
        mock_session = MagicMock()
        mock_response = MagicMock()
        mock_response.json.return_value = {"status": "ok"}
        mock_session.post.return_value = mock_response
        mock_get_conn.return_value = mock_session

        hook = PingPulseHook(
            api_key="ppk_test_123",
            base_url="https://app.pingpulse.com",
        )
        result = hook.send_heartbeat(monitor_id="hb123abc")

        call_args = mock_session.post.call_args
        assert "/hb/hb123abc/ping" in call_args[0][0]
        assert result == {"status": "ok"}

    @patch("pingpulse_airflow.hooks.pingpulse.PingPulseHook.get_conn")
    def test_test_connection_success(self, mock_get_conn):
        """Test connection test with successful response."""
        mock_session = MagicMock()
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_session.get.return_value = mock_response
        mock_get_conn.return_value = mock_session

        hook = PingPulseHook(api_key="test")
        success, message = hook.test_connection()

        assert success is True
        assert "successful" in message.lower()

    @patch("pingpulse_airflow.hooks.pingpulse.PingPulseHook.get_conn")
    def test_test_connection_failure(self, mock_get_conn):
        """Test connection test with failed response."""
        mock_session = MagicMock()
        mock_session.get.side_effect = Exception("Connection refused")
        mock_get_conn.return_value = mock_session

        hook = PingPulseHook(api_key="test")
        success, message = hook.test_connection()

        assert success is False
        assert "failed" in message.lower()
