from datetime import timedelta

from rest.serializers import ReportTemplateSerializer
from core.views import ModelListViewBase, LoginRequiredMixin, SimpleCreateViewBase, DetailedModelViewBase
from core.views import SimpleUpdateViewBase
from .models import ReportTemplate
from users.models import HEAD_OF_LAB_ID, LAB_GROUP_ID


class ReportTemplateListView(LoginRequiredMixin, ModelListViewBase):
    serializer = ReportTemplateSerializer
    require_group = HEAD_OF_LAB_ID


class ReportTemplateDetailView(LoginRequiredMixin, DetailedModelViewBase):
    model = ReportTemplate
    require_group = HEAD_OF_LAB_ID


class ReportTemplateCreateView(LoginRequiredMixin, SimpleCreateViewBase):
    model = ReportTemplate
    require_group = HEAD_OF_LAB_ID


class ReportTemplateUpdateView(LoginRequiredMixin, SimpleUpdateViewBase):
    model = ReportTemplate
    require_group = HEAD_OF_LAB_ID

# report creation forms and stuff

from django.views.generic import TemplateView
from projects.models import Project
from .forms import ProjectReportTemplateSelectForm


class ProjectReportSetupView(LoginRequiredMixin, TemplateView):
    template_name = 'report_template/create.html'
    project = None

    require_group = LAB_GROUP_ID

    def dispatch(self, request, *args, **kwargs):
        # grab pk from url and fetch the project object
        pk = self.kwargs.get('pk', None)
        self.project = Project.objects.get(pk=pk)
        return super(ProjectReportSetupView, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        ctx = super(ProjectReportSetupView, self).get_context_data(**kwargs)
        # query all the things! filter out stuff without a measurement, else this might break
        # the query string later on
        qs = self.project.samples.filter(measurements__isnull=False).prefetch_related('measurements')
        samples = dict()
        for sample in qs:
            samples[sample.pk] = {'sample': sample, 'measurements': sample.measurements.all()}
        ctx['samples'] = samples
        ctx['object'] = self.project
        ctx['form'] = ProjectReportTemplateSelectForm()  # template selection drop down
        ctx['has_templates'] = ReportTemplate.objects.all().count() > 0
        return ctx


from measurements.models import Measurement


class ReportCreatorView(LoginRequiredMixin, TemplateView):
    template_name = 'report_template/template.html'

    require_group = LAB_GROUP_ID

    def get_context_data(self, **kwargs):

        ctx = super(ReportCreatorView, self).get_context_data(**kwargs)

        ctx.update({'commentsColumn': self.request.GET.get('commentsColumn', False),
                    'remarksColumn': self.request.GET.get('remarksColumn', False)})

        sort_key = self.request.GET.get('order_by', '')

        measurement_keys = self.request.GET.get('mkeys', None).split(',')
        measurements = Measurement.objects.filter(pk__in=measurement_keys).order_by(sort_key). \
            prefetch_related('sample', 'sample__contained_in', 'rounds'). \
            values('sample', 'sample__reference', 'sample__contained_in__name', 'sample__name',
                   'finished_at', 'comments', 'pk', 'compliant_result',
                   'sample__sampled_at', 'analysis_result')

        ctx['measurements'] = measurements

        template_object = \
            ReportTemplate.objects.get(pk=self.request.GET.get('report_template', None))

        operator_list = list()
        # pimp up the query dicts from above by looking up additional stuff
        for m in measurements:
            mobject = Measurement.objects.get(pk=m['pk'])
            m['predilution'] = mobject.sample.total_dilution

            # pull in result adjust with predilution
            if mobject.analysis_result is not None:
                m['result'] = m['predilution'] * mobject.analysis_result
            else:  # make sure to avoid key errors on result
                m['result'] = None

            # lookup the number of panelist included in the measurement and the total
            # amount of ites

            # just throw the primary key of every panelist which took part in an non excluded round
            # into set, the size will later tell how many unique panelist where around
            unique_panel = set()
            ite_count = 0
            for mround in mobject.rounds.all():
                if mround.is_included:
                    for sr in mround.results.all():
                        if sr.valid:
                            unique_panel.add(sr.panelist_id)
                            ite_count += 1

            m['ite_count'] = ite_count
            m['panelist_count'] = len(unique_panel)

            # while we're at it, insert the automated remarks
            # non standard compliance wins above all
            if mobject.standard_identifier <= 0:
                m['remark'] = template_object.not_standard_compliant_remark
            # no team (~ no standard compliance)
            elif m['result'] is not None and m['result'] < template_object.lower_threshold:
                m['remark'] = template_object.lower_threshold_remark
            elif m['result'] is None and mobject.analysis_result is not None:
                m['remark'] = template_object.insufficient_volume_remark
            elif mobject.sample.supplier is not None:
                m['remark'] = template_object.client_bag_remark
            # late analysis
            elif mobject.finished_at > (mobject.sample.sampled_at + timedelta(hours=30)):
                m['remark'] = template_object.late_analysis_text
            else:
                m['remark'] = None

            for r in mobject.rounds.all():
                operator_list.append(r.operator)

        ctx['lab_tech_list'] = map(lambda x: x.first_name[0] + x.last_name[0], set(operator_list))

        project_pk = self.request.GET.get('project', None)
        project = Project.objects.select_related('client', 'contact').filter(id=project_pk). \
            values('contact', 'contact__first_name', 'contact__last_name', 'client', 'reference',
                   'client__zip', 'client__city', 'client__address', 'client__country',
                   'client__client__name', 'name', 'client__phone', 'project_manager__first_name',
                   'project_manager__last_name', 'project_manager').first()

        # via history object, grab creator and time of this project item
        from history.models import HistoryEntry
        from django.contrib.contenttypes.models import ContentType

        # we know at least on entry is around, since someone had to create this stuff, right?
        history = HistoryEntry.objects.filter(content_type=ContentType.objects.get_for_model(Project),
                                              object_id=project_pk).order_by('timestamp').first()

        ctx['created_at'] = history.timestamp
        ctx['created_by'] = '{0}. {1}'.format(self.request.user.first_name[:1],
                                              self.request.user.last_name)

        if project['contact']:
            ctx['contact_person_client'] = '{0}. {1}'.format(project['contact__first_name'][:1],
                                                             project['contact__last_name'])
        else:
            ctx['contact_person_client'] = None

        if project['project_manager']:
            ctx['project_manager'] = '{0}. {1}'.format(project['project_manager__first_name'][:1],
                                                       project['project_manager__last_name'])
        else:
            ctx['project_manager'] = None

        ctx['project'] = project

        # pull in template
        ctx['template'] = template_object
        if template_object.header_logo:
            ctx['header_logo'] = template_object.header_logo.url

        if template_object.footer_logo:
            ctx['footer_logo'] = template_object.footer_logo.url

        use_sig = self.request.GET.get('signature_choice', None)

        if use_sig == 'user' and self.request.user.signature:
            ctx['signature'] = self.request.user.signature.url
        elif use_sig == 'template' and template_object.signature:
            ctx['signature'] = template_object.signature.url
        else:
            ctx['signature'] = None

        ctx['header_text'] = template_object.header_text.splitlines()
        ctx['footer_text'] = template_object.footer_text.splitlines()
        ctx['samples_second_page'] = template_object.sample_list_second_page

        return ctx

