from unittest.mock import patch

import base64

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

from accounts.models import KYCDocument, TransporterDriverLink, TransporterProfile, UserRole

User = get_user_model()

_TINY_PNG = (
    'data:image/png;base64,'
    + base64.b64encode(
        b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01'
        b'\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89'
        b'\x00\x00\x00\nIDATx\x9cc\x00\x01\x00\x00\x05\x00\x01\r\n-\xdb'
        b'\x00\x00\x00\x00IEND\xaeB`\x82'
    ).decode()
)


class FleetDriverCreateApiTests(APITestCase):
    def setUp(self):
        self.fleet_owner = User.objects.create_user(
            'fleet-owner@test.com',
            email='fleet-owner@test.com',
            password='secret',
        )
        UserRole.objects.create(
            user=self.fleet_owner,
            role=UserRole.Role.TRANSPORTER,
            phone='03000000001',
            language='en',
        )
        TransporterProfile.objects.create(
            user=self.fleet_owner,
            account_type=TransporterProfile.AccountType.FLEET_OWNER,
            country_to_country=True,
            local=False,
            documents_verified=True,
            tc_id='1',
        )
        token, _ = Token.objects.get_or_create(user=self.fleet_owner)
        self.client = APIClient()
        self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token.key}')

    @patch('api.serializers.create_traccar_device', return_value={'id': 999})
    @patch('api.serializers.generate_unique_tc_uid', return_value='TC999')
    def test_create_fleet_driver_inherits_owner_load_type_flags(self, _mock_uid, _mock_traccar):
        response = self.client.post(
            '/api/transporter/drivers/',
            {
                'email': 'new-fleet-driver@test.com',
                'password': 'secret123',
                'first_name': 'Fleet',
                'last_name': 'Driver',
                'phone': '03000000099',
            },
            format='json',
        )

        self.assertEqual(response.status_code, 201, response.content)
        driver = User.objects.get(username='new-fleet-driver@test.com')
        profile = driver.transporter_profile
        self.assertEqual(profile.account_type, TransporterProfile.AccountType.TRANSPORTER_DRIVER)
        self.assertTrue(profile.country_to_country)
        self.assertFalse(profile.local)
        self.assertTrue(
            TransporterDriverLink.objects.filter(
                transporter=self.fleet_owner,
                driver=driver,
                is_active=True,
            ).exists()
        )

    @patch('api.serializers.create_traccar_device', return_value={'id': 1001})
    @patch('api.serializers.generate_unique_tc_uid', return_value='TC1001')
    def test_create_fleet_driver_with_documents_and_expiry(self, _mock_uid, _mock_traccar):
        response = self.client.post(
            '/api/transporter/drivers/',
            {
                'email': 'docs-fleet-driver@test.com',
                'password': 'secret123',
                'first_name': 'Docs',
                'last_name': 'Driver',
                'documents': [
                    {
                        'document_type': 'DRIVER_LICENSE',
                        'file': _TINY_PNG,
                        'file_back': _TINY_PNG,
                        'expiry_date': '2027-12-31',
                    },
                    {
                        'document_type': 'PASSPORT_COPY',
                        'file': _TINY_PNG,
                        'passport_number': 'FD-PASS-001',
                        'expiry_date': '2030-01-15',
                    },
                ],
            },
            format='json',
        )
        self.assertEqual(response.status_code, 201, response.content)
        data = response.json()['data']
        types = {d['document_type']: d for d in data['documents']}
        self.assertIn('DRIVER_LICENSE', types)
        self.assertIn('PASSPORT_COPY', types)
        self.assertEqual(types['DRIVER_LICENSE']['expiry_date'], '2027-12-31')
        self.assertEqual(types['PASSPORT_COPY']['expiry_date'], '2030-01-15')
        self.assertEqual(types['PASSPORT_COPY']['passport_number'], 'FD-PASS-001')
        self.assertTrue(types['DRIVER_LICENSE']['file_url'])
        self.assertTrue(types['DRIVER_LICENSE']['file_back_url'])
        driver = User.objects.get(username='docs-fleet-driver@test.com')
        self.assertEqual(KYCDocument.objects.filter(user=driver).count(), 2)

    @patch('api.serializers.create_traccar_device', return_value={'id': 1002})
    @patch('api.serializers.generate_unique_tc_uid', return_value='TC1002')
    def test_patch_and_documents_endpoint_upsert_expiry(self, _mock_uid, _mock_traccar):
        create = self.client.post(
            '/api/transporter/drivers/',
            {
                'email': 'patch-docs-driver@test.com',
                'password': 'secret123',
                'documents': [
                    {
                        'document_type': 'PERMIT',
                        'file': _TINY_PNG,
                        'expiry_date': '2026-08-01',
                    },
                ],
            },
            format='json',
        )
        self.assertEqual(create.status_code, 201, create.content)
        driver_id = create.json()['data']['id']

        patch = self.client.patch(
            f'/api/transporter/drivers/{driver_id}/',
            {
                'documents': [
                    {'document_type': 'PERMIT', 'expiry_date': '2026-09-01'},
                ],
            },
            format='json',
        )
        self.assertEqual(patch.status_code, 200, patch.content)
        permit = next(d for d in patch.json()['data']['documents'] if d['document_type'] == 'PERMIT')
        self.assertEqual(permit['expiry_date'], '2026-09-01')

        upload = self.client.post(
            f'/api/transporter/drivers/{driver_id}/documents/',
            {
                'document_type': 'COUNTRY_GCC',
                'file': _TINY_PNG,
                'file_back': _TINY_PNG,
                'expiry_date': '2028-03-01',
            },
            format='json',
        )
        self.assertEqual(upload.status_code, 201, upload.content)
        self.assertEqual(upload.json()['data']['document_type'], 'COUNTRY_GCC')
        self.assertEqual(upload.json()['data']['expiry_date'], '2028-03-01')

        listed = self.client.get(f'/api/transporter/drivers/{driver_id}/documents/')
        self.assertEqual(listed.status_code, 200)
        types = {d['document_type'] for d in listed.json()['data']}
        self.assertEqual(types, {'PERMIT', 'COUNTRY_GCC'})

    @patch('api.serializers.create_traccar_device', return_value={'id': 1003})
    @patch('api.serializers.generate_unique_tc_uid', return_value='TC1003')
    def test_fleet_driver_rejects_company_document_type(self, _mock_uid, _mock_traccar):
        create = self.client.post(
            '/api/transporter/drivers/',
            {
                'email': 'bad-doc-driver@test.com',
                'password': 'secret123',
                'documents': [
                    {'document_type': 'COMPANY_REGISTRATION', 'file': _TINY_PNG},
                ],
            },
            format='json',
        )
        self.assertEqual(create.status_code, 400, create.content)
        self.assertIn('documents', create.json()['error'])
        self.assertFalse(User.objects.filter(username='bad-doc-driver@test.com').exists())

    @patch('api.serializers.create_traccar_device', return_value={'id': 1004})
    @patch('api.serializers.generate_unique_tc_uid', return_value='TC1004')
    def test_fleet_driver_rejects_vehicle_registration_document(self, _mock_uid, _mock_traccar):
        create = self.client.post(
            '/api/transporter/drivers/',
            {
                'email': 'vr-doc-driver@test.com',
                'password': 'secret123',
                'documents': [
                    {
                        'document_type': 'VEHICLE_REGISTRATION',
                        'file': _TINY_PNG,
                        'file_back': _TINY_PNG,
                    },
                ],
            },
            format='json',
        )
        self.assertEqual(create.status_code, 400, create.content)
        self.assertIn('documents', create.json()['error'])
        self.assertFalse(User.objects.filter(username='vr-doc-driver@test.com').exists())

        ok = self.client.post(
            '/api/transporter/drivers/',
            {
                'email': 'vr-doc-driver@test.com',
                'password': 'secret123',
            },
            format='json',
        )
        self.assertEqual(ok.status_code, 201, ok.content)
        driver_id = ok.json()['data']['id']
        upload = self.client.post(
            f'/api/transporter/drivers/{driver_id}/documents/',
            {
                'document_type': 'VEHICLE_REGISTRATION',
                'file': _TINY_PNG,
                'file_back': _TINY_PNG,
            },
            format='json',
        )
        self.assertEqual(upload.status_code, 400, upload.content)
        self.assertIn('document_type', upload.json()['error'])
