# Path: dash/orgs/models.py
# class Invitation(SmartModel):
#     org = models.ForeignKey(
#         Org,
#         on_delete=models.PROTECT,
#         verbose_name=_("Org"),
#         related_name="invitations",
#         help_text=_("The organization to which the account is invited to view"),
#     )
# 
#     email = models.EmailField(
#         verbose_name=_("Email"), help_text=_("The email to which we send the invitation of the viewer")
#     )
# 
#     secret = models.CharField(
#         verbose_name=_("Secret"),
#         max_length=64,
#         unique=True,
#         help_text=_("a unique code associated with this invitation"),
#     )
# 
#     user_group = models.CharField(max_length=1, choices=USER_GROUPS, default="V", verbose_name=_("User Role"))
# 
#     def save(self, *args, **kwargs):
#         if not self.secret:
#             secret = Invitation.generate_random_string(64)
# 
#             while Invitation.objects.filter(secret=secret):
#                 secret = Invitation.generate_random_string(64)
# 
#             self.secret = secret
# 
#         return super(Invitation, self).save(*args, **kwargs)
# 
#     @classmethod
#     def generate_random_string(cls, length):
#         """
#         Generatesa a [length] characters alpha numeric secret
#         """
#         # avoid things that could be mistaken ex: 'I' and '1'
#         letters = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"
#         return "".join([random.choice(letters) for _ in range(length)])
# 
#     def send_invitation(self):
#         from .tasks import send_invitation_email_task
# 
#         send_invitation_email_task(self.id)
# 
#     def send_email(self):
#         # no=op if we do not know the email
#         if not self.email:
#             return
# 
#         subject = _("%s Invitation") % self.org.name
#         template = "orgs/email/invitation_email"
#         to_email = self.email
# 
#         context = dict(org=self.org, now=timezone.now(), invitation=self)
#         context["subject"] = subject
#         context["host"] = self.org.build_host_link()
# 
#         send_dash_email(to_email, subject, template, context)
# 
# class TaskState(models.Model):
#     """
#     Holds org specific state for a scheduled task
#     """
# 
#     LOCK_KEY = "org-task-lock:%s:%s"
# 
#     org = models.ForeignKey(Org, on_delete=models.PROTECT, related_name="task_states")
# 
#     task_key = models.CharField(max_length=32)
# 
#     started_on = models.DateTimeField(null=True)
# 
#     ended_on = models.DateTimeField(null=True)
# 
#     last_successfully_started_on = models.DateTimeField(null=True)
# 
#     last_results = models.TextField(null=True)
# 
#     is_failing = models.BooleanField(default=False)
# 
#     is_disabled = models.BooleanField(default=False)
# 
#     @classmethod
#     def get_or_create(cls, org, task_key):
#         existing = cls.objects.filter(org=org, task_key=task_key).first()
#         if existing:
#             return existing
# 
#         return cls.objects.create(org=org, task_key=task_key)
# 
#     @classmethod
#     def get_lock_key(cls, org, task_key):
#         return cls.LOCK_KEY % (org.id, task_key)
# 
#     @classmethod
#     def get_failing(cls):
#         return cls.objects.filter(org__is_active=True, is_failing=True)
# 
#     def is_running(self):
#         return self.started_on and not self.ended_on
# 
#     def has_ever_run(self):
#         return self.started_on is not None
# 
#     def get_last_results(self):
#         return json.loads(self.last_results) if self.last_results else None
# 
#     def get_time_taken(self):
#         until = self.ended_on if self.ended_on else timezone.now()
#         return (until - self.started_on).total_seconds()
# 
#     class Meta:
#         unique_together = ("org", "task_key")


import inspect
import json
import logging
from functools import wraps
from django_redis import get_redis_connection
from django.apps import apps
from django.utils import timezone
from celery import shared_task, signature
from .models import Invitation, TaskState





ORG_TASK_LOCK_KEY = "org-task-lock:%s:%s"

logger = logging.getLogger(__name__)


@shared_task(track_started=True, name="send_invitation_email_task")
def send_invitation_email_task(invitation_id):

# Path: dash/orgs/models.py
# class Invitation(SmartModel):
#     org = models.ForeignKey(
#         Org,
#         on_delete=models.PROTECT,
#         verbose_name=_("Org"),
#         related_name="invitations",
#         help_text=_("The organization to which the account is invited to view"),
#     )
# 
#     email = models.EmailField(
#         verbose_name=_("Email"), help_text=_("The email to which we send the invitation of the viewer")
#     )
# 
#     secret = models.CharField(
#         verbose_name=_("Secret"),
#         max_length=64,
#         unique=True,
#         help_text=_("a unique code associated with this invitation"),
#     )
# 
#     user_group = models.CharField(max_length=1, choices=USER_GROUPS, default="V", verbose_name=_("User Role"))
# 
#     def save(self, *args, **kwargs):
#         if not self.secret:
#             secret = Invitation.generate_random_string(64)
# 
#             while Invitation.objects.filter(secret=secret):
#                 secret = Invitation.generate_random_string(64)
# 
#             self.secret = secret
# 
#         return super(Invitation, self).save(*args, **kwargs)
# 
#     @classmethod
#     def generate_random_string(cls, length):
#         """
#         Generatesa a [length] characters alpha numeric secret
#         """
#         # avoid things that could be mistaken ex: 'I' and '1'
#         letters = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"
#         return "".join([random.choice(letters) for _ in range(length)])
# 
#     def send_invitation(self):
#         from .tasks import send_invitation_email_task
# 
#         send_invitation_email_task(self.id)
# 
#     def send_email(self):
#         # no=op if we do not know the email
#         if not self.email:
#             return
# 
#         subject = _("%s Invitation") % self.org.name
#         template = "orgs/email/invitation_email"
#         to_email = self.email
# 
#         context = dict(org=self.org, now=timezone.now(), invitation=self)
#         context["subject"] = subject
#         context["host"] = self.org.build_host_link()
# 
#         send_dash_email(to_email, subject, template, context)
# 
# class TaskState(models.Model):
#     """
#     Holds org specific state for a scheduled task
#     """
# 
#     LOCK_KEY = "org-task-lock:%s:%s"
# 
#     org = models.ForeignKey(Org, on_delete=models.PROTECT, related_name="task_states")
# 
#     task_key = models.CharField(max_length=32)
# 
#     started_on = models.DateTimeField(null=True)
# 
#     ended_on = models.DateTimeField(null=True)
# 
#     last_successfully_started_on = models.DateTimeField(null=True)
# 
#     last_results = models.TextField(null=True)
# 
#     is_failing = models.BooleanField(default=False)
# 
#     is_disabled = models.BooleanField(default=False)
# 
#     @classmethod
#     def get_or_create(cls, org, task_key):
#         existing = cls.objects.filter(org=org, task_key=task_key).first()
#         if existing:
#             return existing
# 
#         return cls.objects.create(org=org, task_key=task_key)
# 
#     @classmethod
#     def get_lock_key(cls, org, task_key):
#         return cls.LOCK_KEY % (org.id, task_key)
# 
#     @classmethod
#     def get_failing(cls):
#         return cls.objects.filter(org__is_active=True, is_failing=True)
# 
#     def is_running(self):
#         return self.started_on and not self.ended_on
# 
#     def has_ever_run(self):
#         return self.started_on is not None
# 
#     def get_last_results(self):
#         return json.loads(self.last_results) if self.last_results else None
# 
#     def get_time_taken(self):
#         until = self.ended_on if self.ended_on else timezone.now()
#         return (until - self.started_on).total_seconds()
# 
#     class Meta:
#         unique_together = ("org", "task_key")


# Path: dash/orgs/tasks.py
import inspect
import json
import logging
from functools import wraps
from django_redis import get_redis_connection
from django.apps import apps
from django.utils import timezone
from celery import shared_task, signature
from .models import Invitation, TaskState






ORG_TASK_LOCK_KEY = "org-task-lock:%s:%s"

logger = logging.getLogger(__name__)


@shared_task(track_started=True, name="send_invitation_email_task")
def send_invitation_email_task(invitation_id):

    invitation = Invitation.objects.get(pk=invitation_id)