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, Shipment, Trip, TripReview, TripShipperReview

User = get_user_model()


class ShipperTripRatingFlagApiTests(TestCase):
    def setUp(self):
        self.shipper = User.objects.create_user('ship-flag@test.com', email='ship-flag@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('tr-flag@test.com', email='tr-flag@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('drv-flag@test.com', email='drv-flag@test.com', password='secret')
        UserRole.objects.create(user=self.driver, role=UserRole.Role.TRANSPORTER)
        TransporterProfile.objects.create(
            user=self.driver,
            account_type=TransporterProfile.AccountType.DRIVER,
            local=True,
            country_to_country=False,
            documents_verified=True,
        )

        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.COMPLETED,
        )
        bid = Bid.objects.create(
            shipment=shipment,
            transporter=self.transporter,
            amount=Decimal('100.00'),
            status=Bid.Status.ACCEPTED,
        )
        self.trip = Trip.objects.create(
            shipment=shipment,
            accepted_bid=bid,
            transporter=self.transporter,
            assigned_driver=self.driver,
            status=Trip.Status.COMPLETED,
        )

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

    def test_shipper_trip_detail_rating_flag_reflects_shipper_review_not_transporter_review(self):
        client = self._shipper_client()

        before = client.get(f'/api/shipper/trips/{self.trip.id}/')
        self.assertEqual(before.status_code, 200)
        self.assertIs(before.json()['data']['shipper_rating'], False)

        TripShipperReview.objects.create(
            trip=self.trip,
            shipper=self.shipper,
            transporter=self.transporter,
            reviewer=self.transporter,
            shipper_rating=5,
        )
        after_transporter_review = client.get(f'/api/shipper/trips/{self.trip.id}/')
        self.assertIs(after_transporter_review.json()['data']['shipper_rating'], False)

        review = client.post(
            f'/api/shipper/trips/{self.trip.id}/review/',
            {
                'transporter_rating': 4,
                'driver_rating': 5,
                'comment': 'Great driver',
            },
            format='json',
        )
        self.assertEqual(review.status_code, 201)

        after_shipper_review = client.get(f'/api/shipper/trips/{self.trip.id}/')
        self.assertIs(after_shipper_review.json()['data']['shipper_rating'], True)

    def test_shipper_trip_list_uses_same_rating_flag(self):
        TripReview.objects.create(
            trip=self.trip,
            shipper=self.shipper,
            transporter=self.transporter,
            driver=self.driver,
            transporter_rating=4,
            driver_rating=5,
        )

        response = self._shipper_client().get('/api/shipper/trips/')
        self.assertEqual(response.status_code, 200)
        row = next(item for item in response.json()['data'] if item['id'] == self.trip.id)
        self.assertIs(row['shipper_rating'], True)
