# -*- encoding: utf-8 -*-

from datetime import date, datetime, timedelta       # timeSlices
from collections import OrderedDict

import django
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import redirect, resolve_url
from django.template import Template, RequestContext, loader
from django.template.loader import render_to_string
from django.shortcuts import render

from django.contrib.auth.decorators import login_required
from django.urls import reverse  
from django.views.decorators.csrf import ensure_csrf_cookie
from django.forms import ModelForm
from django.contrib import messages
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import pgettext, pgettext_lazy

from django.db import transaction
from django.db.models import F

from django.core.exceptions import ValidationError
from django.core.validators import validate_email

import logging
import bleach
import html2text

from django.conf import settings as appSettings

from . import models
from . import forms
from . import auth as nalodeni_auth

# Logger instance
logger = logging.getLogger(__name__)

def role_required(roles=[]):
    def decorate(func):
        def call(request, *args, **kwargs):
            for r in roles:
                if not r in request.session['site_perms']:
                    messages.error(request, "Nedostatečné oprávnění pro přístup. Detaily byly zaznamenány.")
                    return HttpResponseRedirect('/')
            result = func(request, *args, **kwargs)
            return result
        return call
    return decorate


@ensure_csrf_cookie
#@login_required(login_url="/prihlaseni")
#@role_required(['sso_news_list'])
def news_all(request):
    newsletters = models.Newsletter.objects.filter(is_del=False)

    site_perms = request.session.get('site_perms',[])
    actions = set()

    if 'sso_news_manage' in site_perms:
        actions.add('add_news_list')
        actions.add('news_list_actions')
        actions.add('news_list_details')
    if 'sso_kodo' in site_perms:
        actions.add('news_list_details')

    if len(actions) == 0:
        newsletters = newsletters.filter(enabled=True)

    template = 'news/list.html'
    context = {
        'newsletters' : newsletters,
        'actions' : actions,
        }

    return render(request, template, context)


@ensure_csrf_cookie
@login_required(login_url="/prihlaseni")
@role_required(['sso_news_list'])
def list_edit(request, lid=None):
    if lid is not None:
        obj = models.Newsletter.objects.filter(pk=lid, is_del=False)
        if len(obj) == 1:
            obj = obj[0]
        elif len(obj) == 0:
            obj = None
        else:
            1/0
    else:
        obj = None

    site_perms = request.session.get('site_perms',[])
    passed = False
    if (obj is not None and request.user == obj.managed_by) or 'sso_news_manage' in site_perms:
        passed = True

    if not passed:
        messages.error(request, _('Nedostatečné oprávnění.'))
        return redirect('nalodeni:news_all')

    if request.method == 'GET':
        form = forms.NewsletterForm(instance=obj)
    elif request.method == 'POST':
        form = forms.NewsletterForm(request.POST, instance=obj)

        if form.is_valid():
            if request.POST.get('del_item', 'ne') == "ano":
                form.instance.is_del = True
                form.instance.save()

                messages.info(request, "Záznam byl smazán.")
                return redirect('nalodeni:news_all')

            form.save()

            messages.info(request, "Údaje byly uloženy.")
            return redirect('nalodeni:news_all')

    template = 'news/list_edit.html'
    context = {
        'form' : form,
        'regions' : models.InterestRegion.objects.all(),
        'topics'  : models.UserTopic.objects.all(),
        'skills'  : models.UserSkill.objects.all(),
        }

    return render(request, template, context)


@ensure_csrf_cookie
def list_show(request, lid):
    """
    Seznam zpráv pro daný newsletter.
    """
    obj = models.Newsletter.objects.filter(pk=lid, is_del=False)
    if len(obj) == 1:
        obj=obj[0]
    else:
        return redirect('nalodeni:news_all')

    site_perms = request.session.get('site_perms',[])
    actions = set()

    if (request.user == obj.managed_by or 'sso_news_manage' in site_perms):
        actions.add('nwsl_edit')
    if (request.user in obj.sent_by.all() or request.user == obj.managed_by
            or 'sso_news_manage' in site_perms):
        actions.add('nwsl_details')
        actions.add('nwsl_actions')
    if 'sso_news_list_recipients' in site_perms:
        actions.add('show_newsletter_recipients')

    msgs = obj.newsmsg_set.filter(is_del=False)
    if 'nwsl_actions' not in actions:
        msgs = msgs.exclude(sent_ts=None)
        
    template = 'news/list_show.html'
    context = {
        'obj' : obj,
        'msgs' : msgs,
        'actions' : actions,
        }

    return render(request, template, context)


@ensure_csrf_cookie
@login_required(login_url="/prihlaseni")
@role_required(['sso_news_list_recipients'])
def list_show_recipients(request, lid):
    """
    Seznam příjemců pro daný newsletter.
    """
    obj = models.Newsletter.objects.filter(pk=lid, is_del=False)
    if len(obj) == 1:
        obj=obj[0]
    else:
        return redirect('nalodeni:news_all')

    site_perms = request.session.get('site_perms',[])
    actions = set()

    if not (request.user in obj.sent_by.all() or request.user == obj.managed_by
            or 'sso_news_manage' in site_perms):
        messages.error(request, _('Nedostatečné oprávnění.'))
        return redirect('nalodeni:news_all')

    recipients = obj.get_recip_users()
    recipients_cnt = len(recipients)
    template = 'news/list_show_recipients.html'
    context = {
        'obj' : obj,
        'msgs' : obj.newsmsg_set.filter(is_del=False),
        'recipients' : recipients,
        'recipients_cnt' : recipients_cnt,
        'actions' : actions,
        }

    return render(request, template, context)




@ensure_csrf_cookie
def msg_show(request, mid):
    """
    Detail zpravy newsletteru.
    """
    obj = models.NewsMsg.objects.filter(pk=mid,is_del=False)
    if len(obj) == 1:
        obj = obj[0]
    elif len(obj) == 0:
        obj = None
        messages.error("Objekt nenalezen.")
        return redirect('nalodeni:news_all')
    else:
        1/0

    site_perms = request.session.get('site_perms',[])
    actions = set()
    passed = False

    if (request.user in obj.news.sent_by.all()
            or request.user == obj.news.managed_by
            or 'sso_news_manage' in site_perms):
        actions.add('nwsl_actions')
        passed = True

    # zobrazit jiz odeslanou zpravu
    if obj.sent_ts is not None:
        passed = True

    if not passed:
        messages.error(request, _('Zpráva neexistuje, nebo nemáte dostatečné oprávnění k jejímu zobrazení.'))
        return redirect('nalodeni:news_all')

    template = 'news/msg_show.html'
    context = {
        'msg' : obj,
        'blocks' : obj.newsmsgblock_set.all(),
        'actions' : actions,
        }

    return render(request, template, context)


@ensure_csrf_cookie
@login_required(login_url="/prihlaseni")
def msg_edit(request, lid, mid=None):
    """
    Seznam zpráv pro daný newsletter.
    """
    if mid is not None:
        obj = models.NewsMsg.objects.filter(pk=mid, is_del=False)
        if len(obj) == 1:
            obj = obj[0]
        elif len(obj) == 0:
            obj = None
            return redirect('nalodeni:news_msg_create', lid=lid)
        else:
            1/0
    else:
        obj = None

    if obj is None:
        obj = models.NewsMsg(news_id=lid)

    site_perms = request.session.get('site_perms',[])
    actions = set()

    if not (request.user in obj.news.sent_by.all()
            or request.user == obj.news.managed_by
            or 'sso_news_manage' in site_perms):
        messages.error(request, _('Nedostatečné oprávnění pro vytvoření zprávy.'))
        return redirect('nalodeni:news_all')


    if request.method == 'GET':
        form = forms.NewsMsgForm(instance=obj)
    elif request.method == 'POST':
        form = forms.NewsMsgForm(request.POST, instance=obj)

        if form.is_valid():
            form.instance.created_by = request.user
            form.instance.created_ts = datetime.now()

            if request.POST.get('del_item', 'ne') == "ano":
                form.instance.is_del = True
                form.instance.save()

                messages.info(request, "Záznam byl smazán.")
                return redirect('nalodeni:news_list_show', lid=lid)

            form.instance.headerText = bleach.clean(form.instance.headerText,
                tags=['b','ul','ol','li','a','i','hr','br'], strip=True)
            form.instance.footerText = bleach.clean(form.instance.footerText,
                tags=['b','ul','ol','li','a','i','hr','br'], strip=True)

            form.instance.headerText = bleach.linkify(form.instance.headerText)
            form.instance.footerText = bleach.linkify(form.instance.footerText)
            form.save()

            messages.info(request, "Údaje byly uloženy.")
            return redirect('nalodeni:news_msg_show', mid=form.instance.id)

    template = 'news/msg_edit.html'
    context = {
        'form' : form,
        }

    return render(request, template, context)


@ensure_csrf_cookie
@login_required(login_url="/prihlaseni")
def msg_send(request, id, realSend=False):
    """
    Odeslani newsletteru.
    """
    obj = models.NewsMsg.objects.filter(pk=id,is_del=False)
    if len(obj) == 1:
        obj = obj[0]
    elif len(obj) == 0:
        obj = None
        messages.error("Objekt nenalezen.")
        return redirect('nalodeni:news_all')
    else:
        1/0

    site_perms = request.session.get('site_perms',[])
    actions = set()

    if not (request.user in obj.news.sent_by.all()
            or request.user == obj.news.managed_by
            or 'sso_news_manage' in site_perms):
        messages.error(request, _('Nedostatečné oprávnění.'))
        return redirect('nalodeni:news_all')

    if 'sso_news_manage' in site_perms:
        recipients_wanted = request.GET.get('recipients','test')
    else:
        recipients_wanted = "test"

    update_sent_ts = False
    use_public_to_email = False
    recipients_email = []
    recip_users = []
    if obj.sent_ts is None:     # jeste nerozeslano
        if recipients_wanted == 'all':
            update_sent_ts = True
            use_public_to_email = True
            recip_users = obj.news.get_recip_users()
        else:
            recip_users = [ request.user ]
    else:
        if recipients_wanted == "test":
            recip_users = [ request.user ]
        else:
            messages.error(request, "Zpráva již byla rozeslána.")
            return redirect('nalodeni:news_list_show', lid=obj.news_id)

    if obj.testMailRecipients is not None and recipients_wanted == "test":
        for eml in obj.testMailRecipients.split(","):
            try:
                eml = eml.strip()
                validate_email(eml)
                recipients_email.append(eml)
            except ValidationError:
                messages.error(request, "Testovací email %s není ve tvaru emailu." % (eml,) )

    for rcp in recip_users:
        # pouzivat KONTAKTNI email misto REGISTRACNIHO
        eml = rcp.email_contact_active
        if eml is None or len(eml.strip()) == 0:
            eml = rcp.email
        try:
            validate_email(eml)
            recipients_email.append(eml)
        except ValidationError:
            messages.error(request, "Email '%s' uživatele %s není ve správném tvaru." % (eml, rcp.username))

    template = 'news/msg_to_email.html'
    context = {
        'msg' : obj,
        'abs_host_url' : '%s://%s' % ( request.scheme, request.get_host()),
        'blocks' : obj.newsmsgblock_set.all(),
        }

    if realSend:
        from django.core.mail import get_connection, EmailMultiAlternatives
        import quopri

        mailgun_backend = get_connection('anymail.backends.mailgun.EmailBackend')

        header_from = '%s <%s>' % (
                appSettings.ANYMAIL['FROM_NAME'],
                appSettings.ANYMAIL['FROM_EMAIL'],
            )
        html_message = render_to_string(template, context)
        plain_message = html2text.html2text(html_message)

        ema = EmailMultiAlternatives(
                "%s - %s" % (obj.news.name, obj.title),
                plain_message, header_from )
        ema.connection = mailgun_backend

        if use_public_to_email:
            ema.to = [ appSettings.ANYMAIL['PUBLIC_TO_EMAIL'] ]
        else:
            # pouzit kontaktni nebo registracni email uzivatele
            eml = rcp.email_contact_active
            if eml is None or len(eml.strip()) == 0:
                eml = rcp.email
            ema.to = [ eml ]

        ema.bcc = recipients_email
        if obj.news.replyToEmail is not None:
            try:
                eml = obj.news.replyToEmail.strip()
                validate_email(eml)
                ema.extra_headers = {
                    'Reply-To' : eml,
                    }
            except ValidationError:
                messages.error(request, "Odpovědní email '%s' není ve tvaru emailu. Odesílání zrušeno." % (eml,) )
                messages.info(request, "Chybu může opravit správce tohoto newsletteru." )
                return redirect('nalodeni:news_list_show', lid=obj.news_id)

        ema.attach_alternative(html_message, "text/html")
        ema.send()

        if update_sent_ts:
            obj.sent_ts = datetime.now()
            obj.save()

        messages.info(request, "Zpráva odeslána pomocí MailGun celkem %s uživatelům." % len(recipients_email) )
    else:
        messages.error(request, "Message delivery disabled.")

    return redirect('nalodeni:news_list_show', lid=obj.news_id)


def msg_preview(request, id):
    """
    Verejny nahled newsletteru.
    """
    obj = models.NewsMsg.objects.filter(pk=id,is_del=False)
    if len(obj) == 1:
        obj = obj[0]
    elif len(obj) == 0:
        obj = None
        messages.error("Objekt nenalezen.")
        return redirect('nalodeni:news_all')
    else:
        1/0

    site_perms = request.session.get('site_perms',[])
    actions = set()

    passed = False
    if (request.user in obj.news.sent_by.all()
            or request.user == obj.news.managed_by
            or 'sso_news_manage' in site_perms):
        passed = True
    if obj.sent_ts is not None:
        passed = True

    if not passed:
        return redirect('nalodeni:news_all')


    template = 'news/msg_to_email.html'
    context = {
        'msg' : obj,
        'abs_host_url' : '%s://%s' % ( request.scheme, request.get_host()),
        'blocks' : obj.newsmsgblock_set.all(),
        }

    return render(request, template, context)



@ensure_csrf_cookie
@login_required(login_url="/prihlaseni")
def block_edit(request, mid, bid=None):
    """
    Seznam zpráv pro daný newsletter.
    """
    if bid is not None:
        obj = models.NewsMsgBlock.objects.filter(pk=bid, newsmsg_id=mid)
        if len(obj) == 1:
            obj = obj[0]
        elif len(obj) == 0:
            obj = None
            return redirect('nalodeni:news_block_create', mid=mid)
        else:
            1/0
    else:
        obj = None

    if obj is None:
        obj = models.NewsMsgBlock(newsmsg_id=mid)

    site_perms = request.session.get('site_perms',[])
    actions = set()

    if not (request.user in obj.newsmsg.news.sent_by.all()
            or request.user == obj.newsmsg.news.managed_by
            or 'sso_news_manage' in site_perms):
        messages.error(request, _('Nedostatečné oprávnění pro editaci bloku zprávy.'))
        return redirect('nalodeni:news_all')


    if request.method == 'GET':
        form = forms.NewsMsgBlockForm(instance=obj)
    elif request.method == 'POST':
        form = forms.NewsMsgBlockForm(request.POST, instance=obj)

        if form.is_valid():
            form.instance.content = bleach.clean(form.instance.content,
                tags=['b','ul','ol','li','a','i','hr'], strip=True)
            form.instance.content = bleach.linkify(form.instance.content)
            form.save()

            messages.info(request, "Údaje byly uloženy.")
            return redirect('nalodeni:news_msg_show', mid=mid)

    template = 'news/block_edit.html'
    context = {
        'form' : form,
        }

    return render(request, template, context)

@ensure_csrf_cookie
@login_required(login_url="/prihlaseni")
def block_delete(request, bid):
    """
    Seznam zpráv pro daný newsletter.
    """
    obj = models.NewsMsgBlock.objects.filter(pk=bid)
    if len(obj) == 1:
        obj = obj[0]
    elif len(obj) == 0:
        obj = None
        return redirect('nalodeni:news_all')
    else:
        1/0

    site_perms = request.session.get('site_perms',[])
    actions = set()

    if not (request.user in obj.newsmsg.news.sent_by.all()
            or request.user == obj.newsmsg.news.managed_by
            or 'sso_news_manage' in site_perms):
        messages.error(request, _('Nedostatečné oprávnění pro smazání bloku zprávy.'))
        return redirect('nalodeni:news_all')

    mid = obj.newsmsg_id
    obj.delete()

    messages.info(request, "Záznam byl smazán.")
    return redirect('nalodeni:news_msg_show', mid=mid)


