from datetime import date, datetime
import os

from django.conf import settings
from django.contrib import admin
from django.contrib.auth.models import User
from django.db import models
from django.db.models import Q
from django.utils.timezone import now
from pytz import timezone

localtz = timezone(settings.TIME_ZONE)


def get_current_date():
    return localtz.normalize(now()).date()


def get_current_datetime():
    return localtz.normalize(now())


# proxy class for convenience and UI
class Dojo_User(User):
    class Meta:
        proxy = True

    def get_full_name(self):
        """
        Returns the first_name plus the last_name, with a space in between.
        """
        full_name = '%s %s (%s)' % (self.first_name,
                                    self.last_name,
                                    self.username)
     
   return full_name.strip()

    def __unicode__(self):
        return self.get_full_name()


class Contact(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()
    team = models.CharField(max_length=100)
    is_admin = models.BooleanField(default=False)
    is_globally_read_only = models.BooleanField(default=False)
    updated = models.DateTimeField(editable=F
alse)


class Product_Type(models.Model):
    name = models.CharField(max_length=300)

    def findings_count(self):
        findings = Finding.objects.filter(active=True, mitigated__isnull=True,
                                          false_p=False, verified=True)
        findings = findings.filter(Q(severity="Critical") |
                                   Q(severity="High") |
                                   Q(severity="Medium") |
                                   Q(severity="Low"))
        findings = findings.filter(test__engagement__product__prod_type=self)
        return len(findings)

    def products_count(self):
        products = Product.objects.filter(prod_type=self)
        return len(products)

    def __unicode__(self):
        return self.name


class Product_Line(models.Model):
    name = models.CharField(max_length=300)
    description = models.CharField(max_length=2000)

    def __unicode__(self):
        return self.name


class Report_Type(models.Model):
    name = models.CharField(max_length=300)


class Test_Type(models.Model):
    name = models.CharField(max_length=200)

    def __unicode__(self):
        return self.name


class Product(models.Model):
    name = models.CharField(max_length=300)
    description = models.CharField(max_length=2000)
    prod_manager = models.CharField(default=0, max_length=200)
    tech_contact = models.CharField(default=0, max_length=200)
    manager = models.CharField(default=0, max_length=200)
    created = models.DateTimeField(editable=False, null=True, blank=True)
    prod_type = models.ForeignKey(Product_Type, related_name='prod_type',
                                  null=True, blank=True)
    updated = models.DateTimeField(editable=False, null=True, blank=True)
    tid = models.IntegerField(default=0, editable=False)
    authorized_users = models.ManyToManyField(User, null=True, blank=True)

    def __unicode__(self):
        return self.name

    class Meta:
        ordering = ('name',)

    @property
    def findings_count(self):
        findings = Finding.objects.filter(active=True, mitigated__isnull=True,
                                          false_p=False, verified=True)
        e = Engagement.objects.filter(product=self)
        f_count = 0
        for engagement in e:
            t = Test.objects.filter(engagement=engagement)
            for test in t:
                f_count += findings.filter(test=test).count()
        return f_count

    @property
    def endpoint_count(self):
        return Endpoint.objects.filter(finding__test__engagement__product=self,
                                       finding__active=True,
                                       finding__verified=True,
                                       finding__mitigated__isnull=True).distinct().count()

    def open_findings(self, start_date=None, end_date=None):
        if start_date is None or end_date is None:
            return {}
        else:
            critical = Finding.objects.filter(test__engagement__product=self,
                                              active=True,
                                              mitigated__isnull=True,
                                              false_p=False, verified=True,
                                              severity="Critical",
                                              date__range=[start_date,
                                                           end_date]).count()
            high = Finding.objects.filter(test__engagement__product=self,
                                          active=True, mitigated__isnull=True,
                                          false_p=False, verified=True,
                                          severity="High",
                                          date__range=[start_date,
                                                       end_date]).count()
            medium = Finding.objects.filter(test__engagement__product=self,
                                            active=True,
                                            mitigated__isnull=True,
                                            false_p=False, verified=True,
                                            severity="Medium",
                                            date__range=[start_date,
                                                         end_date]).count()
            low = Finding.objects.filter(test__engagement__product=self,
                                         active=True, mitigated__isnull=True,
                                         false_p=False, verified=True,
                                         severity="Low",
                                         date__range=[start_date,
                                                      end_date]).count()
            return {'Critical': critical,
                    'High': high,
                    'Medium': medium,
                    'Low': low,
                    'Total': (critical + high + medium + low)}

    def reported_findings(self, start_date=None, end_date=None):
        if start_date is None or end_date is None:
            return {}
        else:
            critical = Finding.objects.filter(test__engagement__product=self,
                                              false_p=False, verified=True,
                                              severity="Critical",
                                              date__range=[start_date,
                                                           end_date])
            high = Finding.objects.filter(test__engagement__product=self,
                                          active=True, mitigated__isnull=True,
                                          false_p=False, verified=True,
                                          severity="High",
                                          date__range=[start_date,
                                                       end_date])
            medium = Finding.objects.filter(test__engagement__product=self,
                                            active=True,
                                            mitigated__isnull=True,
                                            false_p=False, verified=True,
                                            severity="Medium",
                                            date__range=[start_date,
                                                         end_date])
            low = Finding.objects.filter(test__engagement__product=self,
                                         active=True, mitigated__isnull=True,
                                         false_p=False, verified=True,
                                         severity="Low",
                                         date__range=[start_date,
                                                      end_date])
            return ((len(critical) + len(high) + len(medium) + len(low)),
                    [critical,
                     high,
    