"""
Unit tests for Field Mobile models.

Tests model methods without database access.
"""
from unittest.mock import Mock, patch, MagicMock
from decimal import Decimal
import pytest


class TestEventStatusHistoryModel:
    """Test EventStatusHistory model methods."""

    def test_str_method(self):
        """Should return formatted status change."""
        from smoothschedule.communication.mobile.models import EventStatusHistory

        history = EventStatusHistory()
        history.event_id = 42
        history.old_status = 'SCHEDULED'
        history.new_status = 'EN_ROUTE'

        result = str(history)

        assert result == 'Event 42: SCHEDULED → EN_ROUTE'

    def test_str_method_completed(self):
        """Should show completed status change."""
        from smoothschedule.communication.mobile.models import EventStatusHistory

        history = EventStatusHistory()
        history.event_id = 100
        history.old_status = 'IN_PROGRESS'
        history.new_status = 'COMPLETED'

        result = str(history)

        assert result == 'Event 100: IN_PROGRESS → COMPLETED'

    def test_model_has_required_fields(self):
        """Should have all required fields."""
        from smoothschedule.communication.mobile.models import EventStatusHistory

        field_names = [f.name for f in EventStatusHistory._meta.get_fields()]
        assert 'tenant' in field_names
        assert 'event_id' in field_names
        assert 'old_status' in field_names
        assert 'new_status' in field_names
        assert 'changed_by' in field_names
        assert 'changed_at' in field_names
        assert 'notes' in field_names
        assert 'latitude' in field_names
        assert 'longitude' in field_names
        assert 'source' in field_names

    def test_source_choices(self):
        """Should have source choices defined."""
        from smoothschedule.communication.mobile.models import EventStatusHistory

        choices = dict(EventStatusHistory._meta.get_field('source').choices)
        assert 'mobile_app' in choices
        assert 'web_app' in choices
        assert 'api' in choices
        assert 'system' in choices

    def test_meta_ordering(self):
        """Should order by -changed_at."""
        from smoothschedule.communication.mobile.models import EventStatusHistory

        assert EventStatusHistory._meta.ordering == ['-changed_at']


class TestEmployeeLocationUpdateModel:
    """Test EmployeeLocationUpdate model methods."""

    def test_str_method(self):
        """Should return employee and coordinates."""
        from smoothschedule.communication.mobile.models import EmployeeLocationUpdate

        location = EmployeeLocationUpdate()
        location.latitude = Decimal('37.7749295')
        location.longitude = Decimal('-122.4194155')

        mock_employee = Mock()
        mock_employee.__str__ = Mock(return_value='John Doe')
        location._state.fields_cache['employee'] = mock_employee

        result = str(location)

        assert 'John Doe' in result
        assert '37.7749295' in result
        assert '-122.4194155' in result

    def test_model_has_required_fields(self):
        """Should have all required fields."""
        from smoothschedule.communication.mobile.models import EmployeeLocationUpdate

        field_names = [f.name for f in EmployeeLocationUpdate._meta.get_fields()]
        assert 'tenant' in field_names
        assert 'employee' in field_names
        assert 'event_id' in field_names
        assert 'latitude' in field_names
        assert 'longitude' in field_names
        assert 'accuracy' in field_names
        assert 'altitude' in field_names
        assert 'heading' in field_names
        assert 'speed' in field_names
        assert 'timestamp' in field_names
        assert 'battery_level' in field_names

    def test_meta_ordering(self):
        """Should order by -timestamp."""
        from smoothschedule.communication.mobile.models import EmployeeLocationUpdate

        assert EmployeeLocationUpdate._meta.ordering == ['-timestamp']

    def test_get_latest_for_event(self):
        """Should return most recent location for an event."""
        from smoothschedule.communication.mobile.models import EmployeeLocationUpdate

        mock_location = Mock()

        with patch.object(EmployeeLocationUpdate.objects, 'filter') as mock_filter:
            mock_filter.return_value.order_by.return_value.first.return_value = mock_location

            result = EmployeeLocationUpdate.get_latest_for_event(
                tenant_id=1, event_id=42
            )

            mock_filter.assert_called_once_with(tenant_id=1, event_id=42)
            mock_filter.return_value.order_by.assert_called_once_with('-timestamp')
            assert result == mock_location

    def test_get_route_for_event_calls_filter(self):
        """Should filter by tenant_id and event_id."""
        from smoothschedule.communication.mobile.models import EmployeeLocationUpdate

        mock_locations = [
            {'latitude': 37.77, 'longitude': -122.42, 'timestamp': 'ts1', 'accuracy': 10},
            {'latitude': 37.78, 'longitude': -122.43, 'timestamp': 'ts2', 'accuracy': 5},
        ]

        # Build up the mock chain properly
        mock_values = Mock(return_value=mock_locations)
        mock_slice = Mock()
        mock_slice.values = mock_values

        mock_order_by = Mock()
        mock_order_by.__getitem__ = Mock(return_value=mock_slice)

        mock_filter = Mock()
        mock_filter.order_by = Mock(return_value=mock_order_by)

        with patch.object(EmployeeLocationUpdate.objects, 'filter', return_value=mock_filter):
            result = EmployeeLocationUpdate.get_route_for_event(
                tenant_id=1, event_id=42, limit=100
            )

            EmployeeLocationUpdate.objects.filter.assert_called_once_with(
                tenant_id=1, event_id=42
            )
            mock_filter.order_by.assert_called_once_with('timestamp')


class TestFieldCallLogModel:
    """Test FieldCallLog model methods."""

    def test_str_method_outbound_voice(self):
        """Should show outbound voice call format."""
        from smoothschedule.communication.mobile.models import FieldCallLog

        call_log = FieldCallLog()
        call_log.call_type = FieldCallLog.CallType.VOICE
        call_log.direction = FieldCallLog.Direction.OUTBOUND
        call_log.status = FieldCallLog.Status.COMPLETED

        result = str(call_log)

        assert 'voice' in result
        assert '→' in result
        assert 'completed' in result.lower()

    def test_str_method_inbound_sms(self):
        """Should show inbound SMS format."""
        from smoothschedule.communication.mobile.models import FieldCallLog

        call_log = FieldCallLog()
        call_log.call_type = FieldCallLog.CallType.SMS
        call_log.direction = FieldCallLog.Direction.INBOUND
        call_log.status = FieldCallLog.Status.COMPLETED

        result = str(call_log)

        assert 'sms' in result
        assert '←' in result

    def test_model_has_required_fields(self):
        """Should have all required fields."""
        from smoothschedule.communication.mobile.models import FieldCallLog

        field_names = [f.name for f in FieldCallLog._meta.get_fields()]
        assert 'tenant' in field_names
        assert 'event_id' in field_names
        assert 'call_type' in field_names
        assert 'direction' in field_names
        assert 'status' in field_names
        assert 'employee' in field_names
        assert 'customer_phone' in field_names
        assert 'proxy_number' in field_names
        assert 'twilio_call_sid' in field_names
        assert 'twilio_message_sid' in field_names
        assert 'duration_seconds' in field_names
        assert 'cost_cents' in field_names

    def test_call_type_choices(self):
        """Should have voice and sms types."""
        from smoothschedule.communication.mobile.models import FieldCallLog

        assert FieldCallLog.CallType.VOICE == 'voice'
        assert FieldCallLog.CallType.SMS == 'sms'

    def test_direction_choices(self):
        """Should have outbound and inbound directions."""
        from smoothschedule.communication.mobile.models import FieldCallLog

        assert FieldCallLog.Direction.OUTBOUND == 'outbound'
        assert FieldCallLog.Direction.INBOUND == 'inbound'

    def test_status_choices(self):
        """Should have all status choices."""
        from smoothschedule.communication.mobile.models import FieldCallLog

        assert FieldCallLog.Status.INITIATED == 'initiated'
        assert FieldCallLog.Status.RINGING == 'ringing'
        assert FieldCallLog.Status.IN_PROGRESS == 'in_progress'
        assert FieldCallLog.Status.COMPLETED == 'completed'
        assert FieldCallLog.Status.BUSY == 'busy'
        assert FieldCallLog.Status.NO_ANSWER == 'no_answer'
        assert FieldCallLog.Status.FAILED == 'failed'
        assert FieldCallLog.Status.CANCELED == 'canceled'

    def test_meta_ordering(self):
        """Should order by -initiated_at."""
        from smoothschedule.communication.mobile.models import FieldCallLog

        assert FieldCallLog._meta.ordering == ['-initiated_at']
