"""
This file holds the functions necesary to:

- Connect to seller's shop API
- Load information on seller [??]
- Load product information

"""
import logging
from io import BytesIO
import datetime

from woocommerce import API
import requests
from PIL import Image
from django.core.files import File

from bs4 import BeautifulSoup

from companies.models import Company
from products.models import Product
from products.serializers import ProductSerializer
from history.models import HistorySync


logging.basicConfig(
    filename='logs/woocommerce.log',
    filemode='w',
    format='%(levelname)s:%(message)s',
    level=logging.INFO,
    )


PRODUCT_FIELDS = [f.name for f in Product._meta.get_fields()]


def get_wcapi_instance(url, key, secret, version="wc/v3"):
    wcapi = API(
        url=url,
        consumer_key=key,
        consumer_secret=secret,
        wp_api=True,
        version=version
    )
    return wcapi


def create_imported_product(info, company, history, user):
    # extract m2m field data
    tags = [t.get('name') for t in info.pop('tags')]
    attributes = [t.get('name') for t in info.pop('attributes')]
    # prepare instance data
    instance_data = {
        'company':company.id,
        'creator': user.id if user is not None else None,
        'history': history.id,
        'url': info.get('permalink'),
        'stock': info.get('stock_quantity'),
        'name': info.get('name'),
        'description': BeautifulSoup(info.get('description', ''), "lxml").text,
        'sku': info.get('sku'),
        'price': None if info.get('price') == '' else info.get('price'),
        }

    # alternative method
    serializer = ProductSerializer(data=instance_data)
    if serializer.is_valid():
        # try:
        #     new = Product.objects.create(**serializer.validated_data)
        #     new.tags = tags
        #     new.attributes = attributes
        #     new.save()
        # except Exception as e:
        #     logging.error(f"Could not create product instance: {str(e)}")
        #     return None

        new, created = Product.objects.get_or_create(
            company=company, 
            creator=user if user is not None else None,
            history=history,
            url=instance_data['url'],
            stock=instance_data['stock'],
            name=instance_data['name'],
            description=instance_data['description'],
            sku=instance_data['sku'],
            price=instance_data['price']
            )
        new.tags = tags
        new.attributes = attributes
        new.save()
        if len(info['images']) > 0:
            try:
                # get image
                headers={"User-Agent" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"}
                image_url = info['images'][0]['src']
                response = requests.get(image_url, stream=True, headers=headers)
                assert(response.status_code==200)
                response.raw.decode_content = True
                image = Image.open(response.raw)
                # save using File object
                img_io = BytesIO()
                image.save(img_io, format=image.format)
                new.image.save(f"{new.name}-{new.sku}.{image.format.lower()}", File(img_io), save=False)
                new.save()
            except AssertionError as e:
                logging.error(f"Source image [{info['images'][0]['src']}] not reachable: {response.status_code}")
            except Exception as e:
                logging.error(f"Could not add image to product {new.sku} from [{info['images'][0]['src']}]: {str(e)}")
        else:
            logging.info(f"No image for Product {new.name}")
        return new
    else:
        logging.error(f"{serializer.errors}")
        return None


def migrate_shop_products(url, key, secret, user=None, version="wc/v3"):
    """Tries to connect to WooCommerce site @ url with given credentials

    If succesful, returns list of Product instances created

    """
    # get wcapi
    wcapi = get_wcapi_instance(url, key, secret, version)

    

    consumer_key = 'ck_565539bb25b472b1ff7a209eb157ca11c0a26397'
    consumer_secret = 'cs_9c1690ba5da0dd70f51d61c395628fa14d1a104c'

    # get company fom url
    company = Company.objects.filter(shop_link=url).first()

    if not company:
        logging.error(f"Could not find Company with URL: {url}")
        print(f"Could not find Company with URL: {url}")
        return None

    new_products = []
    page = 1
    attemps = 0
    error = False
    # list products
    while True:
        
        try:
            response = wcapi.get('products/', params={'per_page': 10, 'page': page})
            page += 1
            if response.status_code == 200:
                products = response.json()
            elif response.status_code == 401:
                logging.error(f"{response.status_code} [{response.url}]: {response.json()}")
                error = True
            else:
                logging.error(f"Could not load products from {response.url}: [{response.status_code}]")
                print(f"Could not load products fom {response.url}: [{response.status_code}]")
                error = True
        except requests.exceptions.ReadTimeout as e:
            logging.error(f"Timeout reading backend: {str(e)}")
            # skip and try next
            attemps += 1
            if attemps>4:
                break
            else:
                continue
        # exit loop if no more products
        if not products:
            break

        # create HistorySync instance and link to every product created
        history = HistorySync.objects.create(
            company=company,
            sync_date=datetime.datetime.now(),
        )
        counter = 0
        for product in products:
            # check if exists
            if product['sku'] and Product.objects.filter(sku=product['sku']).exists():
                # product already registered
                logging.info(f"Product with sku [{product['sku']}] already registered")
                print(f"Product with sku [{product['sku']}] already registered")
                # TODO: UPDATE instance??
                continue
            new = create_imported_product(product, company, history, user)
            if new is not None:
                new_products.append(new)
                counter += 1
                logging.info(f"Product '{new.name}' created")
                print(f"Product '{new.name}' created")

        # update history.quantity
        history.quantity = counter
        history.save()
        

    logging.info(f"Products created: {len(new_products)}")
    print(f"Products created: {len(new_products)}")

    return {"new_products": new_products, "error": error}





