# passerelle.contrib.teamnet_axel
# Copyright (C) 2015  Entr'ouvert
#
# This program 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 program 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 program.  If not, see <http://www.gnu.org/licenses/>.

import json

from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import DetailView as GenericDetailView
from django.http import HttpResponse, HttpResponseNotFound

from passerelle import utils

from .models import Management, Link, AxelException
from . import soap

class ManagementDetailView(GenericDetailView):
    model = Management
    template_name = 'passerelle/contrib/teamnet_axel/detail.html'


class DetailView(GenericDetailView):
    model = Management

    def get_data(self, request, *args, **kwargs):
        raise NotImplementedError

    @utils.protected_api('can_access')
    @utils.to_json('api')
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        return self.get_data(request, *args, **kwargs)


class PingView(DetailView):
    def get_data(self, request, *args, **kwargs):
        client = soap.get_client(self.object)
        res = {'ping': 'pong'}
        if 'debug' in request.GET:
            res['client'] = soap.client_to_jsondict(client)
        return res


class AuthView(DetailView):
    def get_data(self, request, *args, **kwargs):
        login = request.GET.get('login')
        pwd = request.GET.get('password')
        return self.object.auth(login, pwd)


class LinkView(DetailView):
    def get_data(self, request, *args, **kwargs):
        nameid = request.GET.get('NameID')
        if not nameid:
            raise AxelException('NameID required')
        login = request.GET.get('login')
        pwd = request.GET.get('password')
        user = self.object.auth(login, pwd)
        if not user:
            raise AxelException('authentication failed')
        if not 'idfamille' in user:
            raise AxelException('user without idfamille')
        famille = self.object.get_famille(user['idfamille'])
        Link.objects.update_or_create(resource=self.object,
                nameid=nameid, defaults={'login': login, 'pwd': pwd})
        user['_famille'] = famille
        user['_nameid'] = nameid
        return user


class UnlinkView(DetailView):
    def get_data(self, request, *args, **kwargs):
        nameid = request.GET.get('NameID')
        if not nameid:
            raise AxelException('NameID required')
        logins = [v['login'] for v in Link.objects.filter(resource=self.object, nameid=nameid).values('login')]
        Link.objects.filter(resource=self.object, nameid=nameid).delete()
        if logins:
            return {'login_was': logins}
        else:
            return None


class FamilyView(DetailView):
    def get_family_id(self, request):
        nameid = request.GET.get('NameID')
        if not nameid:
            raise AxelException('NameID required')
        links = Link.objects.filter(resource=self.object, nameid=nameid)
        if len(links) > 1:
            raise AxelException('multiple links')
        if not links:
            return None
        user = self.object.auth(links[0].login, links[0].pwd)
        if not user:
            raise AxelException('authentication failed')
        if not 'idfamille' in user:
            raise AxelException('user without idfamille')
        return user['idfamille']

    def get_data(self, request, *args, **kwargs):
        family_id = self.get_family_id(request)
        if not family_id:
            return
        famille = self.object.get_famille(family_id)
        if not 'key' in kwargs:
            return famille
        else:
            return famille.get(kwargs['key'])


class InvoicesView(FamilyView):

    def get_data(self, request, regie_id, **kwargs):
        return self.object.get_payable_invoices(regie_id, self.get_family_id(request))


class HistoryInvoicesView(FamilyView):

    def get_data(self, request, regie_id, **kwargs):
        return self.object.get_historical_invoices(regie_id, self.get_family_id(request))


class InvoiceView(DetailView):

    def get_data(self, request, *args, **kwargs):
        return self.object.get_invoice(kwargs['regie_id'], kwargs['invoice_id'])


class InvoicePDFView(DetailView):

    def get_data(self, request, *args, **kwargs):
        invoice_id = kwargs['invoice_id']
        pdf = self.object.get_invoice_pdf(invoice_id)
        if not pdf:
            return HttpResponseNotFound()

        response = HttpResponse(content_type='application/pdf')
        response['Content-Disposition'] = 'attachment; filename="%s.pdf"' % invoice_id
        response.write(pdf)
        return response


class InvoicePayView(DetailView):

    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(InvoicePayView, self).dispatch(*args, **kwargs)

    @utils.to_json('api')
    @utils.protected_api('can_access')
    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        data = json.loads(request.body)
        return self.object.pay_invoice(kwargs['regie_id'],
                    kwargs['invoice_id'], data['transaction_id'],
                    data['transaction_date'])
