# -*- coding: utf-8 -*-

import json
import logging
from datetime import datetime
from unittest import TestCase

from distribution.controllers import Feed, FeedDetail, FeedDetailPost
from distribution import app
from distribution.models.feed import FeedItem
from . import utils
from ..utils import get_consumer_post_data, get_stored_data

logging.disable(logging.CRITICAL)


class ITControllerTestCase(TestCase):
    controller = None

    def setUp(self):
        self.context = app
        self.context.config['DEBUG'] = True
        self.context.config['TESTING'] = True
        self.app = app.test_client()

    def tearDown(self):
        FeedItem.manager.clear()


class ITControllerCreateOnSetUpTestCase(ITControllerTestCase):
    def setUp(self):
        super(ITControllerCreateOnSetUpTestCase, self).setUp()
        utils.create_feed(data=get_consumer_post_data(), datetime=datetime.utcnow())


class ITFeedTestCase(ITControllerCreateOnSetUpTestCase):
    controller = Feed

    def test_json_get_all(self):
        res = self.app.get('/feed/v1/?format=json')
        self.assertEquals(200, res.status_code)
        items = json.loads(res.data)
        self.assertEquals('news:ab121241-de46-4776-a2b5-ece310a40aad', items[0]['id'])
        self.assertEquals(len(items), 1)


class ITFeedDetailTestCase(ITControllerCreateOnSetUpTestCase):
    controller = FeedDetail

    def test_get_existent(self):
        res = self.app.get('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aad/')
        self.assertEquals(res.status_code, 200)
        item = json.loads(res.data)
        self.assertEquals(item['id'], 'news:ab121241-de46-4776-a2b5-ece310a40aad')
        self.assertEquals(item['title'], 'Exclusive: Lost City Discovered in the Honduran Rain Forest')

    def test_get_non_existent(self):
        res = self.app.get('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aax/')
        self.assertEquals(res.status_code, 404)

    def test_get_disabled(self):
        res = self.app.delete('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aad/')
        self.assertEquals(res.status_code, 204)

        res = self.app.get('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aad/')
        self.assertEquals(res.status_code, 404)

    def test_put_existent(self):
        res = self.app.put('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aad/',
                           data=json.dumps({'title': 'The new title', 'abstract': 'The new abstract'}),
                           content_type='application/json')
        self.assertEquals(res.status_code, 200)

        res = self.app.get('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aad/')
        self.assertEquals(res.status_code, 200)
        item = json.loads(res.data)
        self.assertEquals(item['title'], 'The new title')
        self.assertEquals(item['abstract'], 'The new abstract')

    def test_put_non_existent(self):
        res = self.app.put('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aax/',
                           data=json.dumps({'title': 'The new title', 'abstract': 'The new abstract'}),
                           content_type='application/json')
        self.assertEquals(res.status_code, 404)

    def test_put_disabled(self):
        self.app.delete('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aad/')

        res = self.app.put('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aad/',
                           data=json.dumps({'title': 'The new title', 'abstract': 'The new abstract'}),
                           content_type='application/json')
        self.assertEquals(res.status_code, 404)

    def test_put_invalid_input(self):
        res = self.app.put('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aad/',
                           data='CRASH!',
                           content_type='application/json')
        self.assertEquals(res.status_code, 422)

    def test_put_invalid_fields(self):
        res = self.app.put('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aad/',
                           data=json.dumps({'title': 'The new title', 'inexistent': 'This field is invalid'}),
                           content_type='application/json')
        self.assertEquals(res.status_code, 200)

        res = self.app.get('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aad/')
        self.assertEquals(res.status_code, 200)
        item = json.loads(res.data)
        self.assertEquals(item['title'], 'The new title')

    def test_delete_existent(self):
        res = self.app.delete('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aad/')
        self.assertEquals(res.status_code, 204)

        item = FeedItem.manager.get('news:ab121241-de46-4776-a2b5-ece310a40aad')
        self.assertTrue(item.is_deleted())

    def test_delete_non_existent(self):
        res = self.app.delete('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aax/')
        self.assertEquals(res.status_code, 404)

    def test_delete_disabled(self):
        res = self.app.delete('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aad/')
        self.assertEquals(res.status_code, 204)

        res = self.app.delete('/api/v1/item/news:ab121241-de46-4776-a2b5-ece310a40aad/')
        self.assertEquals(res.status_code, 404)


class ITFeedDetailPostTestCase(ITControllerTestCase):
    controller = FeedDetailPost

    def _post_feed_item(self):
        item_data = get_stored_data()[0]
        item_data['meta'].pop('domain', None)
        return self.app.post('/api/v1/item/',
                             data=json.dumps({'item': item_data,
                                              'domain': 'news'}),
                             content_type='application/json')

    def test_post_existent(self):
        self._post_feed_item()
        res = self._post_feed_item()
        self.assertEquals(res.status_code, 409)

    def test_post_non_existent(self):
        res = self._post_feed_item()
        self.assertEquals(res.status_code, 201)

    def test_post_disabled(self):
        self._post_feed_item()
        res = self.app.delete('/api/v1/item/news:fba75b9c-3dcb-4ea7-bd32-9b3716d65692/')
        self.assertEquals(res.status_code, 204)

        res = self._post_feed_item()
        self.assertEquals(res.status_code, 201)

    def test_put_invalid_input(self):
        res = self.app.post('/api/v1/item/',
                            data='CRASH!',
                            content_type='application/json')
        self.assertEquals(res.status_code, 422)
