import json
from io import BytesIO

import requests
import validators

from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import parse_servings, parse_servings_text, parse_time
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Recipe, Step


class RecipeSage(Integration):

    def get_recipe_from_file(self, file):

        recipe = Recipe.objects.create(
            name=file['name'].strip(),
            created_by=self.request.user, internal=True,
            space=self.request.space)

        if file['recipeYield'] != '':
            recipe.servings = parse_servings(file['recipeYield'])
            recipe.servings_text = parse_servings_text(file['recipeYield'])

        try:
            if 'totalTime' in file and file['totalTime'] != '':
                recipe.working_time = parse_time(file['totalTime'])

            if 'timePrep' in file and file['prepTime'] != '':
                recipe.working_time = parse_time(file['timePrep'])
                recipe.waiting_time = parse_time(file['totalTime']) - parse_time(file['timePrep'])
        except Exception as e:
            print('failed to parse time ', str(e))

        recipe.save()

        ingredient_parser = IngredientParser(self.request, True)
        ingredients_added = False
        for s in file['recipeInstructions']:
            step = Step.objects.create(
                instruction=s['text'], space=self.request.space,
            )
            if not ingredients_added:
                ingredients_added = True

                for ingredient in file['recipeIngredient']:
                    amount, unit, food, note = ingredient_parser.parse(ingredient)
                    f = ingredient_parser.get_food(food)
                    u = ingredient_parser.get_unit(unit)
                    step.ingredients.add(Ingredient.objects.create(
                        food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
                    ))
            recipe.steps.add(step)

        if len(file['image']) > 0:
            try:
                url = file['image'][0]
                if validators.url(url, public=True):
                    response = requests.get(url)
                    self.import_recipe_image(recipe, BytesIO(response.content))
            except Exception as e:
                print('failed to import image ', str(e))

        return recipe

    def get_file_from_recipe(self, recipe):
        data = {
            '@context': 'http://schema.org',
            '@type': 'Recipe',
            'creditText': '',
            'isBasedOn': '',
            'name': recipe.name,
            'description': recipe.description,
            'prepTime': str(recipe.working_time),
            'totalTime': str(recipe.waiting_time + recipe.working_time),
            'recipeYield': str(recipe.servings),
            'image': [],
            'recipeCategory': [],
            'comment': [],
            'recipeIngredient': [],
            'recipeInstructions': [],
        }

        for s in recipe.steps.all():
            data['recipeInstructions'].append({
                '@type': 'HowToStep',
                'text': s.instruction
            })

            for i in s.ingredients.all():
                data['recipeIngredient'].append(f'{float(i.amount)} {i.unit} {i.food}')

        return data

    def get_files_from_recipes(self, recipes, el, cookie):
        json_list = []
        for r in recipes:
            json_list.append(self.get_file_from_recipe(r))

            el.exported_recipes += 1
            el.msg += self.get_recipe_processed_msg(r)
            el.save()

        return [[self.get_export_file_name('json'), json.dumps(json_list)]]

    def split_recipe_file(self, file):
        return json.loads(file.read().decode("utf-8"))
