from decimal import Decimal

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
from core.models import Bid, FavoriteTransporter, Shipment, Trip

User = get_user_model()


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

        self.transporter = User.objects.create_user('fav-transporter@test.com', email='fav-transporter@test.com', password='secret')
        UserRole.objects.create(user=self.transporter, role=UserRole.Role.TRANSPORTER)
        TransporterProfile.objects.create(
            user=self.transporter,
            account_type=TransporterProfile.AccountType.DRIVER,
            local=True,
            country_to_country=False,
            documents_verified=True,
        )

        self.driver = User.objects.create_user('fav-driver@test.com', email='fav-driver@test.com', password='secret')
        UserRole.objects.create(user=self.driver, role=UserRole.Role.TRANSPORTER)
        TransporterProfile.objects.create(
            user=self.driver,
            account_type=TransporterProfile.AccountType.TRANSPORTER_DRIVER,
            local=True,
            country_to_country=False,
            documents_verified=True,
        )

        self.shipment = Shipment.objects.create(
            shipper=self.shipper,
            pickup_address='A',
            delivery_address='B',
            cargo_type='General',
            weight='1 ton',
            vehicle_type_required='Flatbed',
            local=True,
            country_to_country=False,
            status=Shipment.Status.ASSIGNED,
        )
        self.bid = Bid.objects.create(
            shipment=self.shipment,
            transporter=self.transporter,
            amount=Decimal('1200.00'),
            status=Bid.Status.ACCEPTED,
        )
        self.trip = Trip.objects.create(
            shipment=self.shipment,
            accepted_bid=self.bid,
            transporter=self.transporter,
            assigned_driver=self.driver,
            status=Trip.Status.IN_TRANSIT,
        )

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

    def test_trip_list_and_detail_return_is_favourite_false_initially(self):
        # 1. GET /api/shipper/trips/
        res_list = self.client.get('/api/shipper/trips/')
        self.assertEqual(res_list.status_code, 200)
        data_list = res_list.json()['data']
        self.assertEqual(len(data_list), 1)
        self.assertIn('is_favourite', data_list[0])
        self.assertFalse(data_list[0]['is_favourite'])
        self.assertFalse(data_list[0]['is_favorite'])

        # 2. GET /api/shipper/trips/{id}/
        res_detail = self.client.get(f'/api/shipper/trips/{self.trip.id}/')
        self.assertEqual(res_detail.status_code, 200)
        data_detail = res_detail.json()['data']
        self.assertIn('is_favourite', data_detail)
        self.assertFalse(data_detail['is_favourite'])
        self.assertFalse(data_detail['is_favorite'])
        self.assertFalse(data_detail['accepted_bid']['is_favourite'])
        self.assertFalse(data_detail['assigned_driver']['is_favourite'])

    def test_trip_list_and_detail_return_is_favourite_true_when_favorited(self):
        # Shipper favorites the transporter
        FavoriteTransporter.objects.create(shipper=self.shipper, transporter=self.transporter)

        # 1. GET /api/shipper/trips/
        res_list = self.client.get('/api/shipper/trips/')
        self.assertEqual(res_list.status_code, 200)
        data_list = res_list.json()['data']
        self.assertTrue(data_list[0]['is_favourite'])
        self.assertTrue(data_list[0]['is_favorite'])

        # 2. GET /api/shipper/trips/{id}/
        res_detail = self.client.get(f'/api/shipper/trips/{self.trip.id}/')
        self.assertEqual(res_detail.status_code, 200)
        data_detail = res_detail.json()['data']
        self.assertTrue(data_detail['is_favourite'])
        self.assertTrue(data_detail['is_favorite'])
        self.assertTrue(data_detail['accepted_bid']['is_favourite'])

    def test_trip_returns_is_favourite_true_when_assigned_driver_favorited(self):
        # Shipper favorites the assigned fleet driver
        FavoriteTransporter.objects.create(shipper=self.shipper, transporter=self.driver)

        res_detail = self.client.get(f'/api/shipper/trips/{self.trip.id}/')
        self.assertEqual(res_detail.status_code, 200)
        data_detail = res_detail.json()['data']
        self.assertTrue(data_detail['is_favourite'])
        self.assertTrue(data_detail['assigned_driver']['is_favourite'])
