from datetime import datetime, timedelta
import uuid
from casexml.apps.case.models import CommCareCase
from corehq.apps.api.es import ReportCaseES, ReportXFormES
from corehq.apps.reports.filters.base import BaseSingleOptionFilter
from corehq.apps.reports.generic import GenericTabularReport
from corehq.apps.reports.standard import CustomProjectReport, ProjectReportParametersMixin, DatespanMixin

from pact.enums import PACT_DOMAIN, PACT_CASE_TYPE, XMLNS_DOTS_FORM
from pact.models import PactPatientCase, DOTSubmission, CObservation
from pact.reports.dot_calendar import DOTCalendarReporter


class PactDOTPatientField(BaseSingleOptionFilter):
    slug = "dot_patient"
    label = "DOT Patient"
    default_option = "Select DOT Patient"

    @property
    def options(self):
        patient_cases = self.get_pact_cases()
        case_type = self.request.GET.get(self.slug, '')

        self.selected = case_type
        self.options = [
            dict(val=case['_id'], text="(%s) - %s" % (case.get('pactid.#value', '[none]'), case['name']))
            for case in patient_cases]

    @classmethod
    def get_pact_cases(cls):
        #query couch to get reduce count of all PACT cases
        case_es = ReportCaseES(PACT_DOMAIN)
        total_count = CommCareCase.get_db().view('hqcase/types_by_domain',
                                                 key=["pact", PACT_CASE_TYPE]).first().get('value', 100)
        fields = ['_id', 'name', 'pactid.#value']
        query = case_es.base_query(terms={'type': PACT_CASE_TYPE},
                                   fields=fields,
                                   start=0,
                                   size=total_count)
        query['filter']['and'].append({"prefix": {"dot_status.#value": "dot"}})

        results = case_es.run_query(query)
        for res in results['hits']['hits']:
            yield res['fields']


class PactDOTReport(GenericTabularReport, CustomProjectReport, ProjectReportParametersMixin,
                    DatespanMixin):
    label = "DOT Patient List"
    slug = "dots"

    report_template_path = "pact/dots/dots_report.html"
    flush_layout = True
    fields = ['pact.reports.dot.PactDOTPatientField', 'corehq.apps.reports.filters.dates.DatespanFilter']

    @property
    def report_context(self):
        ret = {}
        if not self.request.GET.has_key('dot_patient') or self.request.GET.get('dot_patient') == "":
            self.report_template_path = "pact/dots/dots_report_nopatient.html"
            return ret
        submit_id = self.request.GET.get('submit_id', None)
        ret['dot_case_id'] = self.request.GET['dot_patient']
        casedoc = PactPatientCase.get(ret['dot_case_id'])
        ret['patient_case'] = casedoc
        start_date_str = self.request.GET.get('startdate',
                                              (datetime.utcnow() - timedelta(days=7)).strftime(
                                                  '%Y-%m-%d'))
        end_date_str = self.request.GET.get('enddate', datetime.utcnow().strftime("%Y-%m-%d"))

        start_date = datetime.strptime(start_date_str, "%Y-%m-%d")
        end_date = datetime.strptime(end_date_str, "%Y-%m-%d")

        ret['startdate'] = start_date_str
        ret['enddate'] = end_date_str

        dcal = DOTCalendarReporter(casedoc, start_date=start_date, end_date=end_date, submit_id=submit_id)
        ret['dot_calendar'] = dcal

        unique_visits = dcal.unique_xforms()
        xform_es = ReportXFormES(PACT_DOMAIN)

        q = xform_es.base_query(size=len(unique_visits))
        lvisits = list(unique_visits)
        if len(lvisits) > 0:
            q['filter']['and'].append({"ids": {"values": lvisits}})
            #todo double check pactid/caseid matches
        q['sort'] = {'received_on': 'desc'}
        res = xform_es.run_query(q)

        #ugh, not storing all form data by default - need to get?
        ret['sorted_visits'] = [DOTSubmission.wrap(x['_source']) for x in
                                filter(lambda x: x['_source']['xmlns'] == XMLNS_DOTS_FORM,
                                       res['hits']['hits'])]
        return ret



@@ -389,16 +389,70 @@
 panMixin
+%0Afrom dimagi.utils.decorators.memoized import memoized
 %0A%0Afrom p
@@ -793,32 +793,46 @@
 %0A%0A    @property%0A
+    @memoized%0A
     def options(
@@ -850,159 +850,14 @@
     
-patient_cases = self.get_pact_cases()%0A        case_type = self.request.GET.get(self.slug, '')%0A%0A        self.selected = case_type%0A        self.options =
+return
  %5B%0A 
@@ -989,22 +989,129 @@
  in 
-patient_cases%5D
+self.get_pact_cases()%0A        %5D%0A%0A    @property%0A    def selected(self):%0A        return self.request.GET.get(self.slug, '')
 %0A%0A  
@@ -1163,16 +1163,17 @@
        #
+ 
 query co

fix pact DOT admin report