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

# Copyright(C) 2015      Oleg Plakhotniuk
#
# This file is part of a woob module.
#
# This woob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This woob module is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this woob module. If not, see <http://www.gnu.org/licenses/>.


import re
from datetime import datetime
from decimal import Decimal
from itertools import count, takewhile

from woob.browser import URL, LoginBrowser, need_login
from woob.browser.pages import HTMLPage
from woob.capabilities.base import Currency
from woob.capabilities.shop import Item, Order, OrderNotFound, Payment
from woob.exceptions import BrowserIncorrectPassword
from woob.tools.capabilities.bank.transactions import AmericanTransaction as AmTr

__all__ = ['Ideel']


class IdeelPage(HTMLPage):
    @property
    def logged(self):
        return bool(self.doc.xpath('//a[@href="/logout"]'))


class LoginPage(IdeelPage):
    def login(self, username, password):
        form = self.get_form(xpath='//form[@id="iform"]')
        form['login'] = username
        form['password'] = password
        form.submit()


class HistoryPage(IdeelPage):
    def exists(self):
        return bool(self.doc.xpath('//table[@id="order_history"]'))

    def iter_orders(self):
        return (tr.xpath('td[1]/a/text()')[0][1:]
                for tr in self.doc.xpath('//table[@id="order_history"]/tbody/tr'))


class OrderPage(IdeelPage):
    def exists(self):
        return bool(self.order_number())

    def order(self):
        order = Order(id=self.order_number())
        order.date = self.order_date()
        order.tax = self.tax()
        order.shipping = self.shipping()
        order.discount = self.discount()
        order.total = self.total()
        return order

    def items(self):
        for tr in self.doc.xpath('//table[contains(@class,"items_table")]'
                                 '//tr[td[@class="items_desc"]]'):
            label = tr.xpath('*//div[@class="item_desc"]//span/text()')[0]
            url = tr.xpath('*//div[@class="item_img"]//@src')[0]
            onclk = tr.xpath('*//div[@class="item_img"]//@onclick')
            if onclk:
                url = re.match(r'window.open\(\'([^\']*)\'.*', onclk[0]).group(1)
            if url.startswith('/'):
                url = self.browser.BASEURL + url
            price = tr.xpath('td[@class="items_price"]/span/text()')[0]
            qty = tr.xpath('td[@class="items_qty"]//span/text()')[0]
            price = AmTr.decimal_amount(price) * Decimal(qty)
            item = Item()
            item.label = label
            item.url = url
            item.price = price
            yield item

    def payments(self):
        # There's no payment information on Ideel, so we'll make one up.
        p = Payment()
        p.date = self.order_date()
        p.method = u'DEFAULT PAYMENT'
        p.amount = self.total()
        yield p

    def order_number(self):
        return next(iter(self.doc.xpath(
            u'//b[text()="Order Number:"]/../strong/text()')), None)

    def order_date(self):
        txt = self.doc.xpath('//div[@id="purchase-notice"]/text()')[0]
        date = re.match(r'.* (\w+ \d+, \d+)$', txt).group(1)
        return datetime.strptime(date, '%b %d, %Y')

    def tax(self):
        return AmTr.decimal_amount(self.doc.xpath(
            '//span[@id="taxes"]/text()')[0])

    def shipping(self):
        if self.doc.xpath('//tr[@id="shipping_fee_row"]'
                          '//span[@class="free_shipping"]'):
            amount = '0'
        else:
            amount = self.doc.xpath('//span[@id="shipping_fee"]/text()')[0]
        return AmTr.decimal_amount(amount)

    def discount(self):
        TAGS = ['coupon_discount_amount', 'promo_discount_amount',
                'total_rewards', 'applied_credit']
        return -sum(AmTr.decimal_amount(x[1:][:-1]) for tag in TAGS
                    for x in self.doc.xpath('//span[@id="%s"]/text()' % tag))

    def total(self):
        return AmTr.decimal_amount(self.doc.xpath(
            '//span[@id="total"]/text()')[0])


class Ideel(LoginBrowser):
    BASEURL = 'http://www.ideel.com'
    login = URL(r'https://www.ideel.com/login$', LoginPage)
    history = URL(r'/my_account/orders\?page=(?P<page>\d+)$', HistoryPage)
    order = URL(r'/my_account/orders/(?P<order>\d+)$', OrderPage)
    unknown = URL(r'/.*$', IdeelPage)

    def get_currency(self):
        # Ideel uses only U.S. dollars.
        return Currency.get_currency(u'$')

    @need_login
    def get_order(self, id_):
        if self.order.go(order=id_).exists():
            return self.page.order()
        raise OrderNotFound()

    @need_login
    def iter_orders(self):
        exists = HistoryPage.exists
        hists = takewhile(exists, (self.history.go(page=i) for i in count(1)))
        return (self.get_order(x) for h in hists for x in h.iter_orders())

    @need_login
    def iter_payments(self, order):
        return self.order.stay_or_go(order=order.id).payments()

    @need_login
    def iter_items(self, order):
        return self.order.stay_or_go(order=order.id).items()

    def do_login(self):
        self.login.stay_or_go().login(self.username, self.password)
        if not self.page.logged:
            raise BrowserIncorrectPassword()
