"""Tests for WFRMLS History module."""

import pytest
from datetime import datetime, date
from typing import Dict, Any
from unittest.mock import Mock, patch

from wfrmls.history import HistoryTransactionalClient, HistoryTransactionType, HistoryStatus
from wfrmls.exceptions import WFRMLSError


class TestHistoryTransactionType:
    """Test suite for HistoryTransactionType enum."""

    def test_history_transaction_type_values(self) -> None:
        """Test HistoryTransactionType enum values."""
        assert HistoryTransactionType.SALE.value == "Sale"
        assert HistoryTransactionType.LEASE.value == "Lease"
        assert HistoryTransactionType.RENTAL.value == "Rental"
        assert HistoryTransactionType.AUCTION.value == "Auction"


class TestHistoryStatus:
    """Test suite for HistoryStatus enum."""

    def test_history_status_values(self) -> None:
        """Test HistoryStatus enum values."""
        assert HistoryStatus.CLOSED.value == "Closed"
        assert HistoryStatus.SOLD.value == "Sold"
        assert HistoryStatus.LEASED.value == "Leased"
        assert HistoryStatus.EXPIRED.value == "Expired"
        assert HistoryStatus.WITHDRAWN.value == "Withdrawn"


class TestHistoryTransactionalClient:
    """Test suite for HistoryTransactionalClient class."""

    def setup_method(self) -> None:
        """Set up test fixtures."""
        self.client = HistoryTransactionalClient(bearer_token="test_token")

    @patch("wfrmls.history.HistoryTransactionalClient.get")
    def test_get_history_transactions_basic(self, mock_get: Mock) -> None:
        """Test basic get_history_transactions functionality."""
        mock_response: Dict[str, Any] = {
            "value": [
                {
                    "TransactionKey": "T123",
                    "ClosePrice": 500000,
                    "CloseDate": "2024-01-01T12:00:00Z",
                    "TransactionType": "Sale"
                }
            ]
        }
        mock_get.return_value = mock_response

        result = self.client.get_history_transactions()

        mock_get.assert_called_once_with("HistoryTransactional", params={})
        assert result == mock_response

    @patch("wfrmls.history.HistoryTransactionalClient.get")
    def test_get_history_transactions_with_all_params(self, mock_get: Mock) -> None:
        """Test get_history_transactions with all parameters."""
        mock_response: Dict[str, Any] = {"value": []}
        mock_get.return_value = mock_response

        result = self.client.get_history_transactions(
            top=50,
            skip=10,
            filter_query="TransactionType eq 'Sale'",
            select=["TransactionKey", "ClosePrice"],
            orderby="CloseDate desc",
            expand=["Property"],
            count=True
        )

        expected_params = {
            "$top": 50,
            "$skip": 10,
            "$filter": "TransactionType eq 'Sale'",
            "$select": "TransactionKey,ClosePrice",
            "$orderby": "CloseDate desc",
            "$expand": "Property",
            "$count": "true"
        }

        mock_get.assert_called_once_with("HistoryTransactional", params=expected_params)

    @patch("wfrmls.history.HistoryTransactionalClient.get")
    def test_get_history_transactions_top_limit_enforcement(self, mock_get: Mock) -> None:
        """Test that top parameter is limited to 200."""
        mock_get.return_value = {"value": []}

        self.client.get_history_transactions(top=300)

        expected_params = {"$top": 200}
        mock_get.assert_called_once_with("HistoryTransactional", params=expected_params)

    @patch("wfrmls.history.HistoryTransactionalClient.get")
    def test_get_history_transaction(self, mock_get: Mock) -> None:
        """Test get_history_transaction functionality."""
        transaction_key = "T123"
        mock_response: Dict[str, Any] = {
            "TransactionKey": transaction_key,
            "ClosePrice": 500000,
            "CloseDate": "2024-01-01T12:00:00Z"
        }
        mock_get.return_value = mock_response

        result = self.client.get_history_transaction(transaction_key)

        mock_get.assert_called_once_with(f"HistoryTransactional('{transaction_key}')")
        assert result == mock_response

    @patch("wfrmls.history.HistoryTransactionalClient.get_history_transactions")
    def test_get_transactions_for_property(self, mock_get_transactions: Mock) -> None:
        """Test get_transactions_for_property functionality."""
        mock_response: Dict[str, Any] = {"value": []}
        mock_get_transactions.return_value = mock_response

        result = self.client.get_transactions_for_property(
            listing_key="12345",
            orderby="CloseDate desc"
        )

        mock_get_transactions.assert_called_once_with(
            filter_query="ListingKey eq '12345'",
            orderby="CloseDate desc"
        )

    @patch("wfrmls.history.HistoryTransactionalClient.get_history_transactions")
    def test_get_sales_by_price_range(self, mock_get_transactions: Mock) -> None:
        """Test get_sales_by_price_range functionality."""
        mock_response: Dict[str, Any] = {"value": []}
        mock_get_transactions.return_value = mock_response

        result = self.client.get_sales_by_price_range(
            min_price=400000,
            max_price=600000,
            orderby="CloseDate desc"
        )

        expected_filter = "TransactionType eq 'Sale' and ClosePrice ge 400000 and ClosePrice le 600000"
        mock_get_transactions.assert_called_once_with(
            filter_query=expected_filter,
            orderby="CloseDate desc"
        )

    @patch("wfrmls.history.HistoryTransactionalClient.get_history_transactions")
    def test_get_recent_sales(self, mock_get_transactions: Mock) -> None:
        """Test get_recent_sales functionality."""
        mock_response: Dict[str, Any] = {"value": []}
        mock_get_transactions.return_value = mock_response

        result = self.client.get_recent_sales(
            days_back=30,
            orderby="CloseDate desc"
        )

        # Check that the filter contains the expected parts
        mock_get_transactions.assert_called_once()
        call_args = mock_get_transactions.call_args
        assert "filter_query" in call_args.kwargs
        assert "TransactionType eq 'Sale'" in call_args.kwargs["filter_query"]
        assert "CloseDate ge" in call_args.kwargs["filter_query"]

    @patch("wfrmls.history.HistoryTransactionalClient.get_history_transactions")
    def test_get_transactions_by_city(self, mock_get_transactions: Mock) -> None:
        """Test get_transactions_by_city functionality."""
        mock_response: Dict[str, Any] = {"value": []}
        mock_get_transactions.return_value = mock_response

        result = self.client.get_transactions_by_city(
            city="Salt Lake City",
            orderby="CloseDate desc"
        )

        mock_get_transactions.assert_called_once_with(
            filter_query="City eq 'Salt Lake City'",
            orderby="CloseDate desc"
        )

    @patch("wfrmls.history.HistoryTransactionalClient.get_history_transactions")
    def test_get_closed_transactions(self, mock_get_transactions: Mock) -> None:
        """Test get_closed_transactions functionality."""
        mock_response: Dict[str, Any] = {"value": []}
        mock_get_transactions.return_value = mock_response

        result = self.client.get_closed_transactions(
            orderby="CloseDate desc"
        )

        mock_get_transactions.assert_called_once_with(
            filter_query="Status eq 'Closed'",
            orderby="CloseDate desc"
        )

    @patch("wfrmls.history.HistoryTransactionalClient.get_history_transactions")
    def test_get_transactions_with_property(self, mock_get_transactions: Mock) -> None:
        """Test get_transactions_with_property functionality."""
        mock_response: Dict[str, Any] = {"value": []}
        mock_get_transactions.return_value = mock_response

        result = self.client.get_transactions_with_property(
            orderby="CloseDate desc",
            top=25
        )

        mock_get_transactions.assert_called_once_with(
            expand="Property",
            orderby="CloseDate desc",
            top=25
        )

    @patch("wfrmls.history.HistoryTransactionalClient.get_history_transactions")
    def test_get_modified_transactions_datetime(self, mock_get_transactions: Mock) -> None:
        """Test get_modified_transactions with datetime object."""
        mock_response: Dict[str, Any] = {"value": []}
        mock_get_transactions.return_value = mock_response

        since_datetime = datetime(2024, 1, 1, 12, 0, 0)
        result = self.client.get_modified_transactions(
            since=since_datetime,
            orderby="ModificationTimestamp desc"
        )

        expected_filter = "ModificationTimestamp gt '2024-01-01T12:00:00Z'"
        mock_get_transactions.assert_called_once_with(
            filter_query=expected_filter,
            orderby="ModificationTimestamp desc"
        )

    @patch("wfrmls.history.HistoryTransactionalClient.get_history_transactions")
    def test_get_sales_by_date_range(self, mock_get_transactions: Mock) -> None:
        """Test get_sales_by_date_range functionality."""
        mock_response: Dict[str, Any] = {"value": []}
        mock_get_transactions.return_value = mock_response

        start_date = date(2024, 1, 1)
        end_date = date(2024, 1, 31)
        result = self.client.get_sales_by_date_range(
            start_date=start_date,
            end_date=end_date,
            orderby="CloseDate desc"
        )

        expected_filter = "TransactionType eq 'Sale' and CloseDate ge '2024-01-01' and CloseDate le '2024-01-31'"
        mock_get_transactions.assert_called_once_with(
            filter_query=expected_filter,
            orderby="CloseDate desc"
        )

    def test_init_default_params(self) -> None:
        """Test HistoryTransactionalClient initialization with default parameters."""
        client = HistoryTransactionalClient()
        # Test that it doesn't raise an exception and creates properly
        assert hasattr(client, 'bearer_token')
        assert hasattr(client, 'base_url')

    def test_init_with_params(self) -> None:
        """Test HistoryTransactionalClient initialization with custom parameters."""
        client = HistoryTransactionalClient(
            bearer_token="custom_token",
            base_url="https://custom.api.com"
        )
        assert hasattr(client, 'bearer_token')
        assert hasattr(client, 'base_url') 