from pprint import pprint

from django.db.models import Q, F

from establishment.models import Establishment
from location.models import Address
from product.models import PurchasedProduct, Product
from transfer.models import Establishments, Dishes, EstablishmentNotes, \
                            EstablishmentMerchandises
from transfer.serializers.establishment import EstablishmentSerializer, \
                                               EstablishmentNoteSerializer
from transfer.serializers.plate import PlateSerializer


def transfer_establishment():
    result = []

    # todo: filter(location__city__name__icontains='paris')
    old_establishments = Establishments.objects.exclude(
        id__in=list(Establishment.objects.all().values_list('old_id', flat=True))
    ).prefetch_related(
        'establishmentinfos_set',
        'schedules_set',
        'descriptions_set',
    )

    for item in old_establishments:
        data = {
            'old_id': item.id,
            'name': item.name,
            'transliterated_name': item.index_name,
            'slug': item.slug,
            'type': item.type,
            'phone': item.phone,
            'created': item.created_at,
            'state': item.state,
            'description': {},
            'website': None,
            'facebook': None,
            'twitter': None,
            'lafourchette': None,
            'booking': None,
            'schedules': None,
            'email': None,
        }

        if item.location:
            data.update({
                'location': item.location.id,
                'tz': item.location.timezone or 'UTC',
            })

        # Инфо
        info = item.establishmentinfos_set.first()
        if info:
            data.update({
                'website': info.website,
                'facebook': info.facebook,
                'twitter': info.twitter,
                'lafourchette': info.lafourchette,
                'booking': info.booking_url,
                'email': info.email,
            })

        # Время работы
        schedule = item.schedules_set.first()
        if schedule:
            data.update({
                'schedules': schedule.timetable,
            })

        # Описание
        descriptions = item.descriptions_set.all()
        for description in descriptions:
            data['description'].update({
                description.locale: description.text,
            })

        result.append(data)

    serialized_data = EstablishmentSerializer(data=result, many=True)
    if serialized_data.is_valid():
        serialized_data.save()
    else:
        pprint(f"Establishment serializer errors: {serialized_data.errors}")


def transfer_menu():
    dishes = Dishes.objects.exclude(
        Q(establishment_id__isnull=True) |
        Q(dish_type__isnull=True) |
        Q(price__isnull=True) |
        Q(currency__isnull=True) |
        Q(name__isnull=True) |
        Q(name__exact='')
    ).annotate(
        country_code=F('establishment__location__country_code'),
    )

    serialized_data = PlateSerializer(data=list(dishes.values()), many=True)
    if serialized_data.is_valid():
        serialized_data.save()
    else:
        pprint(f"Menu serializer errors: {serialized_data.errors}")

        
def transfer_establishment_addresses():
    old_establishments = Establishments.objects.only("id", "location_id").exclude(
        Q(type='Wineyard') |
        Q(location__timezone__isnull=True)
    )

    for old_establishment in old_establishments:
        try:
            establishment = Establishment.objects.get(old_id=old_establishment.id)
        except Establishment.DoesNotExist:
            continue

        try:
            location = Address.objects.get(old_id=old_establishment.location_id)
        except Address.MultipleObjectsReturned:
            location = Address.objects.filter(old_id=old_establishment.location_id).first()
        except Address.DoesNotExist:
            continue

        establishment.address = location
        establishment.save()


def transfer_establishment_note():
    errors = []
    queryset = EstablishmentNotes.objects.exclude(text__exact='') \
                                         .exclude(text__isnull=True) \
                                         .exclude(establishment_id__isnull=True)
    serialized_data = EstablishmentNoteSerializer(
      data=list(queryset.values()),
      many=True)
    if serialized_data.is_valid():
        serialized_data.save()
    else:
        for d in serialized_data.errors: errors.append(d) if d else None
        pprint(f"transfer_establishment_note errors: {errors}")


def transfer_purchased_plaques():
    update_products_counter = 0
    already_updated_counter = 0
    not_existed_establishment_counter = 0

    purchased = EstablishmentMerchandises.objects.values_list(
        'establishment_id',
        'merchandise__vintage',
        'gifted',
        'quantity'
    )
    for old_est_id, vintage, gifted, quantity in purchased:
        establishment_qs = Establishment.objects.filter(old_id=old_est_id)
        product_qs = Product.objects.filter(name='Plaque restaurants',
                                            vintage=vintage)
        if establishment_qs.exists() and product_qs.exists():
            product = product_qs.first()
            establishment = establishment_qs.first()

            purchases, created = PurchasedProduct.objects.get_or_create(
                establishment=establishment,
                product=product,
                is_gifted=gifted,
                quantity=quantity
            )
            if created:
                update_products_counter += 1
            else:
                already_updated_counter += 1
        else:
            not_existed_establishment_counter += 1

    print(f'Updated products: {update_products_counter}\n'
          f'Already updated: {already_updated_counter}\n'
          f'Not existed establishment: {not_existed_establishment_counter}')


data_types = {
    "establishment": [
        transfer_establishment,
    ],
    "establishment_note": [transfer_establishment_note],
    "location_establishment": [
        transfer_establishment_addresses
    ],
    "menu": [transfer_menu],
    "purchased_plaques": [
        transfer_purchased_plaques
    ],
}
