# coding: utf-8

import logging
from hashlib import md5

from django.conf import settings
from django.template import loader
from rest_framework.response import Response
from startrek_client.exceptions import StartrekError, StartrekServerError

from procu.api import models
from procu.api.enums import LINK
from procu.api.tasks import sync_remotes
from procu.api.utils import get_tracker_client
from procu.rest import exceptions, generics
from procu.rest.metadata.mixins import CreateMetaMixin
from procu.rest.permissions import EntryPermission, StaffOnly
from .permissions import WarehousePermission
from .serializers import Create, get_context

logger = logging.getLogger(__name__)


class WarehouseView(CreateMetaMixin, generics.RetrieveAPIView):
    lookup_url_kwarg = 'quote_id'
    serializer_class = Create
    permission_classes = (StaffOnly, EntryPermission, WarehousePermission)

    def get_queryset(self):
        return models.Quote.objects.permitted(self.request.user).filter(
            request__enquiry=self.kwargs['enquiry_id']
        )

    def retrieve(self, request, *args, **kwargs):
        enquiry_id = self.kwargs['enquiry_id']
        quote_id = self.kwargs['quote_id']
        context = get_context(request.user, enquiry_id, quote_id)
        return Response(context)

    def post(self, request, *args, **kwargs):

        quote = self.object
        rfx = quote.request

        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        data = serializer.validated_data

        client = get_tracker_client()
        queue_name = settings.WAREHOUSE_QUEUE

        data['agent'] = quote.supplier.legal_name
        data['url'] = settings.FRONT_INTERNAL_PREFIX
        data['enquiry_key'] = rfx.key

        body = loader.render_to_string('warehouse.txt', context={'data': data})
        body = '\n'.join(filter(None, body.split('\n')))

        issue_kwargs = dict(
            queue=queue_name,
            type={'name': 'Task'},
            description=body,
            tags=['procu'],
            createdBy=self.request.user.username,
            deadline=data['delivery_at'].strftime('%Y-%m-%d'),
            attachments=[a.file for a in data['attachments']],
        )

        # ----------------------------------------------------------------------

        issue_kwargs['followers'] = followers = data['followers']

        # Add delivery address contacts as followers
        for contact in data['address'].contacts:
            if contact.get('username'):
                followers.append(contact['username'])

        # ----------------------------------------------------------------------

        try:
            worktype_field = client.fields.get('logisticsWorktype')

            worktype_options = worktype_field.optionsProvider['values']['LOGIC']

            if 'Приемка' in worktype_options:
                issue_kwargs['logisticsWorktype'] = 'Приемка'

        except (StartrekError, KeyError, ValueError):
            logger.exception('Could not set worktype')

        # ----------------------------------------------------------------------

        try:
            loc_field = client.fields.get(settings.WAREHOUSE_LOC_FIELD)

            loc_options = loc_field.optionsProvider['values']['LOGIC']
            assert 'OTHER' in loc_options

            location = data['address'].tracker_location
            location = location if (location in loc_options) else 'OTHER'

            issue_kwargs[settings.WAREHOUSE_LOC_FIELD] = location

        except (StartrekError, KeyError, ValueError):
            logger.exception('Could not set location')

        # ----------------------------------------------------------------------

        try:
            org_field = client.fields.get(settings.WAREHOUSE_ORG_FIELD)

            org_options = org_field.optionsProvider['values']['LOGIC']

            org = data['legal_entity'].tracker_field

            if org in org_options:
                issue_kwargs[settings.WAREHOUSE_ORG_FIELD] = org

        except (StartrekError, KeyError, ValueError):
            logger.exception('Could not set legal entity')

        # ----------------------------------------------------------------------

        try:
            cmpts = {c['name'] for c in client.queues[queue_name]['components']}
            issue_kwargs['components'] = list(
                cmpts.intersection(data['address'].tracker_components)
            )

        except (StartrekError, KeyError):
            logger.exception('Could not set components')

        # ----------------------------------------------------------------------

        try:
            subject = 'Приемка в {}: {}'.format(
                issue_kwargs[settings.WAREHOUSE_LOC_FIELD], data['subject']
            )

        except KeyError:
            subject = 'Приемка: {}'.format(data['subject'])

        issue_kwargs['summary'] = subject

        # ----------------------------------------------------------------------

        issue_kwargs['unique'] = md5((subject + body).encode()).hexdigest()

        # ----------------------------------------------------------------------

        try:
            issue = client.issues.create(**issue_kwargs)

        except StartrekServerError as exc:
            errors = exc.error_messages

            if exc.errors:
                errors.extend(f'{f}: {v}' for f, v in exc.errors.items())

            if not errors:
                errors.append('Could not create ticket')

            raise exceptions.ValidationError({'detail': errors})

        except Exception:
            logger.exception('Could not create ticket in LOGIC')
            raise exceptions.ValidationError(
                {'detail': 'Could not create ticket'}
            )

        sync_remotes.apply_async(
            kwargs={
                'enquiry_id': rfx.enquiry_id,
                'link_to': [issue.key],
                'unlink_from': [],
            }
        )

        # ----------------------------------------------------------------------

        models.Link.objects.get_or_create(
            enquiry_id=rfx.enquiry_id,
            key=issue.key,
            defaults={'type': LINK.TRACKER, 'author': request.user},
        )

        # ----------------------------------------------------------------------

        return Response(
            {'key': issue.key, 'summary': subject, 'description': body}
        )
