from test.test_const import CONST_BASE_URL, CONST_PORT, CONST_SSL
from unittest import TestCase

import responses
from requests.exceptions import HTTPError

from pygrocydm import GrocyDataManager
from pygrocydm.battery import Battery
from pygrocydm.chore import Chore
from pygrocydm.equipment import Equipment
from pygrocydm.location import Location
from pygrocydm.product import Product
from pygrocydm.product_group import ProductGroup
from pygrocydm.quantity_unit import QuantityUnit
from pygrocydm.quantity_unit_conversion import QuantityUnitConversion
from pygrocydm.shopping_list import ShoppingList, ShoppingListItem
from pygrocydm.task import Task
from pygrocydm.task_category import TaskCategory
from pygrocydm.userentity import UserEntity
from pygrocydm.userfield import Userfield
from pygrocydm.userobject import UserObject


class TestGrocyDataManager(TestCase):

    def setUp(self):
        self.gdm = GrocyDataManager(CONST_BASE_URL, "api_key")
        self.gdm = None
        self.gdm = GrocyDataManager(CONST_BASE_URL, "demo_mode",  verify_ssl = CONST_SSL, port = CONST_PORT)

    def test_init(self):
        assert isinstance(self.gdm, GrocyDataManager)

    def test_products_valid(self):
        products = self.gdm.products().list
        assert isinstance(products, tuple)
        assert len(products) >=1
        for product in products:
            assert isinstance(product, Product)

    @responses.activate
    def test_products_invalid_no_data(self):
        resp = []
        responses.add(responses.GET,
            '{}:{}/api/objects/products'.format(CONST_BASE_URL, CONST_PORT),
            json=resp,
            status=200)
        products = self.gdm.products().list
        assert products is None

    @responses.activate
    def test_products_error(self):
        responses.add(responses.GET,
            '{}:{}/api/objects/products'.format(CONST_BASE_URL, CONST_PORT),
            status=400)
        self.assertRaises(HTTPError, self.gdm.products)

    def test_chores_valid(self):
        chores = self.gdm.chores().list
        assert isinstance(chores, tuple)
        assert len(chores) >=1
        for chore in chores:
            assert isinstance(chore, Chore)

    def test_locations_valid(self):
        locations = self.gdm.locations().list
        assert isinstance(locations, tuple)
        assert len(locations) >=1
        for location in locations:
            assert isinstance(location, Location)

    def test_batteries_valid(self):
        batteries = self.gdm.batteries().list
        assert isinstance(batteries, tuple)
        assert len(batteries) >=1
        for battery in batteries:
            assert isinstance(battery, Battery)

    def test_shopping_list_items_valid(self):
        shopping_list_items = self.gdm.shopping_list().list
        assert isinstance(shopping_list_items, tuple)
        assert len(shopping_list_items) >=1
        for items in shopping_list_items:
            assert isinstance(items, ShoppingListItem)

    def test_shopping_lists_valid(self):
        shopping_lists = self.gdm.shopping_lists().list
        assert isinstance(shopping_lists, tuple)
        assert len(shopping_lists) >=1
        for shopping_list in shopping_lists:
            assert isinstance(shopping_list, ShoppingList)

    def test_add_product_valid(self):
        product_list = self.gdm.products()
        old_len = len(product_list.list)
        new_product = {}
        new_product['name'] = 'Test product'
        new_product['location_id'] = 1
        new_product['qu_id_purchase'] = 1
        new_product['qu_id_stock'] = 1
        new_product['qu_factor_purchase_to_stock'] = 1
        new_product_id = product_list.add(new_product)
        new_len = len(product_list.list)
        assert isinstance(new_product_id, int)
        assert new_len == old_len + 1

    def test_add_product_error(self):
        product_list = self.gdm.products()
        new_product = {}
        new_product['name'] = 'Test product'
        self.assertRaises(HTTPError, product_list.add, new_product)

    def test_edit_product_valid(self):
        fields = {}
        fields['name'] = 'Test'
        assert not self.gdm.products().list[-1].edit(fields)

    def test_edit_product_error(self):
        fields = {}
        fields['nam'] = 'Test'
        product = self.gdm.products().list[0]
        self.assertRaises(HTTPError, product.edit, fields)

    def test_product_delete_valid(self):
        product = self.gdm.products().list[-1]
        old_len = len(self.gdm.products().list)
        assert not product.delete()
        self.gdm.products().refresh()
        new_len = len(self.gdm.products().list)
        assert new_len == old_len - 1

    def test_product_delete_error(self):
        product = self.gdm.products().list[-1]
        product.delete()
        self.assertRaises(HTTPError, product.delete)

    def test_search_product_valid(self):
        products = self.gdm.products().search("Co")
        assert isinstance(products, tuple)
        assert len(products) >=1
        for product in products:
            assert isinstance(product, Product)

    def test_search_product_invalid_no_data(self):
        products = self.gdm.products().search("Toto")
        assert products is None

    @responses.activate
    def test_search_product_error(self):
        url = '{}:{}/api/objects/products'.format(CONST_BASE_URL, CONST_PORT)
        responses.add_passthru(url)
        responses.add(responses.GET,
            '{}/search/error'.format(url),
            status=400)
        products = self.gdm.products()
        self.assertRaises(HTTPError, products.search, "error")

    def test_quantity_units_valid(self):
        quantity_units = self.gdm.quantity_units().list
        assert isinstance(quantity_units, tuple)
        assert len(quantity_units) >=1
        for quantity_unit in quantity_units:
            assert isinstance(quantity_unit, QuantityUnit)

    def test_tasks_valid(self):
        tasks = self.gdm.tasks().list
        assert isinstance(tasks, tuple)
        assert len(tasks) >=1
        for task in tasks:
            assert isinstance(task, Task)

    def test_task_categories_valid(self):
        task_categories = self.gdm.task_categories().list
        assert isinstance(task_categories, tuple)
        assert len(task_categories) >=1
        for task_category in task_categories:
            assert isinstance(task_category, TaskCategory)

    def test_product_groups_valid(self):
        product_groups = self.gdm.product_groups().list
        assert isinstance(product_groups, tuple)
        assert len(product_groups) >=1
        for product_group in product_groups:
            assert isinstance(product_group, ProductGroup)

    def test_quantity_unit_conversions_valid(self):
        quantity_unit_conversions = self.gdm.quantity_unit_conversions().list
        assert isinstance(quantity_unit_conversions, tuple)
        assert len(quantity_unit_conversions) >=1
        for quantity_unit_conversion in quantity_unit_conversions:
            assert isinstance(quantity_unit_conversion, QuantityUnitConversion)

    def test_equipment_valid(self):
        equipments = self.gdm.equipment().list
        assert isinstance(equipments, tuple)
        assert len(equipments) >=1
        for equipment in equipments:
            assert isinstance(equipment, Equipment)

    def test_userfields_valid(self):
        userfields = self.gdm.userfields().list
        assert isinstance(userfields, tuple)
        assert len(userfields) >=1
        for userfield in userfields:
            assert isinstance(userfield, Userfield)

    def test_userentities_valid(self):
        userentities = self.gdm.userentities().list
        assert isinstance(userentities, tuple)
        assert len(userentities) >=1
        for userentity in userentities:
            assert isinstance(userentity, UserEntity)

    def test_userobjects_valid(self):
        userobjects = self.gdm.userobjects().list
        assert isinstance(userobjects, tuple)
        assert len(userobjects) >=1
        for userobject in userobjects:
            assert isinstance(userobject, UserObject)
