from decimal import Decimal
from unittest.mock import patch

from django.contrib.auth import get_user_model
from django.test import TestCase
from rest_framework.authtoken.models import Token
from rest_framework.test import APIClient

from accounts.models import ShipperProfile, TransporterProfile, UserRole, Vehicle
from core.models import Shipment

User = get_user_model()


class ShipperNearbyDriversTests(TestCase):
    def setUp(self):
        self.shipper = User.objects.create_user('shipnear@test.com', email='shipnear@test.com', password='secret')
        UserRole.objects.create(user=self.shipper, role=UserRole.Role.SHIPPER, phone='', language='en')
        ShipperProfile.objects.create(user=self.shipper, account_type=ShipperProfile.AccountType.INDIVIDUAL)

        self.transporter = User.objects.create_user('tr1@test.com', email='tr1@test.com', password='secret')
        UserRole.objects.create(user=self.transporter, role=UserRole.Role.TRANSPORTER, phone='123', language='en')
        TransporterProfile.objects.create(
            user=self.transporter,
            account_type=TransporterProfile.AccountType.FLEET_OWNER,
            local=True,
            country_to_country=False,
            documents_verified=True,
            tc_id='111',
        )
        Vehicle.objects.create(
            owner=self.transporter,
            vehicle_type='Flatbed',
            registration_number='TR-111',
            load_capacity=Decimal('5000'),
            is_verified=True,
            is_active=True,
        )

        self.transporter_far = User.objects.create_user('tr2@test.com', email='tr2@test.com', password='secret')
        UserRole.objects.create(user=self.transporter_far, role=UserRole.Role.TRANSPORTER, phone='456', language='en')
        TransporterProfile.objects.create(
            user=self.transporter_far,
            account_type=TransporterProfile.AccountType.FLEET_OWNER,
            local=True,
            country_to_country=False,
            documents_verified=True,
            tc_id='222',
        )
        Vehicle.objects.create(
            owner=self.transporter_far,
            vehicle_type='Flatbed',
            registration_number='TR-222',
            load_capacity=Decimal('5000'),
            is_verified=True,
            is_active=True,
        )

        self.shipment = Shipment.objects.create(
            shipper=self.shipper,
            pickup_address='A',
            pickup_lat=Decimal('24.8607000'),
            pickup_lon=Decimal('67.0011000'),
            delivery_address='B',
            cargo_type='General',
            weight='1 ton',
            vehicle_type_required='Flatbed',
            local=True,
            country_to_country=False,
            status=Shipment.Status.PUBLISHED,
        )

        token, _ = Token.objects.get_or_create(user=self.shipper)
        self.client = APIClient()
        self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token.key}')

    @patch('api.views.get_latest_positions_map')
    def test_returns_only_within_5km_verified_active_transporters(self, mock_positions):
        mock_positions.return_value = {
            '111': {'latitude': 24.8610, 'longitude': 67.0020, 'raw': {'id': 10}},
            '222': {'latitude': 24.9500, 'longitude': 67.1000, 'raw': {'id': 11}},
        }
        r = self.client.get(f'/api/shipper/shipments/{self.shipment.id}/nearby-drivers/')
        self.assertEqual(r.status_code, 200)
        data = r.json()['data']
        self.assertEqual(data['radius_km'], 5.0)
        self.assertEqual(data['count'], 1)
        self.assertEqual(data['drivers'][0]['transporter_id'], self.transporter.id)

    @patch('api.views.get_latest_device_position')
    @patch('api.views.get_latest_positions_map')
    def test_falls_back_to_device_position_when_bulk_map_misses(self, mock_positions, mock_latest_device_position):
        mock_positions.return_value = {}
        mock_latest_device_position.side_effect = [
            {'latitude': 24.8610, 'longitude': 67.0020, 'raw': {'id': 10}},
            {'latitude': 24.9500, 'longitude': 67.1000, 'raw': {'id': 11}},
        ]

        r = self.client.get(f'/api/shipper/shipments/{self.shipment.id}/nearby-drivers/')
        self.assertEqual(r.status_code, 200)
        data = r.json()['data']
        self.assertEqual(data['count'], 1)
        self.assertEqual(data['drivers'][0]['transporter_id'], self.transporter.id)
