import datetime

import requests
from django.conf import settings
from django.db.models import Sum, IntegerField
from django.db.models.functions import Coalesce
from django.utils import timezone

from api.models import Customer, SaleRecord, Business, Redeem


def filter_fields(data: dict) -> dict:
    filtered_data = dict()
    for key in data.keys():
        value = data.get(key)
        if value is None:
            continue
        if isinstance(value, str) and value == '':
            continue
        if isinstance(value, list) and len(value) == 0:
            continue
        if isinstance(value, dict) and len(value.keys()) == 0:
            continue
        filtered_data[key] = value
    return filtered_data


def update_user(instance: Customer) -> None:
    if settings.WEBENGAGE_ENABLED:
        products = list(SaleRecord.objects.filter(
            customer=instance, products__isnull=False).values_list('products__name', flat=True).distinct())
        total_amount = SaleRecord.objects.filter(customer=instance).aggregate(
            total=Coalesce(Sum('amount'), 0, output_field=IntegerField())).get('total')
        attributes = filter_fields(dict(
            businessID=instance.business.id,
            businessName=instance.business.name,
            businessPhone=instance.business.phone,
            businessAddress=instance.business.address,
            businessCountry=instance.business.country.name,
            businessWebsite=instance.business.web_site,
            businessInstagram=instance.business.instagram,
            businessIndustry=instance.business.industry.name,
            businessAddressLink=instance.business.address_link,
            businessPurchaseLink=instance.business.purchase_link,
            countryCode='+' + instance.country_code,
            totalAmount=total_amount,
            loyaltyWeight=instance.loyalty_weight,
            loyaltyModel=instance.business.get_loyalty_model_display(),
            phoneVerification=1 if instance.phone_verification else 0,
            language='en-us',  # FIXME: change to be dynamic
            usedProducts=products,
            rollingDateOfBirth=instance.dob.replace(year=datetime.date.today().year).strftime(
                '%Y-%m-%dT00:00:01+0400') if instance.dob else None
        ))
        data = filter_fields(dict(userId=instance.pk,
                                  firstName=instance.full_name,
                                  birthDate=instance.dob.strftime('%Y-%m-%dT00:00:01+0000') if instance.dob else None,
                                  gender=instance.get_gender_display(),
                                  email=instance.email,
                                  phone='+' + instance.country_code + instance.mobile,
                                  country=instance.business.country.name,
                                  #   time_zone='utc', # FIXME: fix time zone
                                  attributes=attributes
                                  ))
        url = f'https://api.webengage.com/v1/accounts/{settings.WEBENGAGE_LICENSE_CODE}/users'
        headers = {'Authorization': settings.WEBENGAGE_API_KEY,
                   'Content-Type': 'application/json'}

        try:
            print(f'update data {data}')
            res = requests.post(url=url, json=data, headers=headers)
            print(f'update {res.content}')
        except Exception as e:
            print(str(e))


def purchase_event(products: list, amount, delivery_date: datetime.datetime, customer_id: str,
                   first_purchase: bool = False, send_source: str = None, is_verified: bool = False,
                   rate: int = None) -> None:
    if settings.WEBENGAGE_ENABLED:
        customer: Customer = Customer.objects.filter(id=customer_id).first()
        loyalty_program = customer.business.loyalty_model != Business.REWARDS_PRICE_TYPE.OFF and is_verified
        loyalty_model = None
        if customer.business.loyalty_model != Business.REWARDS_PRICE_TYPE.OFF:
            loyalty_model = customer.business.loyalty_model_label
        if amount:
            amount = int(amount)
        if len(products) > 0:
            product = products[0]
        else:
            product = None
        points = None
        if amount and loyalty_program:
            point_divider = customer.business.point_amount_value
            if point_divider > 0:
                points = int(amount / point_divider)

        event_name = 'Purchase'
        event_data = filter_fields(dict(
            products=product,
            amount=amount,
            currency='AED',
            deliveryDate=delivery_date.strftime('%Y-%m-%dT%H:%M:%S+0400') if delivery_date else None,
            submitionDate=timezone.now().strftime("%Y-%m-%dT%H:%M:%S%z"),
            source=send_source,
            firstPurchase=first_purchase,
            loyaltyProgram=loyalty_program,
            userVerificationCode=customer.validation_code,
            loyaltyModel=loyalty_model,
            remainedLoyaltyWeight=customer.loyalty_weight + points if points else customer.loyalty_weight,
            loyaltyWeight=points
        ))
        data = filter_fields(dict(
            userId=customer_id,
            eventName=event_name,
            eventTime=timezone.now().strftime("%Y-%m-%dT%H:%M:%S%z"),
            eventData=event_data
        ))

        url = f'https://api.webengage.com/v1/accounts/{settings.WEBENGAGE_LICENSE_CODE}/events'
        headers = {'Authorization': settings.WEBENGAGE_API_KEY,
                   'Content-Type': 'application/json'}
        try:
            print(f'purchase data {data}')
            res = requests.post(url=url, json=data, headers=headers)
            print(f'purchase {res.content}')
        except Exception as e:
            print(str(e))

        if rate:
            survey_event(rate=rate, customer_id=customer_id, latency=1)


def survey_event(rate: int, customer_id: str, latency: int = 0) -> None:
    if settings.WEBENGAGE_ENABLED and rate:
        event_name = 'Survey'
        event_data = filter_fields(dict(
            score=rate
        ))

        data = filter_fields(dict(
            userId=customer_id,
            eventName=event_name,
            eventTime=(timezone.now() + datetime.timedelta(minutes=latency)).strftime("%Y-%m-%dT%H:%M:%S%z"),
            eventData=event_data
        ))

        url = f'https://api.webengage.com/v1/accounts/{settings.WEBENGAGE_LICENSE_CODE}/events'
        headers = {'Authorization': settings.WEBENGAGE_API_KEY,
                   'Content-Type': 'application/json'}
        try:
            print(f'survey data {data}')
            res = requests.post(url=url, json=data, headers=headers)
            print(f'survey {res.content}')
        except Exception as e:
            print(str(e))


def redeem_event(redeem: Redeem) -> None:
    if settings.WEBENGAGE_ENABLED:
        reward = redeem.reward
        customer = redeem.customer

        event_name = 'Redeem'
        event_data = filter_fields(dict(
            rewardName=reward.name,
            loyaltyWeight=reward.loyalty_weight,
            remainedLoyaltyWeight=customer.loyalty_weight,
            loyaltyModel=customer.business.loyalty_model_label,
            refrence=redeem.id
        ))

        data = filter_fields(dict(
            userId=customer.id,
            eventName=event_name,
            eventTime=timezone.now().strftime("%Y-%m-%dT%H:%M:%S%z"),
            eventData=event_data
        ))

        url = f'https://api.webengage.com/v1/accounts/{settings.WEBENGAGE_LICENSE_CODE}/events'
        headers = {'Authorization': settings.WEBENGAGE_API_KEY,
                   'Content-Type': 'application/json'}
        try:
            print(f'redeem data {data}')
            res = requests.post(url=url, json=data, headers=headers)
            print(f'redeem {res.content}')
        except Exception as e:
            print(str(e))


def login_event(customer: Customer) -> None:
    if settings.WEBENGAGE_ENABLED:

        event_name = 'Login'
        event_data = filter_fields(dict(
            userVerificationCode=customer.validation_code
        ))

        data = filter_fields(dict(
            userId=customer.id,
            eventName=event_name,
            eventTime=timezone.now().strftime("%Y-%m-%dT%H:%M:%S%z"),
            eventData=event_data
        ))

        url = f'https://api.webengage.com/v1/accounts/{settings.WEBENGAGE_LICENSE_CODE}/events'
        headers = {'Authorization': settings.WEBENGAGE_API_KEY,
                   'Content-Type': 'application/json'}
        try:
            print(f'login data {data}')
            res = requests.post(url=url, json=data, headers=headers)
            print(f'login {res.content}')
        except Exception as e:
            print(str(e))


def verification_event(customer: Customer) -> None:
    if settings.WEBENGAGE_ENABLED:

        event_name = 'MobileVerification'
        event_data = None

        data = filter_fields(dict(
            userId=customer.id,
            eventName=event_name,
            eventTime=timezone.now().strftime("%Y-%m-%dT%H:%M:%S%z"),
            eventData=event_data
        ))

        url = f'https://api.webengage.com/v1/accounts/{settings.WEBENGAGE_LICENSE_CODE}/events'
        headers = {'Authorization': settings.WEBENGAGE_API_KEY,
                   'Content-Type': 'application/json'}
        try:
            print(f'verification data {data}')
            res = requests.post(url=url, json=data, headers=headers)
            print(f'verification {res.content}')
        except Exception as e:
            print(str(e))


def profile_event(customer: Customer) -> None:
    if settings.WEBENGAGE_ENABLED:

        event_name = 'Profile'
        event_data = None

        data = filter_fields(dict(
            userId=customer.id,
            eventName=event_name,
            eventTime=timezone.now().strftime("%Y-%m-%dT%H:%M:%S%z"),
            eventData=event_data
        ))

        url = f'https://api.webengage.com/v1/accounts/{settings.WEBENGAGE_LICENSE_CODE}/events'
        headers = {'Authorization': settings.WEBENGAGE_API_KEY,
                   'Content-Type': 'application/json'}
        try:
            print(f'profile data {data}')
            res = requests.post(url=url, json=data, headers=headers)
            print(f'profile {res.content}')
        except Exception as e:
            print(str(e))
