import logging

from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.executors.pool import ProcessPoolExecutor, ThreadPoolExecutor
from django_apscheduler.jobstores import register_events, register_job
from django_apscheduler.models import DjangoJobExecution


from apscheduler.triggers.cron import CronTrigger

from django.conf import settings

from .models import *
from .flight_planning_algorithm import *
from api.functionsNeuralNetworks.appleDetectionModel import *
from api.functionsNeuralNetworks.pearDetectionModel import *
from api.functionsNeuralNetworks.scabDetectionModel import *


def autonomous_flights():
  blocks = Blocks.objects.all()
  for block in blocks:
    if block.is_autonomous:
       autonomous_flight_time_planning(block.id)
  pass

def reshedule_missed_flights():
  late_time = datetime.datetime.now() + datetime.timedelta(minutes=30)
  flights = Flights.objects.filter(status=1)
  for checked_flight in flights:
    if checked_flight.start_date < late_time.replace(tzinfo=datetime.timezone.utc):
      reschedule_flight(checked_flight.id)
  pass

def delete_old_job_executions(max_age=604_800):
  """
  This job deletes APScheduler job execution entries older than `max_age` from the database.
  It helps to prevent the database from filling up with old historical records that are no
  longer useful.
  
  :param max_age: The maximum length of time to retain historical job execution records.
                  Defaults to 7 days.
  """
  DjangoJobExecution.objects.delete_old_job_executions(max_age)

def machine_learning():
  for block in Blocks.objects.all():
    if block.cultivar_id == 1:
      for tree in Trees.objects.filter(block_id=block.id):
        for photos in Photos.objects.filter(tree_id=tree.id):
          appleDetectionModel(photos)
      pass
    elif block.cultivar_id == 2:
      for tree in Trees.objects.filter(block_id=block.id):
        for photos in Photos.objects.filter(tree_id=tree.id):
          pearDetectionModel(photos)
      pass
    elif block.cultivar_id == 3:
      # not yet implemented
      pass
  pass

def simulate_working_drones():
  enterprises_simulated = Enterprises.objects.filter(is_simulated=True)
  for enterprise in enterprises_simulated:
    devices = Devices.objects.filter(enterprise_id=enterprise.id)
    for device in devices:
      if Drones.objects.filter(block_id = device.block.id).exists():
        missions = Missions.objects.filter(block_id = device.block.id, status=0)
        for mission in missions:
          flights = Flights.objects.filter(mission_id = mission.id, status=1)
          for flight in flights:
            # check start time of flights and if it is time to start is lower than now start flight]°
            if flight.start_date < datetime.datetime.now().replace(tzinfo=datetime.timezone.utc):
              flight.start_date = datetime.datetime.now().replace(tzinfo=datetime.timezone.utc)
              flight.status = 2
              flight.save()
              time.sleep(60) # the flight is gonna take 2 minutes
              flight.status = 3
              flight.end_date = datetime.datetime.now().replace(tzinfo=datetime.timezone.utc)
              flight.save()
              # flight ended
              # example photo 
          example_photo_url = 'https://www.allrecipes.com/thmb/YusIoqehzkB6YjCPzd9hhFswddw=/750x0/filters:no_upscale():max_bytes(150000):strip_icc():format(webp)/GettyImages-144476015-3dcb5c523152449caf604e8bc551f5a8.jpg'
          block = Blocks.objects.get(id=device.block.id)
          trees = Trees.objects.filter(block_id=block.id)
          #for tree in trees:
          #  photo = Photos.objects.create(
          #    image_uri = example_photo_url,
          #    tree_id = tree.id,
          #    flight_id = flight.id
          #  )
          #  photo.save()
            # photo saved
          if (Flights.objects.filter(mission_id = mission.id, status=3).count() == Flights.objects.filter(mission_id = mission.id).count()):
            mission.status = 1
            mission.closed_date = datetime.datetime.now().replace(tzinfo=datetime.timezone.utc)
            mission.save()
            # mission ended



            
      else:
        pass
  pass

def delete_invite_codes():
  """
  This job deletes invite codes older than 24 hours from the database.
  """
  invites = TemporaryUser.objects.all()
  for invite in invites:
    if invite.invite_time < datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=datetime.timezone.utc) - datetime.timedelta(days=1):
      # send an email to the user that the invite code has expired
      email = invite.email
      from django.core.mail import send_mail
      subject = 'Reģistrācijas koda termiņš ir beidzies'
      message = 'Jūsu reģistrācijas koda termiņš ir beidzies. Lūdzu, sazinieties ar sava uzņēmuma īpašnieku, lai saņemtu jaunu saiti.'
      email_from = settings.EMAIL_HOST_USER
      recipient_list = [email, ]
      send_mail(subject, message, email_from, recipient_list)

      invite.delete()
    







logger = logging.getLogger(__name__)

# Create scheduler to run in a thread inside the application process
scheduler = BackgroundScheduler(settings.SCHEDULER_CONFIG, timezone=settings.TIME_ZONE)

def start():
    if settings.DEBUG:
      	# Hook into the apscheduler logger
        logging.basicConfig()
        logging.getLogger('apscheduler').setLevel(logging.DEBUG)

    # Adding this job here instead of to crons.
    # This will do the following:
    # - Add a scheduled job to the job store on application initialization
    # - The job will execute a model class method at midnight each day
    # - replace_existing in combination with the unique ID prevents duplicate copies of the job
    scheduler.add_job(
      reshedule_missed_flights,
      trigger=CronTrigger(minute="*/10"), # Every minute
      id="reshedule_missed_flights",  # The `id` assigned to each job MUST be unique
      max_instances=1,
      replace_existing=True,
    )
    logger.info("Added job 'reshedule_missed_flights'.")

    scheduler.add_job(
      delete_old_job_executions,
      trigger=CronTrigger(
        day_of_week="mon", hour="00", minute="00"
      ),  # Midnight on Monday, before start of the next work week.
      id="delete_old_job_executions",
      max_instances=1,
      replace_existing=True,
    )
    logger.info(
      "Added weekly job: 'delete_old_job_executions'."
    )

    scheduler.add_job(
      delete_invite_codes,
      trigger=CronTrigger(
      second="*/5"
      ),  # Every 5 seconds
      id="delete_invite_codes",
      max_instances=1,
      replace_existing=True,
    )

    # Add the scheduled jobs to the Django admin interface
    register_events(scheduler)

    scheduler.start()