import logging
from decimal import Decimal
from django.conf import settings
from core.models import Product, OrderLine

logger = logging.getLogger(__name__)

class Cart:
    def __init__(self, request):
        self.session = request.session
        cart = self.session.get(settings.CART_SESSION_ID)
        if not cart:
            cart = self.session[settings.CART_SESSION_ID] = {}
        self.cart = cart

    def add(self, product, quantity=1, roast='', other='', update_quantity=False):
        product_id = str(product.id)
        if product_id not in self.cart:
            self.cart[product_id] = {
                'quantity': 0,
                'roast': roast,
                'other': other,
                'price': str(product.price)
            }
        elif product_id in self.cart:
            self.cart[product_id].update({
                'roast': roast,
                'other': other,
            })
        if update_quantity:
            self.cart[product_id]['quantity'] = quantity
        else:
            self.cart[product_id]['quantity'] += quantity
        self.save()

    def save(self):
        self.session[settings.CART_SESSION_ID] = self.cart
        self.session.modified = True
        logger.info(f'\nCart:\n{self.cart}\n')

    def remove(self, product):
        product_id = str(product.id)
        if product_id in self.cart:
            del self.cart[product_id]
            self.save()

    def __iter__(self):
        product_ids = self.cart.keys()
        products = Product.objects.filter(id__in=product_ids)
        for product in products:
            self.cart[str(product.id)]['product'] = product

        for item in self.cart.values():
            item['price'] = Decimal(item['price'])
            item['total_price'] = item['price'] * item['quantity']
            yield item

    def __len__(self):
        return sum(item['quantity'] for item in self.cart.values())

    def get_total_price(self):
        return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values())

    def clear(self):
        del self.session[settings.CART_SESSION_ID]
        self.session.modified = True

    def get_bulk_list_and_body_data(self, order, shipping_address=None):
        bulk_list = []

        body_data = {
            'intent': 'CAPTURE',
            'purchase_units': [{
                'amount': {
                    'currency_code': 'USD',
                    'value': f'{self.get_total_price()}',
                    'breakdown': {
                        # Required when including the `items` array
                        'item_total': {
                            'currency_code': 'USD',
                            'value': f'{self.get_total_price()}'
                        }
                    }
                },
                'items': []
            }]
        }

        if shipping_address:
            body_data['purchase_units'][0]['shipping'] = self.process_shipping_address(shipping_address)

        for item in self:
            body_data['purchase_units'][0]['items'].append({
                # Shows within upper-right dropdown during payment approval
                'name': f'{item["product"]}',
                # Item details will also be in the completed paypal.com transaction view
                'description': 'Coffee',
                'unit_amount': {
                    'currency_code': 'USD',
                    'value': f'{item["price"]}'
                },
                'quantity': f'{item["quantity"]}'
            })

            bulk_list.append(
                OrderLine(
                    order=order,
                    product=item['product'],
                    customer_note=f'{item["roast"]} {item["other"]}',
                    unit_price=item['price'],
                    quantity=item['quantity'],
                    tax_rate=2,
                )
            )

        return bulk_list, body_data

    def process_shipping_address(self, address):
        shipping = {
            'address': {
                'address_line_1': f'{address["street_address_1"]}',
                'address_line_2': f'{address["street_address_2"]}',
                'admin_area_2': f'{address["city"]}',
                'admin_area_1': f'{address["state"]}',
                'postal_code': f'{address["postal_code"]}',
                'country_code': 'US'
            }
        }
        return shipping

    # @property
    # def coupon(self):
    #   if self.coupon_id:
    #       return Coupon.objects.get(id=self.coupon_id)
    #   return None

    # def get_discount(self):
    #   if self.coupon:
    #       return (self.coupon.discount / Decimal('100')) * self.get_total_price()
    #   return Decimal('0')

    # def get_total_price_after_discount(self):
    #   return self.get_total_price() - self.get_discount()
